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_errors.h"
48 #include "bgpd/bgp_aspath.h"
49 #include "bgpd/bgp_regex.h"
50 #include "bgpd/bgp_community.h"
51 #include "bgpd/bgp_ecommunity.h"
52 #include "bgpd/bgp_lcommunity.h"
53 #include "bgpd/bgp_clist.h"
54 #include "bgpd/bgp_packet.h"
55 #include "bgpd/bgp_filter.h"
56 #include "bgpd/bgp_fsm.h"
57 #include "bgpd/bgp_mplsvpn.h"
58 #include "bgpd/bgp_nexthop.h"
59 #include "bgpd/bgp_damp.h"
60 #include "bgpd/bgp_advertise.h"
61 #include "bgpd/bgp_zebra.h"
62 #include "bgpd/bgp_vty.h"
63 #include "bgpd/bgp_mpath.h"
64 #include "bgpd/bgp_nht.h"
65 #include "bgpd/bgp_updgrp.h"
66 #include "bgpd/bgp_label.h"
69 #include "bgpd/rfapi/rfapi_backend.h"
70 #include "bgpd/rfapi/vnc_import_bgp.h"
71 #include "bgpd/rfapi/vnc_export_bgp.h"
73 #include "bgpd/bgp_encap_types.h"
74 #include "bgpd/bgp_encap_tlv.h"
75 #include "bgpd/bgp_evpn.h"
76 #include "bgpd/bgp_evpn_vty.h"
77 #include "bgpd/bgp_flowspec.h"
78 #include "bgpd/bgp_flowspec_util.h"
79 #include "bgpd/bgp_pbr.h"
81 #ifndef VTYSH_EXTRACT_PL
82 #include "bgpd/bgp_route_clippy.c"
85 /* Extern from bgp_dump.c */
86 extern const char *bgp_origin_str
[];
87 extern const char *bgp_origin_long_str
[];
90 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
91 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
92 static const struct message bgp_pmsi_tnltype_str
[] = {
93 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
94 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
95 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
96 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
97 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
98 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
99 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
100 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
104 #define VRFID_NONE_STR "-"
106 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
107 safi_t safi
, struct prefix
*p
,
108 struct prefix_rd
*prd
)
111 struct bgp_node
*prn
= NULL
;
117 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
118 || (safi
== SAFI_EVPN
)) {
119 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
121 if (prn
->info
== NULL
)
122 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
124 bgp_unlock_node(prn
);
128 rn
= bgp_node_get(table
, p
);
130 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
131 || (safi
== SAFI_EVPN
))
137 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
138 safi_t safi
, struct prefix
*p
,
139 struct prefix_rd
*prd
)
142 struct bgp_node
*prn
= NULL
;
147 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
148 || (safi
== SAFI_EVPN
)) {
149 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
153 if (prn
->info
== NULL
) {
154 bgp_unlock_node(prn
);
161 rn
= bgp_node_lookup(table
, p
);
166 /* Allocate bgp_info_extra */
167 static struct bgp_info_extra
*bgp_info_extra_new(void)
169 struct bgp_info_extra
*new;
170 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
171 new->label
[0] = MPLS_INVALID_LABEL
;
176 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
178 struct bgp_info_extra
*e
;
180 if (!extra
|| !*extra
)
185 bgp_damp_info_free(e
->damp_info
, 0);
189 struct bgp_info
*bi
= (struct bgp_info
*)e
->parent
;
192 bi
->net
= bgp_unlock_node((struct bgp_node
*)bi
->net
);
193 bgp_info_unlock(e
->parent
);
198 bgp_unlock(e
->bgp_orig
);
200 if ((*extra
)->bgp_fs_pbr
)
201 list_delete_all_node((*extra
)->bgp_fs_pbr
);
202 (*extra
)->bgp_fs_pbr
= NULL
;
203 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
208 /* Get bgp_info extra information for the given bgp_info, lazy allocated
211 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
214 ri
->extra
= bgp_info_extra_new();
218 /* Allocate new bgp info structure. */
219 struct bgp_info
*bgp_info_new(void)
221 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
224 /* Free bgp route information. */
225 static void bgp_info_free(struct bgp_info
*binfo
)
228 bgp_attr_unintern(&binfo
->attr
);
230 bgp_unlink_nexthop(binfo
);
231 bgp_info_extra_free(&binfo
->extra
);
232 bgp_info_mpath_free(&binfo
->mpath
);
234 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
236 XFREE(MTYPE_BGP_ROUTE
, binfo
);
239 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
245 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
247 assert(binfo
&& binfo
->lock
> 0);
250 if (binfo
->lock
== 0) {
252 zlog_debug ("%s: unlocked and freeing", __func__
);
253 zlog_backtrace (LOG_DEBUG
);
255 bgp_info_free(binfo
);
260 if (binfo
->lock
== 1)
262 zlog_debug ("%s: unlocked to 1", __func__
);
263 zlog_backtrace (LOG_DEBUG
);
270 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
272 struct bgp_info
*top
;
284 peer_lock(ri
->peer
); /* bgp_info peer reference */
287 /* Do the actual removal of info from RIB, for use by bgp_process
288 completion callback *only* */
289 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
292 ri
->next
->prev
= ri
->prev
;
294 ri
->prev
->next
= ri
->next
;
298 bgp_info_mpath_dequeue(ri
);
303 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
305 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
306 /* set of previous already took care of pcount */
307 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
310 /* undo the effects of a previous call to bgp_info_delete; typically
311 called when a route is deleted and then quickly re-added before the
312 deletion has been processed */
313 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
315 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
316 /* unset of previous already took care of pcount */
317 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
320 /* Adjust pcount as required */
321 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
323 struct bgp_table
*table
;
325 assert(rn
&& bgp_node_table(rn
));
326 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
328 table
= bgp_node_table(rn
);
330 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
333 if (!BGP_INFO_COUNTABLE(ri
)
334 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
336 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
338 /* slight hack, but more robust against errors. */
339 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
340 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
343 "%s: Asked to decrement 0 prefix count for peer %s",
344 __func__
, ri
->peer
->host
);
345 zlog_backtrace(LOG_WARNING
);
346 zlog_warn("%s: Please report to Quagga bugzilla",
349 } else if (BGP_INFO_COUNTABLE(ri
)
350 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
351 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
352 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
356 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
358 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
361 /* Set/unset bgp_info flags, adjusting any other state as needed.
362 * This is here primarily to keep prefix-count in check.
364 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, uint32_t flag
)
366 SET_FLAG(ri
->flags
, flag
);
368 /* early bath if we know it's not a flag that changes countability state
370 if (!CHECK_FLAG(flag
,
371 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
374 bgp_pcount_adjust(rn
, ri
);
377 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
380 UNSET_FLAG(ri
->flags
, flag
);
382 /* early bath if we know it's not a flag that changes countability state
384 if (!CHECK_FLAG(flag
,
385 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
388 bgp_pcount_adjust(rn
, ri
);
391 /* Get MED value. If MED value is missing and "bgp bestpath
392 missing-as-worst" is specified, treat it as the worst value. */
393 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
395 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
398 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
405 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
407 if (ri
->addpath_rx_id
)
408 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
411 sprintf(buf
, "path %s", ri
->peer
->host
);
414 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
416 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
417 struct bgp_info
*exist
, int *paths_eq
,
418 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
419 char *pfx_buf
, afi_t afi
, safi_t safi
)
421 struct attr
*newattr
, *existattr
;
422 bgp_peer_sort_t new_sort
;
423 bgp_peer_sort_t exist_sort
;
429 uint32_t exist_weight
;
430 uint32_t newm
, existm
;
431 struct in_addr new_id
;
432 struct in_addr exist_id
;
435 int internal_as_route
;
438 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
439 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
441 uint32_t exist_mm_seq
;
448 zlog_debug("%s: new is NULL", pfx_buf
);
453 bgp_info_path_with_addpath_rx_str(new, new_buf
);
457 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
463 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
464 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
465 pfx_buf
, new_buf
, new->flags
, exist_buf
,
470 existattr
= exist
->attr
;
472 /* For EVPN routes, we cannot just go by local vs remote, we have to
473 * look at the MAC mobility sequence number, if present.
475 if (safi
== SAFI_EVPN
) {
476 /* This is an error condition described in RFC 7432 Section
478 * states that in this scenario "the PE MUST alert the operator"
480 * does not state what other action to take. In order to provide
482 * consistency in this scenario we are going to prefer the path
486 if (newattr
->sticky
!= existattr
->sticky
) {
488 prefix2str(&new->net
->p
, pfx_buf
,
490 * PREFIX2STR_BUFFER
);
491 bgp_info_path_with_addpath_rx_str(new, new_buf
);
492 bgp_info_path_with_addpath_rx_str(exist
,
496 if (newattr
->sticky
&& !existattr
->sticky
) {
499 "%s: %s wins over %s due to sticky MAC flag",
500 pfx_buf
, new_buf
, exist_buf
);
504 if (!newattr
->sticky
&& existattr
->sticky
) {
507 "%s: %s loses to %s due to sticky MAC flag",
508 pfx_buf
, new_buf
, exist_buf
);
513 new_mm_seq
= mac_mobility_seqnum(newattr
);
514 exist_mm_seq
= mac_mobility_seqnum(existattr
);
516 if (new_mm_seq
> exist_mm_seq
) {
519 "%s: %s wins over %s due to MM seq %u > %u",
520 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
525 if (new_mm_seq
< exist_mm_seq
) {
528 "%s: %s loses to %s due to MM seq %u < %u",
529 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
535 /* 1. Weight check. */
536 new_weight
= newattr
->weight
;
537 exist_weight
= existattr
->weight
;
539 if (new_weight
> exist_weight
) {
541 zlog_debug("%s: %s wins over %s due to weight %d > %d",
542 pfx_buf
, new_buf
, exist_buf
, new_weight
,
547 if (new_weight
< exist_weight
) {
549 zlog_debug("%s: %s loses to %s due to weight %d < %d",
550 pfx_buf
, new_buf
, exist_buf
, new_weight
,
555 /* 2. Local preference check. */
556 new_pref
= exist_pref
= bgp
->default_local_pref
;
558 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
559 new_pref
= newattr
->local_pref
;
560 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
561 exist_pref
= existattr
->local_pref
;
563 if (new_pref
> exist_pref
) {
566 "%s: %s wins over %s due to localpref %d > %d",
567 pfx_buf
, new_buf
, exist_buf
, new_pref
,
572 if (new_pref
< exist_pref
) {
575 "%s: %s loses to %s due to localpref %d < %d",
576 pfx_buf
, new_buf
, exist_buf
, new_pref
,
581 /* 3. Local route check. We prefer:
583 * - BGP_ROUTE_AGGREGATE
584 * - BGP_ROUTE_REDISTRIBUTE
586 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
587 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
590 "%s: %s wins over %s due to preferred BGP_ROUTE type",
591 pfx_buf
, new_buf
, exist_buf
);
595 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
596 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
599 "%s: %s loses to %s due to preferred BGP_ROUTE type",
600 pfx_buf
, new_buf
, exist_buf
);
604 /* 4. AS path length check. */
605 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
606 int exist_hops
= aspath_count_hops(existattr
->aspath
);
607 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
609 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
612 aspath_hops
= aspath_count_hops(newattr
->aspath
);
613 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
615 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
618 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
619 pfx_buf
, new_buf
, exist_buf
,
621 (exist_hops
+ exist_confeds
));
625 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
628 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
629 pfx_buf
, new_buf
, exist_buf
,
631 (exist_hops
+ exist_confeds
));
635 int newhops
= aspath_count_hops(newattr
->aspath
);
637 if (newhops
< exist_hops
) {
640 "%s: %s wins over %s due to aspath hopcount %d < %d",
641 pfx_buf
, new_buf
, exist_buf
,
642 newhops
, exist_hops
);
646 if (newhops
> exist_hops
) {
649 "%s: %s loses to %s due to aspath hopcount %d > %d",
650 pfx_buf
, new_buf
, exist_buf
,
651 newhops
, exist_hops
);
657 /* 5. Origin check. */
658 if (newattr
->origin
< existattr
->origin
) {
660 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
661 pfx_buf
, new_buf
, exist_buf
,
662 bgp_origin_long_str
[newattr
->origin
],
663 bgp_origin_long_str
[existattr
->origin
]);
667 if (newattr
->origin
> existattr
->origin
) {
669 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
670 pfx_buf
, new_buf
, exist_buf
,
671 bgp_origin_long_str
[newattr
->origin
],
672 bgp_origin_long_str
[existattr
->origin
]);
677 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
678 && aspath_count_hops(existattr
->aspath
) == 0);
679 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
680 && aspath_count_confeds(existattr
->aspath
) > 0
681 && aspath_count_hops(newattr
->aspath
) == 0
682 && aspath_count_hops(existattr
->aspath
) == 0);
684 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
685 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
686 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
687 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
688 || internal_as_route
) {
689 new_med
= bgp_med_value(new->attr
, bgp
);
690 exist_med
= bgp_med_value(exist
->attr
, bgp
);
692 if (new_med
< exist_med
) {
695 "%s: %s wins over %s due to MED %d < %d",
696 pfx_buf
, new_buf
, exist_buf
, new_med
,
701 if (new_med
> exist_med
) {
704 "%s: %s loses to %s due to MED %d > %d",
705 pfx_buf
, new_buf
, exist_buf
, new_med
,
711 /* 7. Peer type check. */
712 new_sort
= new->peer
->sort
;
713 exist_sort
= exist
->peer
->sort
;
715 if (new_sort
== BGP_PEER_EBGP
716 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
719 "%s: %s wins over %s due to eBGP peer > iBGP peer",
720 pfx_buf
, new_buf
, exist_buf
);
724 if (exist_sort
== BGP_PEER_EBGP
725 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
728 "%s: %s loses to %s due to iBGP peer < eBGP peer",
729 pfx_buf
, new_buf
, exist_buf
);
733 /* 8. IGP metric check. */
737 newm
= new->extra
->igpmetric
;
739 existm
= exist
->extra
->igpmetric
;
744 "%s: %s wins over %s due to IGP metric %d < %d",
745 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
752 "%s: %s loses to %s due to IGP metric %d > %d",
753 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
757 /* 9. Same IGP metric. Compare the cluster list length as
758 representative of IGP hops metric. Rewrite the metric value
759 pair (newm, existm) with the cluster list length. Prefer the
760 path with smaller cluster list length. */
761 if (newm
== existm
) {
762 if (peer_sort(new->peer
) == BGP_PEER_IBGP
763 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
764 && (mpath_cfg
== NULL
766 mpath_cfg
->ibgp_flags
,
767 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
768 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
769 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
774 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
775 pfx_buf
, new_buf
, exist_buf
,
783 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
784 pfx_buf
, new_buf
, exist_buf
,
791 /* 10. confed-external vs. confed-internal */
792 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
793 if (new_sort
== BGP_PEER_CONFED
794 && exist_sort
== BGP_PEER_IBGP
) {
797 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
798 pfx_buf
, new_buf
, exist_buf
);
802 if (exist_sort
== BGP_PEER_CONFED
803 && new_sort
== BGP_PEER_IBGP
) {
806 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
807 pfx_buf
, new_buf
, exist_buf
);
812 /* 11. Maximum path check. */
813 if (newm
== existm
) {
814 /* If one path has a label but the other does not, do not treat
815 * them as equals for multipath
817 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
819 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
822 "%s: %s and %s cannot be multipath, one has a label while the other does not",
823 pfx_buf
, new_buf
, exist_buf
);
824 } else if (bgp_flag_check(bgp
,
825 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
828 * For the two paths, all comparison steps till IGP
830 * have succeeded - including AS_PATH hop count. Since
832 * bestpath as-path multipath-relax' knob is on, we
834 * an exact match of AS_PATH. Thus, mark the paths are
836 * That will trigger both these paths to get into the
844 "%s: %s and %s are equal via multipath-relax",
845 pfx_buf
, new_buf
, exist_buf
);
846 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
847 if (aspath_cmp(new->attr
->aspath
,
848 exist
->attr
->aspath
)) {
853 "%s: %s and %s are equal via matching aspaths",
854 pfx_buf
, new_buf
, exist_buf
);
856 } else if (new->peer
->as
== exist
->peer
->as
) {
861 "%s: %s and %s are equal via same remote-as",
862 pfx_buf
, new_buf
, exist_buf
);
866 * TODO: If unequal cost ibgp multipath is enabled we can
867 * mark the paths as equal here instead of returning
872 "%s: %s wins over %s after IGP metric comparison",
873 pfx_buf
, new_buf
, exist_buf
);
876 "%s: %s loses to %s after IGP metric comparison",
877 pfx_buf
, new_buf
, exist_buf
);
882 /* 12. If both paths are external, prefer the path that was received
883 first (the oldest one). This step minimizes route-flap, since a
884 newer path won't displace an older one, even if it was the
885 preferred route based on the additional decision criteria below. */
886 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
887 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
888 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
891 "%s: %s wins over %s due to oldest external",
892 pfx_buf
, new_buf
, exist_buf
);
896 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
899 "%s: %s loses to %s due to oldest external",
900 pfx_buf
, new_buf
, exist_buf
);
905 /* 13. Router-ID comparision. */
906 /* If one of the paths is "stale", the corresponding peer router-id will
907 * be 0 and would always win over the other path. If originator id is
908 * used for the comparision, it will decide which path is better.
910 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
911 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
913 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
914 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
915 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
917 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
919 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
922 "%s: %s wins over %s due to Router-ID comparison",
923 pfx_buf
, new_buf
, exist_buf
);
927 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
930 "%s: %s loses to %s due to Router-ID comparison",
931 pfx_buf
, new_buf
, exist_buf
);
935 /* 14. Cluster length comparision. */
936 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
937 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
939 if (new_cluster
< exist_cluster
) {
942 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
943 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
948 if (new_cluster
> exist_cluster
) {
951 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
952 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
957 /* 15. Neighbor address comparision. */
958 /* Do this only if neither path is "stale" as stale paths do not have
959 * valid peer information (as the connection may or may not be up).
961 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
964 "%s: %s wins over %s due to latter path being STALE",
965 pfx_buf
, new_buf
, exist_buf
);
969 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
972 "%s: %s loses to %s due to former path being STALE",
973 pfx_buf
, new_buf
, exist_buf
);
977 /* locally configured routes to advertise do not have su_remote */
978 if (new->peer
->su_remote
== NULL
)
980 if (exist
->peer
->su_remote
== NULL
)
983 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
988 "%s: %s loses to %s due to Neighor IP comparison",
989 pfx_buf
, new_buf
, exist_buf
);
996 "%s: %s wins over %s due to Neighor IP comparison",
997 pfx_buf
, new_buf
, exist_buf
);
1002 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1003 pfx_buf
, new_buf
, exist_buf
);
1008 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1009 * is preferred, or 0 if they are the same (usually will only occur if
1010 * multipath is enabled
1011 * This version is compatible with */
1012 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
1013 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
1018 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
1032 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1033 struct attr
*attr
, afi_t afi
,
1036 struct bgp_filter
*filter
;
1038 filter
= &peer
->filter
[afi
][safi
];
1040 #define FILTER_EXIST_WARN(F, f, filter) \
1041 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1042 zlog_warn("%s: Could not find configured input %s-list %s!", \
1043 peer->host, #f, F##_IN_NAME(filter));
1045 if (DISTRIBUTE_IN_NAME(filter
)) {
1046 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1048 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1052 if (PREFIX_LIST_IN_NAME(filter
)) {
1053 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1055 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1059 if (FILTER_LIST_IN_NAME(filter
)) {
1060 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1062 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1067 return FILTER_PERMIT
;
1068 #undef FILTER_EXIST_WARN
1071 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1072 struct attr
*attr
, afi_t afi
,
1075 struct bgp_filter
*filter
;
1077 filter
= &peer
->filter
[afi
][safi
];
1079 #define FILTER_EXIST_WARN(F, f, filter) \
1080 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1081 zlog_warn("%s: Could not find configured output %s-list %s!", \
1082 peer->host, #f, F##_OUT_NAME(filter));
1084 if (DISTRIBUTE_OUT_NAME(filter
)) {
1085 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1087 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1091 if (PREFIX_LIST_OUT_NAME(filter
)) {
1092 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1094 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1099 if (FILTER_LIST_OUT_NAME(filter
)) {
1100 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1102 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1107 return FILTER_PERMIT
;
1108 #undef FILTER_EXIST_WARN
1111 /* If community attribute includes no_export then return 1. */
1112 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1114 if (attr
->community
) {
1115 /* NO_ADVERTISE check. */
1116 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1119 /* NO_EXPORT check. */
1120 if (peer
->sort
== BGP_PEER_EBGP
1121 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1124 /* NO_EXPORT_SUBCONFED check. */
1125 if (peer
->sort
== BGP_PEER_EBGP
1126 || peer
->sort
== BGP_PEER_CONFED
)
1127 if (community_include(attr
->community
,
1128 COMMUNITY_NO_EXPORT_SUBCONFED
))
1134 /* Route reflection loop check. */
1135 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1137 struct in_addr cluster_id
;
1139 if (attr
->cluster
) {
1140 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1141 cluster_id
= peer
->bgp
->cluster_id
;
1143 cluster_id
= peer
->bgp
->router_id
;
1145 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1151 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1152 struct attr
*attr
, afi_t afi
, safi_t safi
,
1153 const char *rmap_name
)
1155 struct bgp_filter
*filter
;
1156 struct bgp_info info
;
1157 route_map_result_t ret
;
1158 struct route_map
*rmap
= NULL
;
1160 filter
= &peer
->filter
[afi
][safi
];
1162 /* Apply default weight value. */
1163 if (peer
->weight
[afi
][safi
])
1164 attr
->weight
= peer
->weight
[afi
][safi
];
1167 rmap
= route_map_lookup_by_name(rmap_name
);
1172 if (ROUTE_MAP_IN_NAME(filter
)) {
1173 rmap
= ROUTE_MAP_IN(filter
);
1180 /* Route map apply. */
1182 memset(&info
, 0, sizeof(struct bgp_info
));
1183 /* Duplicate current value to new strucutre for modification. */
1187 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1189 /* Apply BGP route map to the attribute. */
1190 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1192 peer
->rmap_type
= 0;
1194 if (ret
== RMAP_DENYMATCH
)
1200 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1201 struct attr
*attr
, afi_t afi
, safi_t safi
,
1202 const char *rmap_name
)
1204 struct bgp_info info
;
1205 route_map_result_t ret
;
1206 struct route_map
*rmap
= NULL
;
1210 * So if we get to this point and have no rmap_name
1211 * we want to just show the output as it currently
1217 /* Apply default weight value. */
1218 if (peer
->weight
[afi
][safi
])
1219 attr
->weight
= peer
->weight
[afi
][safi
];
1221 rmap
= route_map_lookup_by_name(rmap_name
);
1224 * If we have a route map name and we do not find
1225 * the routemap that means we have an implicit
1231 memset(&info
, 0, sizeof(struct bgp_info
));
1232 /* Route map apply. */
1233 /* Duplicate current value to new strucutre for modification. */
1237 rmap_type
= peer
->rmap_type
;
1238 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1240 /* Apply BGP route map to the attribute. */
1241 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1243 peer
->rmap_type
= rmap_type
;
1245 if (ret
== RMAP_DENYMATCH
)
1247 * caller has multiple error paths with bgp_attr_flush()
1254 /* If this is an EBGP peer with remove-private-AS */
1255 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1256 struct peer
*peer
, struct attr
*attr
)
1258 if (peer
->sort
== BGP_PEER_EBGP
1259 && (peer_af_flag_check(peer
, afi
, safi
,
1260 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1261 || peer_af_flag_check(peer
, afi
, safi
,
1262 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1263 || peer_af_flag_check(peer
, afi
, safi
,
1264 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1265 || peer_af_flag_check(peer
, afi
, safi
,
1266 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1267 // Take action on the entire aspath
1268 if (peer_af_flag_check(peer
, afi
, safi
,
1269 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1270 || peer_af_flag_check(peer
, afi
, safi
,
1271 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1272 if (peer_af_flag_check(
1274 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1275 attr
->aspath
= aspath_replace_private_asns(
1276 attr
->aspath
, bgp
->as
);
1278 // The entire aspath consists of private ASNs so create
1280 else if (aspath_private_as_check(attr
->aspath
))
1281 attr
->aspath
= aspath_empty_get();
1283 // There are some public and some private ASNs, remove
1286 attr
->aspath
= aspath_remove_private_asns(
1290 // 'all' was not specified so the entire aspath must be private
1292 // for us to do anything
1293 else if (aspath_private_as_check(attr
->aspath
)) {
1294 if (peer_af_flag_check(
1296 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1297 attr
->aspath
= aspath_replace_private_asns(
1298 attr
->aspath
, bgp
->as
);
1300 attr
->aspath
= aspath_empty_get();
1305 /* If this is an EBGP peer with as-override */
1306 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1307 struct peer
*peer
, struct attr
*attr
)
1309 if (peer
->sort
== BGP_PEER_EBGP
1310 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1311 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1312 attr
->aspath
= aspath_replace_specific_asn(
1313 attr
->aspath
, peer
->as
, bgp
->as
);
1317 void bgp_attr_add_gshut_community(struct attr
*attr
)
1319 struct community
*old
;
1320 struct community
*new;
1321 struct community
*merge
;
1322 struct community
*gshut
;
1324 old
= attr
->community
;
1325 gshut
= community_str2com("graceful-shutdown");
1330 merge
= community_merge(community_dup(old
), gshut
);
1332 if (old
->refcnt
== 0)
1333 community_free(old
);
1335 new = community_uniq_sort(merge
);
1336 community_free(merge
);
1338 new = community_dup(gshut
);
1341 community_free(gshut
);
1342 attr
->community
= new;
1343 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1345 /* When we add the graceful-shutdown community we must also
1346 * lower the local-preference */
1347 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1348 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1352 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1354 if (family
== AF_INET
) {
1355 attr
->nexthop
.s_addr
= 0;
1356 attr
->mp_nexthop_global_in
.s_addr
= 0;
1358 if (family
== AF_INET6
)
1359 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1360 if (family
== AF_EVPN
)
1361 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1364 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1365 struct update_subgroup
*subgrp
, struct prefix
*p
,
1368 struct bgp_filter
*filter
;
1371 struct peer
*onlypeer
;
1373 struct attr
*riattr
;
1374 char buf
[PREFIX_STRLEN
];
1380 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1382 if (DISABLE_BGP_ANNOUNCE
)
1385 afi
= SUBGRP_AFI(subgrp
);
1386 safi
= SUBGRP_SAFI(subgrp
);
1387 peer
= SUBGRP_PEER(subgrp
);
1389 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1390 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1393 filter
= &peer
->filter
[afi
][safi
];
1394 bgp
= SUBGRP_INST(subgrp
);
1395 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1398 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1399 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1400 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1403 * direct and direct_ext type routes originate internally even
1404 * though they can have peer pointers that reference other
1407 prefix2str(p
, buf
, PREFIX_STRLEN
);
1408 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1414 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1415 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1416 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1417 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1419 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1424 /* With addpath we may be asked to TX all kinds of paths so make sure
1426 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1427 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1428 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1432 /* If this is not the bestpath then check to see if there is an enabled
1434 * feature that requires us to advertise it */
1435 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1436 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1441 /* Aggregate-address suppress check. */
1442 if (ri
->extra
&& ri
->extra
->suppress
)
1443 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1448 * If we are doing VRF 2 VRF leaking via the import
1449 * statement, we want to prevent the route going
1450 * off box as that the RT and RD created are localy
1451 * significant and globaly useless.
1453 if (safi
== SAFI_MPLS_VPN
&& ri
->extra
&& ri
->extra
->num_labels
1454 && ri
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1457 /* If it's labeled safi, make sure the route has a valid label. */
1458 if (safi
== SAFI_LABELED_UNICAST
) {
1459 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1460 if (!bgp_is_valid_label(&label
)) {
1461 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1462 zlog_debug("u%" PRIu64
":s%" PRIu64
1463 " %s/%d is filtered - no label (%p)",
1464 subgrp
->update_group
->id
, subgrp
->id
,
1465 inet_ntop(p
->family
, &p
->u
.prefix
,
1466 buf
, SU_ADDRSTRLEN
),
1467 p
->prefixlen
, &label
);
1472 /* Do not send back route to sender. */
1473 if (onlypeer
&& from
== onlypeer
) {
1477 /* Do not send the default route in the BGP table if the neighbor is
1478 * configured for default-originate */
1479 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1480 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1481 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1483 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1487 /* Transparency check. */
1488 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1489 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1494 /* If community is not disabled check the no-export and local. */
1495 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1496 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1498 "subgrpannouncecheck: community filter check fail");
1502 /* If the attribute has originator-id and it is same as remote
1504 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1505 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1506 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1508 "%s [Update:SEND] %s originator-id is same as "
1511 prefix2str(p
, buf
, sizeof(buf
)));
1515 /* ORF prefix-list filter check */
1516 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1517 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1518 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1519 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1520 if (peer
->orf_plist
[afi
][safi
]) {
1521 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1523 if (bgp_debug_update(NULL
, p
,
1524 subgrp
->update_group
, 0))
1526 "%s [Update:SEND] %s is filtered via ORF",
1534 /* Output filter check. */
1535 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1536 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1537 zlog_debug("%s [Update:SEND] %s is filtered",
1538 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1542 #ifdef BGP_SEND_ASPATH_CHECK
1543 /* AS path loop check. */
1544 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1545 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1547 "%s [Update:SEND] suppress announcement to peer AS %u "
1548 "that is part of AS path.",
1549 onlypeer
->host
, onlypeer
->as
);
1552 #endif /* BGP_SEND_ASPATH_CHECK */
1554 /* If we're a CONFED we need to loop check the CONFED ID too */
1555 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1556 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1557 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1559 "%s [Update:SEND] suppress announcement to peer AS %u"
1561 peer
->host
, bgp
->confed_id
);
1566 /* Route-Reflect check. */
1567 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1572 /* IBGP reflection check. */
1573 if (reflect
&& !samepeer_safe
) {
1574 /* A route from a Client peer. */
1575 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1576 PEER_FLAG_REFLECTOR_CLIENT
)) {
1577 /* Reflect to all the Non-Client peers and also to the
1578 Client peers other than the originator. Originator
1580 is already done. So there is noting to do. */
1581 /* no bgp client-to-client reflection check. */
1582 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1583 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1584 PEER_FLAG_REFLECTOR_CLIENT
))
1587 /* A route from a Non-client peer. Reflect to all other
1589 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1590 PEER_FLAG_REFLECTOR_CLIENT
))
1595 /* For modify attribute, copy it to temporary structure. */
1596 bgp_attr_dup(attr
, riattr
);
1598 /* If local-preference is not set. */
1599 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1600 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1601 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1602 attr
->local_pref
= bgp
->default_local_pref
;
1605 /* If originator-id is not set and the route is to be reflected,
1606 set the originator id */
1608 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1609 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1610 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1613 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1615 if (peer
->sort
== BGP_PEER_EBGP
1616 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1617 if (from
!= bgp
->peer_self
&& !transparent
1618 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1619 PEER_FLAG_MED_UNCHANGED
))
1621 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1624 /* Since the nexthop attribute can vary per peer, it is not explicitly
1626 * in announce check, only certain flags and length (or number of
1628 * -- for IPv6/MP_REACH) are set here in order to guide the update
1630 * code in setting the nexthop(s) on a per peer basis in
1632 * Typically, the source nexthop in the attribute is preserved but in
1634 * scenarios where we know it will always be overwritten, we reset the
1635 * nexthop to "0" in an attempt to achieve better Update packing. An
1636 * example of this is when a prefix from each of 2 IBGP peers needs to
1638 * announced to an EBGP peer (and they have the same attributes barring
1642 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1644 #define NEXTHOP_IS_V6 \
1645 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1646 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1647 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1648 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1650 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1652 * the peer (group) is configured to receive link-local nexthop
1654 * and it is available in the prefix OR we're not reflecting the route
1656 * the peer (group) to whom we're going to announce is on a shared
1658 * and this is either a self-originated route or the peer is EBGP.
1660 if (NEXTHOP_IS_V6
) {
1661 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1662 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1663 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1664 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1665 || (!reflect
&& peer
->shared_network
1666 && (from
== bgp
->peer_self
1667 || peer
->sort
== BGP_PEER_EBGP
))) {
1668 attr
->mp_nexthop_len
=
1669 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1672 /* Clear off link-local nexthop in source, whenever it is not
1674 * ensure more prefixes share the same attribute for
1677 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1678 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1679 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1682 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1683 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1685 /* Route map & unsuppress-map apply. */
1686 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1687 struct bgp_info info
;
1688 struct bgp_info_extra dummy_info_extra
;
1689 struct attr dummy_attr
;
1691 memset(&info
, 0, sizeof(struct bgp_info
));
1696 memcpy(&dummy_info_extra
, ri
->extra
,
1697 sizeof(struct bgp_info_extra
));
1698 info
.extra
= &dummy_info_extra
;
1701 /* don't confuse inbound and outbound setting */
1702 RESET_FLAG(attr
->rmap_change_flags
);
1705 * The route reflector is not allowed to modify the attributes
1706 * of the reflected IBGP routes unless explicitly allowed.
1708 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1709 && !bgp_flag_check(bgp
,
1710 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1711 bgp_attr_dup(&dummy_attr
, attr
);
1712 info
.attr
= &dummy_attr
;
1715 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1717 if (ri
->extra
&& ri
->extra
->suppress
)
1718 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1721 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1724 peer
->rmap_type
= 0;
1726 if (ret
== RMAP_DENYMATCH
) {
1727 bgp_attr_flush(attr
);
1732 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1733 if (peer
->sort
== BGP_PEER_IBGP
1734 || peer
->sort
== BGP_PEER_CONFED
) {
1735 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1736 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1738 bgp_attr_add_gshut_community(attr
);
1742 /* After route-map has been applied, we check to see if the nexthop to
1743 * be carried in the attribute (that is used for the announcement) can
1744 * be cleared off or not. We do this in all cases where we would be
1745 * setting the nexthop to "ourselves". For IPv6, we only need to
1747 * the global nexthop here; the link-local nexthop would have been
1749 * already, and if not, it is required by the update formation code.
1750 * Also see earlier comments in this function.
1753 * If route-map has performed some operation on the nexthop or the peer
1754 * configuration says to pass it unchanged, we cannot reset the nexthop
1755 * here, so only attempt to do it if these aren't true. Note that the
1756 * route-map handler itself might have cleared the nexthop, if for
1758 * it is configured as 'peer-address'.
1760 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1761 riattr
->rmap_change_flags
)
1763 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1764 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1765 /* We can reset the nexthop, if setting (or forcing) it to
1767 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1768 PEER_FLAG_NEXTHOP_SELF
)
1769 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1770 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1772 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1773 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1774 subgroup_announce_reset_nhop(
1775 (peer_cap_enhe(peer
, afi
, safi
)
1779 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1780 /* Can also reset the nexthop if announcing to EBGP, but
1782 * no peer in the subgroup is on a shared subnet.
1783 * Note: 3rd party nexthop currently implemented for
1786 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1788 subgroup_announce_reset_nhop(
1789 (peer_cap_enhe(peer
, afi
, safi
)
1793 } else if (CHECK_FLAG(ri
->flags
, BGP_INFO_ANNC_NH_SELF
)) {
1795 * This flag is used for leaked vpn-vrf routes
1797 int family
= p
->family
;
1799 if (peer_cap_enhe(peer
, afi
, safi
))
1802 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1804 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1805 __func__
, family2str(family
));
1806 subgroup_announce_reset_nhop(family
, attr
);
1809 /* If IPv6/MP and nexthop does not have any override and happens
1811 * be a link-local address, reset it so that we don't pass along
1813 * source's link-local IPv6 address to recipients who may not be
1815 * the same interface.
1817 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1818 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1819 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1826 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1827 struct bgp_maxpaths_cfg
*mpath_cfg
,
1828 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1830 struct bgp_info
*new_select
;
1831 struct bgp_info
*old_select
;
1832 struct bgp_info
*ri
;
1833 struct bgp_info
*ri1
;
1834 struct bgp_info
*ri2
;
1835 struct bgp_info
*nextri
= NULL
;
1836 int paths_eq
, do_mpath
, debug
;
1837 struct list mp_list
;
1838 char pfx_buf
[PREFIX2STR_BUFFER
];
1839 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1841 bgp_mp_list_init(&mp_list
);
1843 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1845 debug
= bgp_debug_bestpath(&rn
->p
);
1848 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1850 /* bgp deterministic-med */
1852 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1854 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1855 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1856 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1858 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1859 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1861 if (BGP_INFO_HOLDDOWN(ri1
))
1863 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1864 if (ri1
->peer
->status
!= Established
)
1869 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1870 if (CHECK_FLAG(ri2
->flags
,
1871 BGP_INFO_DMED_CHECK
))
1873 if (BGP_INFO_HOLDDOWN(ri2
))
1876 && ri2
->peer
!= bgp
->peer_self
1879 PEER_STATUS_NSF_WAIT
))
1880 if (ri2
->peer
->status
1884 if (aspath_cmp_left(ri1
->attr
->aspath
,
1886 || aspath_cmp_left_confed(
1888 ri2
->attr
->aspath
)) {
1889 if (bgp_info_cmp(bgp
, ri2
,
1895 bgp_info_unset_flag(
1897 BGP_INFO_DMED_SELECTED
);
1903 BGP_INFO_DMED_CHECK
);
1907 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1908 bgp_info_set_flag(rn
, new_select
,
1909 BGP_INFO_DMED_SELECTED
);
1912 bgp_info_path_with_addpath_rx_str(new_select
,
1914 zlog_debug("%s: %s is the bestpath from AS %u",
1916 aspath_get_first_as(
1917 new_select
->attr
->aspath
));
1922 /* Check old selected route and new selected route. */
1925 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1927 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1930 if (BGP_INFO_HOLDDOWN(ri
)) {
1931 /* reap REMOVED routes, if needs be
1932 * selected route must stay for a while longer though
1934 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1935 && (ri
!= old_select
))
1936 bgp_info_reap(rn
, ri
);
1939 zlog_debug("%s: ri %p in holddown", __func__
,
1945 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1946 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1947 if (ri
->peer
->status
!= Established
) {
1951 "%s: ri %p non self peer %s not estab state",
1952 __func__
, ri
, ri
->peer
->host
);
1957 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1958 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1959 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1961 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1965 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1967 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1968 debug
, pfx_buf
, afi
, safi
)) {
1973 /* Now that we know which path is the bestpath see if any of the other
1975 * qualify as multipaths
1979 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1981 sprintf(path_buf
, "NONE");
1983 "%s: After path selection, newbest is %s oldbest was %s",
1985 old_select
? old_select
->peer
->host
: "NONE");
1988 if (do_mpath
&& new_select
) {
1989 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1993 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1995 if (ri
== new_select
) {
1998 "%s: %s is the bestpath, add to the multipath list",
2000 bgp_mp_list_add(&mp_list
, ri
);
2004 if (BGP_INFO_HOLDDOWN(ri
))
2007 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
2008 && !CHECK_FLAG(ri
->peer
->sflags
,
2009 PEER_STATUS_NSF_WAIT
))
2010 if (ri
->peer
->status
!= Established
)
2013 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
2016 "%s: %s has the same nexthop as the bestpath, skip it",
2021 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
2022 debug
, pfx_buf
, afi
, safi
);
2027 "%s: %s is equivalent to the bestpath, add to the multipath list",
2029 bgp_mp_list_add(&mp_list
, ri
);
2034 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
2035 bgp_info_mpath_aggregate_update(new_select
, old_select
);
2036 bgp_mp_list_clear(&mp_list
);
2038 result
->old
= old_select
;
2039 result
->new = new_select
;
2045 * A new route/change in bestpath of an existing route. Evaluate the path
2046 * for advertisement to the subgroup.
2048 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2049 struct bgp_info
*selected
,
2050 struct bgp_node
*rn
,
2051 uint32_t addpath_tx_id
)
2054 struct peer
*onlypeer
;
2060 afi
= SUBGRP_AFI(subgrp
);
2061 safi
= SUBGRP_SAFI(subgrp
);
2062 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2065 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2066 char buf_prefix
[PREFIX_STRLEN
];
2067 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2068 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2072 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2073 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2074 PEER_STATUS_ORF_WAIT_REFRESH
))
2077 memset(&attr
, 0, sizeof(struct attr
));
2078 /* It's initialized in bgp_announce_check() */
2080 /* Announcement to the subgroup. If the route is filtered withdraw it.
2083 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2084 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2086 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2087 selected
->addpath_tx_id
);
2090 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2092 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2099 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2100 * This is called at the end of route processing.
2102 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2104 struct bgp_info
*ri
;
2106 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2107 if (BGP_INFO_HOLDDOWN(ri
))
2109 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2110 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2115 * Has the route changed from the RIB's perspective? This is invoked only
2116 * if the route selection returns the same best route as earlier - to
2117 * determine if we need to update zebra or not.
2119 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2121 struct bgp_info
*mpinfo
;
2123 /* If this is multipath, check all selected paths for any nexthop
2124 * change or attribute change. Some attribute changes (e.g., community)
2125 * aren't of relevance to the RIB, but we'll update zebra to ensure
2126 * we handle the case of BGP nexthop change. This is the behavior
2127 * when the best path has an attribute change anyway.
2129 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2130 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2134 * If this is multipath, check all selected paths for any nexthop change
2136 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2137 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2138 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2139 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2143 /* Nothing has changed from the RIB's perspective. */
2147 struct bgp_process_queue
{
2149 STAILQ_HEAD(, bgp_node
) pqueue
;
2150 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2152 unsigned int queued
;
2156 * old_select = The old best path
2157 * new_select = the new best path
2159 * if (!old_select && new_select)
2160 * We are sending new information on.
2162 * if (old_select && new_select) {
2163 * if (new_select != old_select)
2164 * We have a new best path send a change
2166 * We've received a update with new attributes that needs
2170 * if (old_select && !new_select)
2171 * We have no eligible route that we can announce or the rn
2174 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2175 afi_t afi
, safi_t safi
)
2177 struct bgp_info
*new_select
;
2178 struct bgp_info
*old_select
;
2179 struct bgp_info_pair old_and_new
;
2180 char pfx_buf
[PREFIX2STR_BUFFER
];
2183 /* Is it end of initial update? (after startup) */
2185 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2186 sizeof(bgp
->update_delay_zebra_resume_time
));
2188 bgp
->main_zebra_update_hold
= 0;
2189 FOREACH_AFI_SAFI (afi
, safi
) {
2190 if (bgp_fibupd_safi(safi
))
2191 bgp_zebra_announce_table(bgp
, afi
, safi
);
2193 bgp
->main_peers_update_hold
= 0;
2195 bgp_start_routeadv(bgp
);
2199 struct prefix
*p
= &rn
->p
;
2201 debug
= bgp_debug_bestpath(&rn
->p
);
2203 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2204 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2205 afi2str(afi
), safi2str(safi
));
2208 /* Best path selection. */
2209 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2211 old_select
= old_and_new
.old
;
2212 new_select
= old_and_new
.new;
2214 /* Do we need to allocate or free labels?
2215 * Right now, since we only deal with per-prefix labels, it is not
2216 * necessary to do this upon changes to best path except if the label
2219 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2222 || bgp_label_index_differs(new_select
, old_select
)
2223 || new_select
->sub_type
!= old_select
->sub_type
) {
2224 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2225 && new_select
->attr
->flag
2227 BGP_ATTR_PREFIX_SID
)
2228 && new_select
->attr
->label_index
2229 != BGP_INVALID_LABEL_INDEX
) {
2232 BGP_NODE_REGISTERED_FOR_LABEL
))
2233 bgp_unregister_for_label(rn
);
2234 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2236 bgp_set_valid_label(&rn
->local_label
);
2238 bgp_register_for_label(rn
, new_select
);
2240 } else if (CHECK_FLAG(rn
->flags
,
2241 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2242 bgp_unregister_for_label(rn
);
2244 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2245 bgp_unregister_for_label(rn
);
2249 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2251 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2252 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2253 old_select
, new_select
);
2256 /* If best route remains the same and this is not due to user-initiated
2257 * clear, see exactly what needs to be done.
2259 if (old_select
&& old_select
== new_select
2260 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2261 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2262 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2263 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2265 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2266 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2268 if (bgp_fibupd_safi(safi
)
2269 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2271 if (new_select
->type
== ZEBRA_ROUTE_BGP
2272 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2273 || new_select
->sub_type
2274 == BGP_ROUTE_IMPORTED
))
2276 bgp_zebra_announce(rn
, p
, old_select
,
2280 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2281 bgp_zebra_clear_route_change_flags(rn
);
2283 /* If there is a change of interest to peers, reannounce the
2285 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2286 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2287 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2289 /* unicast routes must also be annouced to
2290 * labeled-unicast update-groups */
2291 if (safi
== SAFI_UNICAST
)
2292 group_announce_route(bgp
, afi
,
2293 SAFI_LABELED_UNICAST
, rn
,
2296 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2297 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2300 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2304 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2306 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2308 /* bestpath has changed; bump version */
2309 if (old_select
|| new_select
) {
2310 bgp_bump_version(rn
);
2312 if (!bgp
->t_rmap_def_originate_eval
) {
2316 update_group_refresh_default_originate_route_map
,
2317 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2318 &bgp
->t_rmap_def_originate_eval
);
2323 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2326 zlog_debug("%s: setting SELECTED flag", __func__
);
2327 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2328 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2329 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2333 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2334 if (old_select
!= new_select
) {
2336 vnc_import_bgp_exterior_del_route(bgp
, p
,
2338 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2341 vnc_import_bgp_exterior_add_route(bgp
, p
,
2343 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2349 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2351 /* unicast routes must also be annouced to labeled-unicast update-groups
2353 if (safi
== SAFI_UNICAST
)
2354 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2358 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2359 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2360 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2361 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2362 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2363 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2365 /* if this is an evpn imported type-5 prefix,
2366 * we need to withdraw the route first to clear
2367 * the nh neigh and the RMAC entry.
2370 is_route_parent_evpn(old_select
))
2371 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2373 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2375 /* Withdraw the route from the kernel. */
2376 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2377 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2378 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2379 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2381 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2385 /* advertise/withdraw type-5 routes */
2386 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2387 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2388 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2390 /* apply the route-map */
2391 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2394 ret
= route_map_apply(
2395 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2396 &rn
->p
, RMAP_BGP
, new_select
);
2397 if (ret
== RMAP_MATCH
)
2398 bgp_evpn_advertise_type5_route(
2399 bgp
, &rn
->p
, new_select
->attr
,
2402 bgp_evpn_advertise_type5_route(bgp
,
2408 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2409 (!old_select
->extra
|| !old_select
->extra
->parent
))
2410 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2413 /* Clear any route change flags. */
2414 bgp_zebra_clear_route_change_flags(rn
);
2416 /* Reap old select bgp_info, if it has been removed */
2417 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2418 bgp_info_reap(rn
, old_select
);
2420 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2424 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2426 struct bgp_process_queue
*pqnode
= data
;
2427 struct bgp
*bgp
= pqnode
->bgp
;
2428 struct bgp_table
*table
;
2429 struct bgp_node
*rn
;
2432 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2433 bgp_process_main_one(bgp
, NULL
, 0, 0);
2434 /* should always have dedicated wq call */
2435 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2439 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2440 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2441 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2442 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2443 table
= bgp_node_table(rn
);
2444 /* note, new RNs may be added as part of processing */
2445 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2447 bgp_unlock_node(rn
);
2448 bgp_table_unlock(table
);
2454 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2456 struct bgp_process_queue
*pqnode
= data
;
2458 bgp_unlock(pqnode
->bgp
);
2460 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2463 void bgp_process_queue_init(void)
2465 if (!bm
->process_main_queue
)
2466 bm
->process_main_queue
=
2467 work_queue_new(bm
->master
, "process_main_queue");
2469 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2470 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2471 bm
->process_main_queue
->spec
.max_retries
= 0;
2472 bm
->process_main_queue
->spec
.hold
= 50;
2473 /* Use a higher yield value of 50ms for main queue processing */
2474 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2477 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2479 struct bgp_process_queue
*pqnode
;
2481 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2482 sizeof(struct bgp_process_queue
));
2484 /* unlocked in bgp_processq_del */
2485 pqnode
->bgp
= bgp_lock(bgp
);
2486 STAILQ_INIT(&pqnode
->pqueue
);
2491 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2493 #define ARBITRARY_PROCESS_QLEN 10000
2494 struct work_queue
*wq
= bm
->process_main_queue
;
2495 struct bgp_process_queue
*pqnode
;
2496 int pqnode_reuse
= 0;
2498 /* already scheduled for processing? */
2499 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2505 /* Add route nodes to an existing work queue item until reaching the
2506 limit only if is from the same BGP view and it's not an EOIU marker
2508 if (work_queue_item_count(wq
)) {
2509 struct work_queue_item
*item
= work_queue_last_item(wq
);
2510 pqnode
= item
->data
;
2512 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2513 || pqnode
->bgp
!= bgp
2514 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2515 pqnode
= bgp_processq_alloc(bgp
);
2519 pqnode
= bgp_processq_alloc(bgp
);
2520 /* all unlocked in bgp_process_wq */
2521 bgp_table_lock(bgp_node_table(rn
));
2523 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2526 /* can't be enqueued twice */
2527 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2528 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2532 work_queue_add(wq
, pqnode
);
2537 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2539 struct bgp_process_queue
*pqnode
;
2541 if (bm
->process_main_queue
== NULL
)
2544 pqnode
= bgp_processq_alloc(bgp
);
2546 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2547 work_queue_add(bm
->process_main_queue
, pqnode
);
2550 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2554 peer
= THREAD_ARG(thread
);
2555 peer
->t_pmax_restart
= NULL
;
2557 if (bgp_debug_neighbor_events(peer
))
2559 "%s Maximum-prefix restart timer expired, restore peering",
2562 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2563 zlog_debug("%s: %s peer_clear failed",
2564 __PRETTY_FUNCTION__
, peer
->host
);
2569 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2573 iana_safi_t pkt_safi
;
2575 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2578 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2579 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2580 PEER_STATUS_PREFIX_LIMIT
)
2585 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2587 afi_safi_print(afi
, safi
), peer
->host
,
2588 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2589 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2591 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2592 PEER_FLAG_MAX_PREFIX_WARNING
))
2595 /* Convert AFI, SAFI to values for packet. */
2596 pkt_afi
= afi_int2iana(afi
);
2597 pkt_safi
= safi_int2iana(safi
);
2601 ndata
[0] = (pkt_afi
>> 8);
2603 ndata
[2] = pkt_safi
;
2604 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2605 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2606 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2607 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2609 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2610 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2611 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2615 /* Dynamic peers will just close their connection. */
2616 if (peer_dynamic_neighbor(peer
))
2619 /* restart timer start */
2620 if (peer
->pmax_restart
[afi
][safi
]) {
2621 peer
->v_pmax_restart
=
2622 peer
->pmax_restart
[afi
][safi
] * 60;
2624 if (bgp_debug_neighbor_events(peer
))
2626 "%s Maximum-prefix restart timer started for %d secs",
2627 peer
->host
, peer
->v_pmax_restart
);
2629 BGP_TIMER_ON(peer
->t_pmax_restart
,
2630 bgp_maximum_prefix_restart_timer
,
2631 peer
->v_pmax_restart
);
2636 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2637 PEER_STATUS_PREFIX_LIMIT
);
2639 if (peer
->pcount
[afi
][safi
]
2640 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2641 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2642 PEER_STATUS_PREFIX_THRESHOLD
)
2647 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2648 afi_safi_print(afi
, safi
), peer
->host
,
2649 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2650 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2651 PEER_STATUS_PREFIX_THRESHOLD
);
2653 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2654 PEER_STATUS_PREFIX_THRESHOLD
);
2658 /* Unconditionally remove the route from the RIB, without taking
2659 * damping into consideration (eg, because the session went down)
2661 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2662 afi_t afi
, safi_t safi
)
2664 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2666 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2667 bgp_info_delete(rn
, ri
); /* keep historical info */
2669 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2672 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2673 struct peer
*peer
, afi_t afi
, safi_t safi
,
2674 struct prefix_rd
*prd
)
2676 /* apply dampening, if result is suppressed, we'll be retaining
2677 * the bgp_info in the RIB for historical reference.
2679 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2680 && peer
->sort
== BGP_PEER_EBGP
)
2681 if ((bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2682 == BGP_DAMP_SUPPRESSED
) {
2683 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2689 if (safi
== SAFI_MPLS_VPN
) {
2690 struct bgp_node
*prn
= NULL
;
2691 struct bgp_table
*table
= NULL
;
2693 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2694 (struct prefix
*)prd
);
2696 table
= (struct bgp_table
*)(prn
->info
);
2698 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2699 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2701 bgp_unlock_node(prn
);
2703 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2704 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2706 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2707 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2713 /* If this is an EVPN route, process for un-import. */
2714 if (safi
== SAFI_EVPN
)
2715 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2717 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2720 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2721 struct peer
*peer
, struct attr
*attr
,
2722 struct bgp_node
*rn
)
2724 struct bgp_info
*new;
2726 /* Make new BGP info. */
2727 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2729 new->instance
= instance
;
2730 new->sub_type
= sub_type
;
2733 new->uptime
= bgp_clock();
2735 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2739 static void overlay_index_update(struct attr
*attr
,
2740 struct eth_segment_id
*eth_s_id
,
2741 union gw_addr
*gw_ip
)
2746 if (eth_s_id
== NULL
) {
2747 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2748 sizeof(struct eth_segment_id
));
2750 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2751 sizeof(struct eth_segment_id
));
2753 if (gw_ip
== NULL
) {
2754 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2756 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2757 sizeof(union gw_addr
));
2761 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2762 struct eth_segment_id
*eth_s_id
,
2763 union gw_addr
*gw_ip
)
2765 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2766 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2769 if (afi
!= AFI_L2VPN
)
2772 memset(&temp
, 0, 16);
2773 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2774 info_gw_ip
= (union gw_addr
*)&temp
;
2775 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2778 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2779 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2782 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2784 info_gw_ip_remote
= gw_ip
;
2785 if (eth_s_id
== NULL
)
2786 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2788 info_eth_s_id_remote
= eth_s_id
;
2789 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2791 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2792 sizeof(struct eth_segment_id
));
2795 /* Check if received nexthop is valid or not. */
2796 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2801 /* Only validated for unicast and multicast currently. */
2802 /* Also valid for EVPN where the nexthop is an IP address. */
2803 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2806 /* If NEXT_HOP is present, validate it. */
2807 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2808 if (attr
->nexthop
.s_addr
== 0
2809 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2810 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2814 /* If MP_NEXTHOP is present, validate it. */
2815 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2816 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2817 * it is not an IPv6 link-local address.
2819 if (attr
->mp_nexthop_len
) {
2820 switch (attr
->mp_nexthop_len
) {
2821 case BGP_ATTR_NHLEN_IPV4
:
2822 case BGP_ATTR_NHLEN_VPNV4
:
2823 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2824 || IPV4_CLASS_DE(ntohl(
2825 attr
->mp_nexthop_global_in
.s_addr
))
2826 || bgp_nexthop_self(bgp
,
2827 attr
->mp_nexthop_global_in
));
2830 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2831 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2832 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2833 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2834 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2835 || IN6_IS_ADDR_MULTICAST(
2836 &attr
->mp_nexthop_global
));
2848 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2849 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2850 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2851 uint32_t num_labels
, int soft_reconfig
,
2852 struct bgp_route_evpn
*evpn
)
2855 int aspath_loop_count
= 0;
2856 struct bgp_node
*rn
;
2858 struct attr new_attr
;
2859 struct attr
*attr_new
;
2860 struct bgp_info
*ri
;
2861 struct bgp_info
*new;
2862 struct bgp_info_extra
*extra
;
2864 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2866 int do_loop_check
= 1;
2867 int has_valid_label
= 0;
2869 int vnc_implicit_withdraw
= 0;
2873 memset(&new_attr
, 0, sizeof(struct attr
));
2874 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2875 new_attr
.label
= MPLS_INVALID_LABEL
;
2878 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2879 /* TODO: Check to see if we can get rid of "is_valid_label" */
2880 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2881 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2883 has_valid_label
= bgp_is_valid_label(label
);
2885 /* When peer's soft reconfiguration enabled. Record input packet in
2888 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2889 && peer
!= bgp
->peer_self
)
2890 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2892 /* Check previously received route. */
2893 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2894 if (ri
->peer
== peer
&& ri
->type
== type
2895 && ri
->sub_type
== sub_type
2896 && ri
->addpath_rx_id
== addpath_id
)
2899 /* AS path local-as loop check. */
2900 if (peer
->change_local_as
) {
2901 if (peer
->allowas_in
[afi
][safi
])
2902 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2903 else if (!CHECK_FLAG(peer
->flags
,
2904 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2905 aspath_loop_count
= 1;
2907 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2908 > aspath_loop_count
) {
2909 reason
= "as-path contains our own AS;";
2914 /* If the peer is configured for "allowas-in origin" and the last ASN in
2916 * as-path is our ASN then we do not need to call aspath_loop_check
2918 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2919 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2922 /* AS path loop check. */
2923 if (do_loop_check
) {
2924 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2925 > peer
->allowas_in
[afi
][safi
]
2926 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2927 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2928 > peer
->allowas_in
[afi
][safi
])) {
2929 reason
= "as-path contains our own AS;";
2934 /* Route reflector originator ID check. */
2935 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2936 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2937 reason
= "originator is us;";
2941 /* Route reflector cluster ID check. */
2942 if (bgp_cluster_filter(peer
, attr
)) {
2943 reason
= "reflected from the same cluster;";
2947 /* Apply incoming filter. */
2948 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2953 bgp_attr_dup(&new_attr
, attr
);
2955 /* Apply incoming route-map.
2956 * NB: new_attr may now contain newly allocated values from route-map
2958 * commands, so we need bgp_attr_flush in the error paths, until we
2960 * the attr (which takes over the memory references) */
2961 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2963 reason
= "route-map;";
2964 bgp_attr_flush(&new_attr
);
2968 if (peer
->sort
== BGP_PEER_EBGP
) {
2970 /* If we receive the graceful-shutdown community from an eBGP
2971 * peer we must lower local-preference */
2972 if (new_attr
.community
2973 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2974 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2975 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2977 /* If graceful-shutdown is configured then add the GSHUT
2978 * community to all paths received from eBGP peers */
2979 } else if (bgp_flag_check(peer
->bgp
,
2980 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2981 bgp_attr_add_gshut_community(&new_attr
);
2985 /* next hop check. */
2986 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2987 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2988 reason
= "martian or self next-hop;";
2989 bgp_attr_flush(&new_attr
);
2993 attr_new
= bgp_attr_intern(&new_attr
);
2995 /* If the update is implicit withdraw. */
2997 ri
->uptime
= bgp_clock();
2998 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
3000 /* Same attribute comes in. */
3001 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
3002 && attrhash_cmp(ri
->attr
, attr_new
)
3003 && (!has_valid_label
3004 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
3005 num_labels
* sizeof(mpls_label_t
))
3007 && (overlay_index_equal(
3008 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3009 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3010 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3011 BGP_CONFIG_DAMPENING
)
3012 && peer
->sort
== BGP_PEER_EBGP
3013 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3014 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3015 bgp_debug_rdpfxpath2str(
3016 afi
, safi
, prd
, p
, label
,
3017 num_labels
, addpath_id
? 1 : 0,
3018 addpath_id
, pfx_buf
,
3020 zlog_debug("%s rcvd %s", peer
->host
,
3024 if (bgp_damp_update(ri
, rn
, afi
, safi
)
3025 != BGP_DAMP_SUPPRESSED
) {
3026 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
3028 bgp_process(bgp
, rn
, afi
, safi
);
3030 } else /* Duplicate - odd */
3032 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3033 if (!peer
->rcvd_attr_printed
) {
3035 "%s rcvd UPDATE w/ attr: %s",
3037 peer
->rcvd_attr_str
);
3038 peer
->rcvd_attr_printed
= 1;
3041 bgp_debug_rdpfxpath2str(
3042 afi
, safi
, prd
, p
, label
,
3043 num_labels
, addpath_id
? 1 : 0,
3044 addpath_id
, pfx_buf
,
3047 "%s rcvd %s...duplicate ignored",
3048 peer
->host
, pfx_buf
);
3051 /* graceful restart STALE flag unset. */
3052 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3053 bgp_info_unset_flag(rn
, ri
,
3055 bgp_process(bgp
, rn
, afi
, safi
);
3059 bgp_unlock_node(rn
);
3060 bgp_attr_unintern(&attr_new
);
3065 /* Withdraw/Announce before we fully processed the withdraw */
3066 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3067 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3068 bgp_debug_rdpfxpath2str(
3069 afi
, safi
, prd
, p
, label
, num_labels
,
3070 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3073 "%s rcvd %s, flapped quicker than processing",
3074 peer
->host
, pfx_buf
);
3077 bgp_info_restore(rn
, ri
);
3080 /* Received Logging. */
3081 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3082 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3083 num_labels
, addpath_id
? 1 : 0,
3084 addpath_id
, pfx_buf
,
3086 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3089 /* graceful restart STALE flag unset. */
3090 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3091 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3093 /* The attribute is changed. */
3094 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3096 /* implicit withdraw, decrement aggregate and pcount here.
3097 * only if update is accepted, they'll increment below.
3099 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3101 /* Update bgp route dampening information. */
3102 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3103 && peer
->sort
== BGP_PEER_EBGP
) {
3104 /* This is implicit withdraw so we should update
3107 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3108 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3111 if (safi
== SAFI_MPLS_VPN
) {
3112 struct bgp_node
*prn
= NULL
;
3113 struct bgp_table
*table
= NULL
;
3115 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3116 (struct prefix
*)prd
);
3118 table
= (struct bgp_table
*)(prn
->info
);
3120 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3121 bgp
, prd
, table
, p
, ri
);
3123 bgp_unlock_node(prn
);
3125 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3126 && (safi
== SAFI_UNICAST
)) {
3127 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3129 * Implicit withdraw case.
3131 ++vnc_implicit_withdraw
;
3132 vnc_import_bgp_del_route(bgp
, p
, ri
);
3133 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3138 /* Special handling for EVPN update of an existing route. If the
3139 * extended community attribute has changed, we need to
3141 * the route using its existing extended community. It will be
3142 * subsequently processed for import with the new extended
3145 if (safi
== SAFI_EVPN
&& !same_attr
) {
3147 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3149 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3152 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3153 attr_new
->ecommunity
);
3155 if (bgp_debug_update(peer
, p
, NULL
, 1))
3157 "Change in EXT-COMM, existing %s new %s",
3159 ri
->attr
->ecommunity
),
3161 attr_new
->ecommunity
));
3162 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3168 /* Update to new attribute. */
3169 bgp_attr_unintern(&ri
->attr
);
3170 ri
->attr
= attr_new
;
3172 /* Update MPLS label */
3173 if (has_valid_label
) {
3174 extra
= bgp_info_extra_get(ri
);
3175 memcpy(&extra
->label
, label
,
3176 num_labels
* sizeof(mpls_label_t
));
3177 extra
->num_labels
= num_labels
;
3178 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3179 bgp_set_valid_label(&extra
->label
[0]);
3183 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3184 && (safi
== SAFI_UNICAST
)) {
3185 if (vnc_implicit_withdraw
) {
3187 * Add back the route with its new attributes
3189 * The route is still selected, until the route
3191 * queued by bgp_process actually runs. We have
3193 * update to the VNC side immediately to avoid
3195 * configuration changes (e.g., route-map
3197 * trigger re-importation of the entire RIB.
3199 vnc_import_bgp_add_route(bgp
, p
, ri
);
3200 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3204 /* Update Overlay Index */
3205 if (afi
== AFI_L2VPN
) {
3206 overlay_index_update(
3207 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3208 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3211 /* Update bgp route dampening information. */
3212 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3213 && peer
->sort
== BGP_PEER_EBGP
) {
3214 /* Now we do normal update dampening. */
3215 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3216 if (ret
== BGP_DAMP_SUPPRESSED
) {
3217 bgp_unlock_node(rn
);
3222 /* Nexthop reachability check - for unicast and
3223 * labeled-unicast.. */
3224 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3225 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3226 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3227 && !CHECK_FLAG(peer
->flags
,
3228 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3230 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3235 struct bgp
*bgp_nexthop
= bgp
;
3237 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3238 bgp_nexthop
= ri
->extra
->bgp_orig
;
3240 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3241 ri
, NULL
, connected
)
3242 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3243 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3245 if (BGP_DEBUG(nht
, NHT
)) {
3246 char buf1
[INET6_ADDRSTRLEN
];
3248 (const void *)&attr_new
3250 buf1
, INET6_ADDRSTRLEN
);
3251 zlog_debug("%s(%s): NH unresolved",
3252 __FUNCTION__
, buf1
);
3254 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3257 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3260 if (safi
== SAFI_MPLS_VPN
) {
3261 struct bgp_node
*prn
= NULL
;
3262 struct bgp_table
*table
= NULL
;
3264 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3265 (struct prefix
*)prd
);
3267 table
= (struct bgp_table
*)(prn
->info
);
3269 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3270 bgp
, prd
, table
, p
, ri
);
3272 bgp_unlock_node(prn
);
3276 /* If this is an EVPN route and some attribute has changed,
3278 * route for import. If the extended community has changed, we
3280 * have done the un-import earlier and the import would result
3282 * route getting injected into appropriate L2 VNIs. If it is
3284 * some other attribute change, the import will result in
3286 * the attributes for the route in the VNI(s).
3288 if (safi
== SAFI_EVPN
&& !same_attr
)
3289 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3291 /* Process change. */
3292 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3294 bgp_process(bgp
, rn
, afi
, safi
);
3295 bgp_unlock_node(rn
);
3297 if (SAFI_UNICAST
== safi
3298 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3299 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3301 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3303 if ((SAFI_MPLS_VPN
== safi
)
3304 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3306 vpn_leak_to_vrf_update(bgp
, ri
);
3310 if (SAFI_MPLS_VPN
== safi
) {
3311 mpls_label_t label_decoded
= decode_label(label
);
3313 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3314 type
, sub_type
, &label_decoded
);
3316 if (SAFI_ENCAP
== safi
) {
3317 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3318 type
, sub_type
, NULL
);
3323 } // End of implicit withdraw
3325 /* Received Logging. */
3326 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3327 if (!peer
->rcvd_attr_printed
) {
3328 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3329 peer
->rcvd_attr_str
);
3330 peer
->rcvd_attr_printed
= 1;
3333 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3334 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3336 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3339 /* Make new BGP info. */
3340 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3342 /* Update MPLS label */
3343 if (has_valid_label
) {
3344 extra
= bgp_info_extra_get(new);
3345 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3346 extra
->num_labels
= num_labels
;
3347 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3348 bgp_set_valid_label(&extra
->label
[0]);
3351 /* Update Overlay Index */
3352 if (afi
== AFI_L2VPN
) {
3353 overlay_index_update(new->attr
,
3354 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3355 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3357 /* Nexthop reachability check. */
3358 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3359 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3360 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3361 && !CHECK_FLAG(peer
->flags
,
3362 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3363 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3368 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3369 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3370 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3372 if (BGP_DEBUG(nht
, NHT
)) {
3373 char buf1
[INET6_ADDRSTRLEN
];
3375 (const void *)&attr_new
->nexthop
,
3376 buf1
, INET6_ADDRSTRLEN
);
3377 zlog_debug("%s(%s): NH unresolved",
3378 __FUNCTION__
, buf1
);
3380 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3383 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3386 new->addpath_rx_id
= addpath_id
;
3388 /* Increment prefix */
3389 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3391 /* Register new BGP information. */
3392 bgp_info_add(rn
, new);
3394 /* route_node_get lock */
3395 bgp_unlock_node(rn
);
3398 if (safi
== SAFI_MPLS_VPN
) {
3399 struct bgp_node
*prn
= NULL
;
3400 struct bgp_table
*table
= NULL
;
3402 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3404 table
= (struct bgp_table
*)(prn
->info
);
3406 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3407 bgp
, prd
, table
, p
, new);
3409 bgp_unlock_node(prn
);
3413 /* If maximum prefix count is configured and current prefix
3415 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3418 /* If this is an EVPN route, process for import. */
3419 if (safi
== SAFI_EVPN
)
3420 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3422 /* Process change. */
3423 bgp_process(bgp
, rn
, afi
, safi
);
3425 if (SAFI_UNICAST
== safi
3426 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3427 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3428 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3430 if ((SAFI_MPLS_VPN
== safi
)
3431 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3433 vpn_leak_to_vrf_update(bgp
, new);
3436 if (SAFI_MPLS_VPN
== safi
) {
3437 mpls_label_t label_decoded
= decode_label(label
);
3439 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3440 sub_type
, &label_decoded
);
3442 if (SAFI_ENCAP
== safi
) {
3443 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3450 /* This BGP update is filtered. Log the reason then update BGP
3453 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3454 if (!peer
->rcvd_attr_printed
) {
3455 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3456 peer
->rcvd_attr_str
);
3457 peer
->rcvd_attr_printed
= 1;
3460 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3461 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3463 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3464 peer
->host
, pfx_buf
, reason
);
3468 /* If this is an EVPN route, un-import it as it is now filtered.
3470 if (safi
== SAFI_EVPN
)
3471 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3473 if (SAFI_UNICAST
== safi
3474 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3475 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3477 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3479 if ((SAFI_MPLS_VPN
== safi
)
3480 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3482 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3485 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3488 bgp_unlock_node(rn
);
3492 * Filtered update is treated as an implicit withdrawal (see
3494 * a few lines above)
3496 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3497 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3505 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3506 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3507 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3508 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3511 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3512 struct bgp_node
*rn
;
3513 struct bgp_info
*ri
;
3516 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3517 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3525 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3527 /* If peer is soft reconfiguration enabled. Record input packet for
3528 * further calculation.
3530 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3531 * routes that are filtered. This tanks out Quagga RS pretty badly due
3533 * the iteration over all RS clients.
3534 * Since we need to remove the entry from adj_in anyway, do that first
3536 * if there was no entry, we don't need to do anything more.
3538 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3539 && peer
!= bgp
->peer_self
)
3540 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3541 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3542 bgp_debug_rdpfxpath2str(
3543 afi
, safi
, prd
, p
, label
, num_labels
,
3544 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3547 "%s withdrawing route %s not in adj-in",
3548 peer
->host
, pfx_buf
);
3550 bgp_unlock_node(rn
);
3554 /* Lookup withdrawn route. */
3555 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3556 if (ri
->peer
== peer
&& ri
->type
== type
3557 && ri
->sub_type
== sub_type
3558 && ri
->addpath_rx_id
== addpath_id
)
3562 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3563 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3564 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3566 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3570 /* Withdraw specified route from routing table. */
3571 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3572 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3573 if (SAFI_UNICAST
== safi
3574 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3575 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3576 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3578 if ((SAFI_MPLS_VPN
== safi
)
3579 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3581 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3583 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3584 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3585 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3587 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3590 /* Unlock bgp_node_get() lock. */
3591 bgp_unlock_node(rn
);
3596 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3599 struct update_subgroup
*subgrp
;
3600 subgrp
= peer_subgroup(peer
, afi
, safi
);
3601 subgroup_default_originate(subgrp
, withdraw
);
3606 * bgp_stop_announce_route_timer
3608 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3610 if (!paf
->t_announce_route
)
3613 THREAD_TIMER_OFF(paf
->t_announce_route
);
3617 * bgp_announce_route_timer_expired
3619 * Callback that is invoked when the route announcement timer for a
3622 static int bgp_announce_route_timer_expired(struct thread
*t
)
3624 struct peer_af
*paf
;
3627 paf
= THREAD_ARG(t
);
3630 if (peer
->status
!= Established
)
3633 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3636 peer_af_announce_route(paf
, 1);
3641 * bgp_announce_route
3643 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3645 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3647 struct peer_af
*paf
;
3648 struct update_subgroup
*subgrp
;
3650 paf
= peer_af_find(peer
, afi
, safi
);
3653 subgrp
= PAF_SUBGRP(paf
);
3656 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3657 * or a refresh has already been triggered.
3659 if (!subgrp
|| paf
->t_announce_route
)
3663 * Start a timer to stagger/delay the announce. This serves
3664 * two purposes - announcement can potentially be combined for
3665 * multiple peers and the announcement doesn't happen in the
3668 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3669 (subgrp
->peer_count
== 1)
3670 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3671 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3672 &paf
->t_announce_route
);
3676 * Announce routes from all AF tables to a peer.
3678 * This should ONLY be called when there is a need to refresh the
3679 * routes to the peer based on a policy change for this peer alone
3680 * or a route refresh request received from the peer.
3681 * The operation will result in splitting the peer from its existing
3682 * subgroups and putting it in new subgroups.
3684 void bgp_announce_route_all(struct peer
*peer
)
3689 FOREACH_AFI_SAFI (afi
, safi
)
3690 bgp_announce_route(peer
, afi
, safi
);
3693 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3694 struct bgp_table
*table
,
3695 struct prefix_rd
*prd
)
3698 struct bgp_node
*rn
;
3699 struct bgp_adj_in
*ain
;
3702 table
= peer
->bgp
->rib
[afi
][safi
];
3704 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3705 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3706 if (ain
->peer
!= peer
)
3709 struct bgp_info
*ri
= rn
->info
;
3710 uint32_t num_labels
= 0;
3711 mpls_label_t
*label_pnt
= NULL
;
3713 if (ri
&& ri
->extra
)
3714 num_labels
= ri
->extra
->num_labels
;
3716 label_pnt
= &ri
->extra
->label
[0];
3718 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3719 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3720 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3721 num_labels
, 1, NULL
);
3724 bgp_unlock_node(rn
);
3730 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3732 struct bgp_node
*rn
;
3733 struct bgp_table
*table
;
3735 if (peer
->status
!= Established
)
3738 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3739 && (safi
!= SAFI_EVPN
))
3740 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3742 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3743 rn
= bgp_route_next(rn
))
3744 if ((table
= rn
->info
) != NULL
) {
3745 struct prefix_rd prd
;
3746 prd
.family
= AF_UNSPEC
;
3748 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3750 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3756 struct bgp_clear_node_queue
{
3757 struct bgp_node
*rn
;
3760 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3762 struct bgp_clear_node_queue
*cnq
= data
;
3763 struct bgp_node
*rn
= cnq
->rn
;
3764 struct peer
*peer
= wq
->spec
.data
;
3765 struct bgp_info
*ri
;
3767 afi_t afi
= bgp_node_table(rn
)->afi
;
3768 safi_t safi
= bgp_node_table(rn
)->safi
;
3773 /* It is possible that we have multiple paths for a prefix from a peer
3774 * if that peer is using AddPath.
3776 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3777 if (ri
->peer
!= peer
)
3780 /* graceful restart STALE flag set. */
3781 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3782 && peer
->nsf
[afi
][safi
]
3783 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3784 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3785 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3787 /* If this is an EVPN route, process for
3789 if (safi
== SAFI_EVPN
)
3790 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3792 /* Handle withdraw for VRF route-leaking and L3VPN */
3793 if (SAFI_UNICAST
== safi
3794 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3795 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3796 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3799 if (SAFI_MPLS_VPN
== safi
&&
3800 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3801 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3804 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3810 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3812 struct bgp_clear_node_queue
*cnq
= data
;
3813 struct bgp_node
*rn
= cnq
->rn
;
3814 struct bgp_table
*table
= bgp_node_table(rn
);
3816 bgp_unlock_node(rn
);
3817 bgp_table_unlock(table
);
3818 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3821 static void bgp_clear_node_complete(struct work_queue
*wq
)
3823 struct peer
*peer
= wq
->spec
.data
;
3825 /* Tickle FSM to start moving again */
3826 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3828 peer_unlock(peer
); /* bgp_clear_route */
3831 static void bgp_clear_node_queue_init(struct peer
*peer
)
3833 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3835 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3836 #undef CLEAR_QUEUE_NAME_LEN
3838 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3839 peer
->clear_node_queue
->spec
.hold
= 10;
3840 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3841 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3842 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3843 peer
->clear_node_queue
->spec
.max_retries
= 0;
3845 /* we only 'lock' this peer reference when the queue is actually active
3847 peer
->clear_node_queue
->spec
.data
= peer
;
3850 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3851 struct bgp_table
*table
)
3853 struct bgp_node
*rn
;
3854 int force
= bm
->process_main_queue
? 0 : 1;
3857 table
= peer
->bgp
->rib
[afi
][safi
];
3859 /* If still no table => afi/safi isn't configured at all or smth. */
3863 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3864 struct bgp_info
*ri
, *next
;
3865 struct bgp_adj_in
*ain
;
3866 struct bgp_adj_in
*ain_next
;
3868 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3869 * queued for every clearing peer, regardless of whether it is
3870 * relevant to the peer at hand.
3872 * Overview: There are 3 different indices which need to be
3873 * scrubbed, potentially, when a peer is removed:
3875 * 1 peer's routes visible via the RIB (ie accepted routes)
3876 * 2 peer's routes visible by the (optional) peer's adj-in index
3877 * 3 other routes visible by the peer's adj-out index
3879 * 3 there is no hurry in scrubbing, once the struct peer is
3880 * removed from bgp->peer, we could just GC such deleted peer's
3881 * adj-outs at our leisure.
3883 * 1 and 2 must be 'scrubbed' in some way, at least made
3884 * invisible via RIB index before peer session is allowed to be
3885 * brought back up. So one needs to know when such a 'search' is
3890 * - there'd be a single global queue or a single RIB walker
3891 * - rather than tracking which route_nodes still need to be
3892 * examined on a peer basis, we'd track which peers still
3895 * Given that our per-peer prefix-counts now should be reliable,
3896 * this may actually be achievable. It doesn't seem to be a huge
3897 * problem at this time,
3899 * It is possible that we have multiple paths for a prefix from
3901 * if that peer is using AddPath.
3905 ain_next
= ain
->next
;
3907 if (ain
->peer
== peer
) {
3908 bgp_adj_in_remove(rn
, ain
);
3909 bgp_unlock_node(rn
);
3915 for (ri
= rn
->info
; ri
; ri
= next
) {
3917 if (ri
->peer
!= peer
)
3921 bgp_info_reap(rn
, ri
);
3923 struct bgp_clear_node_queue
*cnq
;
3925 /* both unlocked in bgp_clear_node_queue_del */
3926 bgp_table_lock(bgp_node_table(rn
));
3929 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3930 sizeof(struct bgp_clear_node_queue
));
3932 work_queue_add(peer
->clear_node_queue
, cnq
);
3940 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3942 struct bgp_node
*rn
;
3943 struct bgp_table
*table
;
3945 if (peer
->clear_node_queue
== NULL
)
3946 bgp_clear_node_queue_init(peer
);
3948 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3949 * Idle until it receives a Clearing_Completed event. This protects
3950 * against peers which flap faster than we can we clear, which could
3953 * a) race with routes from the new session being installed before
3954 * clear_route_node visits the node (to delete the route of that
3956 * b) resource exhaustion, clear_route_node likely leads to an entry
3957 * on the process_main queue. Fast-flapping could cause that queue
3961 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3962 * the unlock will happen upon work-queue completion; other wise, the
3963 * unlock happens at the end of this function.
3965 if (!peer
->clear_node_queue
->thread
)
3968 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3969 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3971 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3972 rn
= bgp_route_next(rn
))
3973 if ((table
= rn
->info
) != NULL
)
3974 bgp_clear_route_table(peer
, afi
, safi
, table
);
3976 /* unlock if no nodes got added to the clear-node-queue. */
3977 if (!peer
->clear_node_queue
->thread
)
3981 void bgp_clear_route_all(struct peer
*peer
)
3986 FOREACH_AFI_SAFI (afi
, safi
)
3987 bgp_clear_route(peer
, afi
, safi
);
3990 rfapiProcessPeerDown(peer
);
3994 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3996 struct bgp_table
*table
;
3997 struct bgp_node
*rn
;
3998 struct bgp_adj_in
*ain
;
3999 struct bgp_adj_in
*ain_next
;
4001 table
= peer
->bgp
->rib
[afi
][safi
];
4003 /* It is possible that we have multiple paths for a prefix from a peer
4004 * if that peer is using AddPath.
4006 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4010 ain_next
= ain
->next
;
4012 if (ain
->peer
== peer
) {
4013 bgp_adj_in_remove(rn
, ain
);
4014 bgp_unlock_node(rn
);
4022 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4024 struct bgp_node
*rn
;
4025 struct bgp_info
*ri
;
4026 struct bgp_table
*table
;
4028 if (safi
== SAFI_MPLS_VPN
) {
4029 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4030 rn
= bgp_route_next(rn
)) {
4031 struct bgp_node
*rm
;
4032 struct bgp_info
*ri
;
4034 /* look for neighbor in tables */
4035 if ((table
= rn
->info
) == NULL
)
4038 for (rm
= bgp_table_top(table
); rm
;
4039 rm
= bgp_route_next(rm
))
4040 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4041 if (ri
->peer
!= peer
)
4043 if (!CHECK_FLAG(ri
->flags
,
4047 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4052 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4053 rn
= bgp_route_next(rn
))
4054 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4055 if (ri
->peer
!= peer
)
4057 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4059 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4065 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4068 struct bgp_node
*rn
;
4069 struct bgp_info
*ri
;
4070 struct bgp_info
*next
;
4072 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4073 for (ri
= rn
->info
; ri
; ri
= next
) {
4075 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4076 && ri
->type
== ZEBRA_ROUTE_BGP
4077 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4078 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4079 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4081 if (bgp_fibupd_safi(safi
))
4082 bgp_zebra_withdraw(&rn
->p
, ri
,
4084 bgp_info_reap(rn
, ri
);
4089 /* Delete all kernel routes. */
4090 void bgp_cleanup_routes(struct bgp
*bgp
)
4093 struct bgp_node
*rn
;
4095 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4096 if (afi
== AFI_L2VPN
)
4098 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4101 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4103 if (afi
!= AFI_L2VPN
) {
4105 safi
= SAFI_MPLS_VPN
;
4106 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4107 rn
= bgp_route_next(rn
)) {
4109 bgp_cleanup_table(bgp
,
4110 (struct bgp_table
*)(rn
->info
),
4112 bgp_table_finish((struct bgp_table
**)&(
4115 bgp_unlock_node(rn
);
4119 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4120 rn
= bgp_route_next(rn
)) {
4122 bgp_cleanup_table(bgp
,
4123 (struct bgp_table
*)(rn
->info
),
4125 bgp_table_finish((struct bgp_table
**)&(
4128 bgp_unlock_node(rn
);
4133 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4134 rn
= bgp_route_next(rn
)) {
4136 bgp_cleanup_table(bgp
,
4137 (struct bgp_table
*)(rn
->info
),
4139 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4141 bgp_unlock_node(rn
);
4146 void bgp_reset(void)
4149 bgp_zclient_reset();
4150 access_list_reset();
4151 prefix_list_reset();
4154 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4156 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4157 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4158 PEER_CAP_ADDPATH_AF_TX_RCV
));
4161 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4163 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4164 struct bgp_nlri
*packet
)
4173 int addpath_encoded
;
4174 uint32_t addpath_id
;
4177 lim
= pnt
+ packet
->length
;
4179 safi
= packet
->safi
;
4181 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4183 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4184 syntactic validity. If the field is syntactically incorrect,
4185 then the Error Subcode is set to Invalid Network Field. */
4186 for (; pnt
< lim
; pnt
+= psize
) {
4187 /* Clear prefix structure. */
4188 memset(&p
, 0, sizeof(struct prefix
));
4190 if (addpath_encoded
) {
4192 /* When packet overflow occurs return immediately. */
4193 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4196 addpath_id
= ntohl(*((uint32_t *)pnt
));
4197 pnt
+= BGP_ADDPATH_ID_LEN
;
4200 /* Fetch prefix length. */
4201 p
.prefixlen
= *pnt
++;
4202 /* afi/safi validity already verified by caller,
4203 * bgp_update_receive */
4204 p
.family
= afi2family(afi
);
4206 /* Prefix length check. */
4207 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4210 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4211 peer
->host
, p
.prefixlen
, packet
->afi
);
4215 /* Packet size overflow check. */
4216 psize
= PSIZE(p
.prefixlen
);
4218 /* When packet overflow occur return immediately. */
4219 if (pnt
+ psize
> lim
) {
4222 "%s [Error] Update packet error (prefix length %d overflows packet)",
4223 peer
->host
, p
.prefixlen
);
4227 /* Defensive coding, double-check the psize fits in a struct
4229 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4232 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4233 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4237 /* Fetch prefix from NLRI packet. */
4238 memcpy(p
.u
.val
, pnt
, psize
);
4240 /* Check address. */
4241 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4242 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4243 /* From RFC4271 Section 6.3:
4245 * If a prefix in the NLRI field is semantically
4247 * (e.g., an unexpected multicast IP address),
4249 * be logged locally, and the prefix SHOULD be
4254 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4255 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4260 /* Check address. */
4261 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4262 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4267 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4269 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4274 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4279 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4281 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4288 /* Normal process. */
4290 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4291 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4292 NULL
, NULL
, 0, 0, NULL
);
4294 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4295 safi
, ZEBRA_ROUTE_BGP
,
4296 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4299 /* Address family configuration mismatch or maximum-prefix count
4305 /* Packet length consistency check. */
4309 "%s [Error] Update packet error (prefix length mismatch with total length)",
4317 static struct bgp_static
*bgp_static_new(void)
4319 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4322 static void bgp_static_free(struct bgp_static
*bgp_static
)
4324 if (bgp_static
->rmap
.name
)
4325 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4326 if (bgp_static
->eth_s_id
)
4327 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4328 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4331 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4332 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4334 struct bgp_node
*rn
;
4335 struct bgp_info
*ri
;
4336 struct bgp_info
*new;
4337 struct bgp_info info
;
4339 struct attr
*attr_new
;
4342 int vnc_implicit_withdraw
= 0;
4349 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4351 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4353 attr
.nexthop
= bgp_static
->igpnexthop
;
4354 attr
.med
= bgp_static
->igpmetric
;
4355 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4357 if (bgp_static
->atomic
)
4358 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4360 /* Store label index, if required. */
4361 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4362 attr
.label_index
= bgp_static
->label_index
;
4363 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4366 /* Apply route-map. */
4367 if (bgp_static
->rmap
.name
) {
4368 struct attr attr_tmp
= attr
;
4370 memset(&info
, 0, sizeof(struct bgp_info
));
4371 info
.peer
= bgp
->peer_self
;
4372 info
.attr
= &attr_tmp
;
4374 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4376 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4378 bgp
->peer_self
->rmap_type
= 0;
4380 if (ret
== RMAP_DENYMATCH
) {
4381 /* Free uninterned attribute. */
4382 bgp_attr_flush(&attr_tmp
);
4384 /* Unintern original. */
4385 aspath_unintern(&attr
.aspath
);
4386 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4390 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4391 bgp_attr_add_gshut_community(&attr_tmp
);
4393 attr_new
= bgp_attr_intern(&attr_tmp
);
4396 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4397 bgp_attr_add_gshut_community(&attr
);
4399 attr_new
= bgp_attr_intern(&attr
);
4402 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4403 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4404 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4408 if (attrhash_cmp(ri
->attr
, attr_new
)
4409 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4410 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4411 bgp_unlock_node(rn
);
4412 bgp_attr_unintern(&attr_new
);
4413 aspath_unintern(&attr
.aspath
);
4416 /* The attribute is changed. */
4417 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4419 /* Rewrite BGP route information. */
4420 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4421 bgp_info_restore(rn
, ri
);
4423 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4425 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4426 && (safi
== SAFI_UNICAST
)) {
4427 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4429 * Implicit withdraw case.
4430 * We have to do this before ri is
4433 ++vnc_implicit_withdraw
;
4434 vnc_import_bgp_del_route(bgp
, p
, ri
);
4435 vnc_import_bgp_exterior_del_route(
4440 bgp_attr_unintern(&ri
->attr
);
4441 ri
->attr
= attr_new
;
4442 ri
->uptime
= bgp_clock();
4444 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4445 && (safi
== SAFI_UNICAST
)) {
4446 if (vnc_implicit_withdraw
) {
4447 vnc_import_bgp_add_route(bgp
, p
, ri
);
4448 vnc_import_bgp_exterior_add_route(
4454 /* Nexthop reachability check. */
4455 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4456 && (safi
== SAFI_UNICAST
4457 || safi
== SAFI_LABELED_UNICAST
)) {
4459 struct bgp
*bgp_nexthop
= bgp
;
4461 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4462 bgp_nexthop
= ri
->extra
->bgp_orig
;
4464 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4466 bgp_info_set_flag(rn
, ri
,
4469 if (BGP_DEBUG(nht
, NHT
)) {
4470 char buf1
[INET6_ADDRSTRLEN
];
4471 inet_ntop(p
->family
,
4475 "%s(%s): Route not in table, not advertising",
4476 __FUNCTION__
, buf1
);
4478 bgp_info_unset_flag(rn
, ri
,
4482 /* Delete the NHT structure if any, if we're
4484 * enabling/disabling import check. We
4485 * deregister the route
4486 * from NHT to avoid overloading NHT and the
4487 * process interaction
4489 bgp_unlink_nexthop(ri
);
4490 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4492 /* Process change. */
4493 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4494 bgp_process(bgp
, rn
, afi
, safi
);
4496 if (SAFI_UNICAST
== safi
4497 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4499 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4500 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4504 bgp_unlock_node(rn
);
4505 aspath_unintern(&attr
.aspath
);
4510 /* Make new BGP info. */
4511 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4513 /* Nexthop reachability check. */
4514 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4515 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4516 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4517 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4519 if (BGP_DEBUG(nht
, NHT
)) {
4520 char buf1
[INET6_ADDRSTRLEN
];
4521 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4524 "%s(%s): Route not in table, not advertising",
4525 __FUNCTION__
, buf1
);
4527 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4530 /* Delete the NHT structure if any, if we're toggling between
4531 * enabling/disabling import check. We deregister the route
4532 * from NHT to avoid overloading NHT and the process interaction
4534 bgp_unlink_nexthop(new);
4536 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4539 /* Aggregate address increment. */
4540 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4542 /* Register new BGP information. */
4543 bgp_info_add(rn
, new);
4545 /* route_node_get lock */
4546 bgp_unlock_node(rn
);
4548 /* Process change. */
4549 bgp_process(bgp
, rn
, afi
, safi
);
4551 if (SAFI_UNICAST
== safi
4552 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4553 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4554 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4557 /* Unintern original. */
4558 aspath_unintern(&attr
.aspath
);
4561 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4564 struct bgp_node
*rn
;
4565 struct bgp_info
*ri
;
4567 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4569 /* Check selected route and self inserted route. */
4570 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4571 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4572 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4575 /* Withdraw static BGP route from routing table. */
4577 if (SAFI_UNICAST
== safi
4578 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4579 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4580 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4582 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4583 bgp_unlink_nexthop(ri
);
4584 bgp_info_delete(rn
, ri
);
4585 bgp_process(bgp
, rn
, afi
, safi
);
4588 /* Unlock bgp_node_lookup. */
4589 bgp_unlock_node(rn
);
4593 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4595 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4596 afi_t afi
, safi_t safi
,
4597 struct prefix_rd
*prd
)
4599 struct bgp_node
*rn
;
4600 struct bgp_info
*ri
;
4602 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4604 /* Check selected route and self inserted route. */
4605 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4606 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4607 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4610 /* Withdraw static BGP route from routing table. */
4613 rfapiProcessWithdraw(
4614 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4615 1); /* Kill, since it is an administrative change */
4617 if (SAFI_MPLS_VPN
== safi
4618 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4619 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4621 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4622 bgp_info_delete(rn
, ri
);
4623 bgp_process(bgp
, rn
, afi
, safi
);
4626 /* Unlock bgp_node_lookup. */
4627 bgp_unlock_node(rn
);
4630 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4631 struct bgp_static
*bgp_static
, afi_t afi
,
4634 struct bgp_node
*rn
;
4635 struct bgp_info
*new;
4636 struct attr
*attr_new
;
4637 struct attr attr
= {0};
4638 struct bgp_info
*ri
;
4640 mpls_label_t label
= 0;
4642 uint32_t num_labels
= 0;
4647 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4649 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4652 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4654 attr
.nexthop
= bgp_static
->igpnexthop
;
4655 attr
.med
= bgp_static
->igpmetric
;
4656 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4658 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4659 || (safi
== SAFI_ENCAP
)) {
4660 if (afi
== AFI_IP
) {
4661 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4662 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4665 if (afi
== AFI_L2VPN
) {
4666 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4668 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4669 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4670 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4671 sizeof(struct in6_addr
));
4672 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4673 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4674 struct bgp_encap_type_vxlan bet
;
4675 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4676 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4677 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4679 if (bgp_static
->router_mac
) {
4680 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4683 /* Apply route-map. */
4684 if (bgp_static
->rmap
.name
) {
4685 struct attr attr_tmp
= attr
;
4686 struct bgp_info info
;
4689 info
.peer
= bgp
->peer_self
;
4690 info
.attr
= &attr_tmp
;
4692 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4694 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4696 bgp
->peer_self
->rmap_type
= 0;
4698 if (ret
== RMAP_DENYMATCH
) {
4699 /* Free uninterned attribute. */
4700 bgp_attr_flush(&attr_tmp
);
4702 /* Unintern original. */
4703 aspath_unintern(&attr
.aspath
);
4704 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4709 attr_new
= bgp_attr_intern(&attr_tmp
);
4711 attr_new
= bgp_attr_intern(&attr
);
4714 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4715 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4716 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4721 memset(&add
, 0, sizeof(union gw_addr
));
4722 if (attrhash_cmp(ri
->attr
, attr_new
)
4723 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4724 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4725 bgp_unlock_node(rn
);
4726 bgp_attr_unintern(&attr_new
);
4727 aspath_unintern(&attr
.aspath
);
4730 /* The attribute is changed. */
4731 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4733 /* Rewrite BGP route information. */
4734 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4735 bgp_info_restore(rn
, ri
);
4737 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4738 bgp_attr_unintern(&ri
->attr
);
4739 ri
->attr
= attr_new
;
4740 ri
->uptime
= bgp_clock();
4743 label
= decode_label(&ri
->extra
->label
[0]);
4746 /* Process change. */
4747 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4748 bgp_process(bgp
, rn
, afi
, safi
);
4750 if (SAFI_MPLS_VPN
== safi
4751 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4752 vpn_leak_to_vrf_update(bgp
, ri
);
4755 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4756 ri
->attr
, afi
, safi
, ri
->type
,
4757 ri
->sub_type
, &label
);
4759 bgp_unlock_node(rn
);
4760 aspath_unintern(&attr
.aspath
);
4766 /* Make new BGP info. */
4767 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4769 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4770 new->extra
= bgp_info_extra_new();
4772 new->extra
->label
[0] = bgp_static
->label
;
4773 new->extra
->num_labels
= num_labels
;
4776 label
= decode_label(&bgp_static
->label
);
4779 /* Aggregate address increment. */
4780 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4782 /* Register new BGP information. */
4783 bgp_info_add(rn
, new);
4784 /* route_node_get lock */
4785 bgp_unlock_node(rn
);
4787 /* Process change. */
4788 bgp_process(bgp
, rn
, afi
, safi
);
4790 if (SAFI_MPLS_VPN
== safi
4791 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4792 vpn_leak_to_vrf_update(bgp
, new);
4795 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4796 safi
, new->type
, new->sub_type
, &label
);
4799 /* Unintern original. */
4800 aspath_unintern(&attr
.aspath
);
4803 /* Configure static BGP network. When user don't run zebra, static
4804 route should be installed as valid. */
4805 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4806 const char *ip_str
, afi_t afi
, safi_t safi
,
4807 const char *rmap
, int backdoor
, uint32_t label_index
)
4809 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4812 struct bgp_static
*bgp_static
;
4813 struct bgp_node
*rn
;
4814 uint8_t need_update
= 0;
4816 /* Convert IP prefix string to struct prefix. */
4817 ret
= str2prefix(ip_str
, &p
);
4819 vty_out(vty
, "%% Malformed prefix\n");
4820 return CMD_WARNING_CONFIG_FAILED
;
4822 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4823 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4824 return CMD_WARNING_CONFIG_FAILED
;
4831 /* Set BGP static route configuration. */
4832 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4835 vty_out(vty
, "%% Can't find static route specified\n");
4836 return CMD_WARNING_CONFIG_FAILED
;
4839 bgp_static
= rn
->info
;
4841 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4842 && (label_index
!= bgp_static
->label_index
)) {
4844 "%% label-index doesn't match static route\n");
4845 return CMD_WARNING_CONFIG_FAILED
;
4848 if ((rmap
&& bgp_static
->rmap
.name
)
4849 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4851 "%% route-map name doesn't match static route\n");
4852 return CMD_WARNING_CONFIG_FAILED
;
4855 /* Update BGP RIB. */
4856 if (!bgp_static
->backdoor
)
4857 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4859 /* Clear configuration. */
4860 bgp_static_free(bgp_static
);
4862 bgp_unlock_node(rn
);
4863 bgp_unlock_node(rn
);
4866 /* Set BGP static route configuration. */
4867 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4870 /* Configuration change. */
4871 bgp_static
= rn
->info
;
4873 /* Label index cannot be changed. */
4874 if (bgp_static
->label_index
!= label_index
) {
4875 vty_out(vty
, "%% cannot change label-index\n");
4876 return CMD_WARNING_CONFIG_FAILED
;
4879 /* Check previous routes are installed into BGP. */
4880 if (bgp_static
->valid
4881 && bgp_static
->backdoor
!= backdoor
)
4884 bgp_static
->backdoor
= backdoor
;
4887 if (bgp_static
->rmap
.name
)
4888 XFREE(MTYPE_ROUTE_MAP_NAME
,
4889 bgp_static
->rmap
.name
);
4890 bgp_static
->rmap
.name
=
4891 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4892 bgp_static
->rmap
.map
=
4893 route_map_lookup_by_name(rmap
);
4895 if (bgp_static
->rmap
.name
)
4896 XFREE(MTYPE_ROUTE_MAP_NAME
,
4897 bgp_static
->rmap
.name
);
4898 bgp_static
->rmap
.name
= NULL
;
4899 bgp_static
->rmap
.map
= NULL
;
4900 bgp_static
->valid
= 0;
4902 bgp_unlock_node(rn
);
4904 /* New configuration. */
4905 bgp_static
= bgp_static_new();
4906 bgp_static
->backdoor
= backdoor
;
4907 bgp_static
->valid
= 0;
4908 bgp_static
->igpmetric
= 0;
4909 bgp_static
->igpnexthop
.s_addr
= 0;
4910 bgp_static
->label_index
= label_index
;
4913 if (bgp_static
->rmap
.name
)
4914 XFREE(MTYPE_ROUTE_MAP_NAME
,
4915 bgp_static
->rmap
.name
);
4916 bgp_static
->rmap
.name
=
4917 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4918 bgp_static
->rmap
.map
=
4919 route_map_lookup_by_name(rmap
);
4921 rn
->info
= bgp_static
;
4924 bgp_static
->valid
= 1;
4926 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4928 if (!bgp_static
->backdoor
)
4929 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4935 void bgp_static_add(struct bgp
*bgp
)
4939 struct bgp_node
*rn
;
4940 struct bgp_node
*rm
;
4941 struct bgp_table
*table
;
4942 struct bgp_static
*bgp_static
;
4944 FOREACH_AFI_SAFI (afi
, safi
)
4945 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4946 rn
= bgp_route_next(rn
)) {
4947 if (rn
->info
== NULL
)
4950 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4951 || (safi
== SAFI_EVPN
)) {
4954 for (rm
= bgp_table_top(table
); rm
;
4955 rm
= bgp_route_next(rm
)) {
4956 bgp_static
= rm
->info
;
4957 bgp_static_update_safi(bgp
, &rm
->p
,
4962 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4968 /* Called from bgp_delete(). Delete all static routes from the BGP
4970 void bgp_static_delete(struct bgp
*bgp
)
4974 struct bgp_node
*rn
;
4975 struct bgp_node
*rm
;
4976 struct bgp_table
*table
;
4977 struct bgp_static
*bgp_static
;
4979 FOREACH_AFI_SAFI (afi
, safi
)
4980 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4981 rn
= bgp_route_next(rn
)) {
4982 if (rn
->info
== NULL
)
4985 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4986 || (safi
== SAFI_EVPN
)) {
4989 for (rm
= bgp_table_top(table
); rm
;
4990 rm
= bgp_route_next(rm
)) {
4991 bgp_static
= rm
->info
;
4992 bgp_static_withdraw_safi(
4993 bgp
, &rm
->p
, AFI_IP
, safi
,
4994 (struct prefix_rd
*)&rn
->p
);
4995 bgp_static_free(bgp_static
);
4997 bgp_unlock_node(rn
);
5000 bgp_static
= rn
->info
;
5001 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5002 bgp_static_free(bgp_static
);
5004 bgp_unlock_node(rn
);
5009 void bgp_static_redo_import_check(struct bgp
*bgp
)
5013 struct bgp_node
*rn
;
5014 struct bgp_node
*rm
;
5015 struct bgp_table
*table
;
5016 struct bgp_static
*bgp_static
;
5018 /* Use this flag to force reprocessing of the route */
5019 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5020 FOREACH_AFI_SAFI (afi
, safi
) {
5021 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5022 rn
= bgp_route_next(rn
)) {
5023 if (rn
->info
== NULL
)
5026 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5027 || (safi
== SAFI_EVPN
)) {
5030 for (rm
= bgp_table_top(table
); rm
;
5031 rm
= bgp_route_next(rm
)) {
5032 bgp_static
= rm
->info
;
5033 bgp_static_update_safi(bgp
, &rm
->p
,
5038 bgp_static
= rn
->info
;
5039 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5044 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5047 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5050 struct bgp_table
*table
;
5051 struct bgp_node
*rn
;
5052 struct bgp_info
*ri
;
5054 table
= bgp
->rib
[afi
][safi
];
5055 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5056 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5057 if (ri
->peer
== bgp
->peer_self
5058 && ((ri
->type
== ZEBRA_ROUTE_BGP
5059 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5060 || (ri
->type
!= ZEBRA_ROUTE_BGP
5062 == BGP_ROUTE_REDISTRIBUTE
))) {
5063 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5065 bgp_unlink_nexthop(ri
);
5066 bgp_info_delete(rn
, ri
);
5067 bgp_process(bgp
, rn
, afi
, safi
);
5074 * Purge all networks and redistributed routes from routing table.
5075 * Invoked upon the instance going down.
5077 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5082 FOREACH_AFI_SAFI (afi
, safi
)
5083 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5088 * Currently this is used to set static routes for VPN and ENCAP.
5089 * I think it can probably be factored with bgp_static_set.
5091 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5092 const char *ip_str
, const char *rd_str
,
5093 const char *label_str
, const char *rmap_str
,
5094 int evpn_type
, const char *esi
, const char *gwip
,
5095 const char *ethtag
, const char *routermac
)
5097 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5100 struct prefix_rd prd
;
5101 struct bgp_node
*prn
;
5102 struct bgp_node
*rn
;
5103 struct bgp_table
*table
;
5104 struct bgp_static
*bgp_static
;
5105 mpls_label_t label
= MPLS_INVALID_LABEL
;
5106 struct prefix gw_ip
;
5108 /* validate ip prefix */
5109 ret
= str2prefix(ip_str
, &p
);
5111 vty_out(vty
, "%% Malformed prefix\n");
5112 return CMD_WARNING_CONFIG_FAILED
;
5115 if ((afi
== AFI_L2VPN
)
5116 && (bgp_build_evpn_prefix(evpn_type
,
5117 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5118 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5119 return CMD_WARNING_CONFIG_FAILED
;
5122 ret
= str2prefix_rd(rd_str
, &prd
);
5124 vty_out(vty
, "%% Malformed rd\n");
5125 return CMD_WARNING_CONFIG_FAILED
;
5129 unsigned long label_val
;
5130 label_val
= strtoul(label_str
, NULL
, 10);
5131 encode_label(label_val
, &label
);
5134 if (safi
== SAFI_EVPN
) {
5135 if (esi
&& str2esi(esi
, NULL
) == 0) {
5136 vty_out(vty
, "%% Malformed ESI\n");
5137 return CMD_WARNING_CONFIG_FAILED
;
5139 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5140 vty_out(vty
, "%% Malformed Router MAC\n");
5141 return CMD_WARNING_CONFIG_FAILED
;
5144 memset(&gw_ip
, 0, sizeof(struct prefix
));
5145 ret
= str2prefix(gwip
, &gw_ip
);
5147 vty_out(vty
, "%% Malformed GatewayIp\n");
5148 return CMD_WARNING_CONFIG_FAILED
;
5150 if ((gw_ip
.family
== AF_INET
5151 && is_evpn_prefix_ipaddr_v6(
5152 (struct prefix_evpn
*)&p
))
5153 || (gw_ip
.family
== AF_INET6
5154 && is_evpn_prefix_ipaddr_v4(
5155 (struct prefix_evpn
*)&p
))) {
5157 "%% GatewayIp family differs with IP prefix\n");
5158 return CMD_WARNING_CONFIG_FAILED
;
5162 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5163 if (prn
->info
== NULL
)
5164 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5166 bgp_unlock_node(prn
);
5169 rn
= bgp_node_get(table
, &p
);
5172 vty_out(vty
, "%% Same network configuration exists\n");
5173 bgp_unlock_node(rn
);
5175 /* New configuration. */
5176 bgp_static
= bgp_static_new();
5177 bgp_static
->backdoor
= 0;
5178 bgp_static
->valid
= 0;
5179 bgp_static
->igpmetric
= 0;
5180 bgp_static
->igpnexthop
.s_addr
= 0;
5181 bgp_static
->label
= label
;
5182 bgp_static
->prd
= prd
;
5185 if (bgp_static
->rmap
.name
)
5186 XFREE(MTYPE_ROUTE_MAP_NAME
,
5187 bgp_static
->rmap
.name
);
5188 bgp_static
->rmap
.name
=
5189 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5190 bgp_static
->rmap
.map
=
5191 route_map_lookup_by_name(rmap_str
);
5194 if (safi
== SAFI_EVPN
) {
5196 bgp_static
->eth_s_id
=
5198 sizeof(struct eth_segment_id
));
5199 str2esi(esi
, bgp_static
->eth_s_id
);
5202 bgp_static
->router_mac
=
5203 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5204 (void)prefix_str2mac(routermac
,
5205 bgp_static
->router_mac
);
5208 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5210 rn
->info
= bgp_static
;
5212 bgp_static
->valid
= 1;
5213 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5219 /* Configure static BGP network. */
5220 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5221 const char *ip_str
, const char *rd_str
,
5222 const char *label_str
, int evpn_type
, const char *esi
,
5223 const char *gwip
, const char *ethtag
)
5225 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5228 struct prefix_rd prd
;
5229 struct bgp_node
*prn
;
5230 struct bgp_node
*rn
;
5231 struct bgp_table
*table
;
5232 struct bgp_static
*bgp_static
;
5233 mpls_label_t label
= MPLS_INVALID_LABEL
;
5235 /* Convert IP prefix string to struct prefix. */
5236 ret
= str2prefix(ip_str
, &p
);
5238 vty_out(vty
, "%% Malformed prefix\n");
5239 return CMD_WARNING_CONFIG_FAILED
;
5242 if ((afi
== AFI_L2VPN
)
5243 && (bgp_build_evpn_prefix(evpn_type
,
5244 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5245 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5246 return CMD_WARNING_CONFIG_FAILED
;
5248 ret
= str2prefix_rd(rd_str
, &prd
);
5250 vty_out(vty
, "%% Malformed rd\n");
5251 return CMD_WARNING_CONFIG_FAILED
;
5255 unsigned long label_val
;
5256 label_val
= strtoul(label_str
, NULL
, 10);
5257 encode_label(label_val
, &label
);
5260 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5261 if (prn
->info
== NULL
)
5262 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5264 bgp_unlock_node(prn
);
5267 rn
= bgp_node_lookup(table
, &p
);
5270 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5272 bgp_static
= rn
->info
;
5273 bgp_static_free(bgp_static
);
5275 bgp_unlock_node(rn
);
5276 bgp_unlock_node(rn
);
5278 vty_out(vty
, "%% Can't find the route\n");
5283 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5284 const char *rmap_name
)
5286 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5287 struct bgp_rmap
*rmap
;
5289 rmap
= &bgp
->table_map
[afi
][safi
];
5292 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5293 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5294 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5297 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5302 if (bgp_fibupd_safi(safi
))
5303 bgp_zebra_announce_table(bgp
, afi
, safi
);
5308 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5309 const char *rmap_name
)
5311 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5312 struct bgp_rmap
*rmap
;
5314 rmap
= &bgp
->table_map
[afi
][safi
];
5316 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5320 if (bgp_fibupd_safi(safi
))
5321 bgp_zebra_announce_table(bgp
, afi
, safi
);
5326 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5329 if (bgp
->table_map
[afi
][safi
].name
) {
5330 vty_out(vty
, " table-map %s\n",
5331 bgp
->table_map
[afi
][safi
].name
);
5335 DEFUN (bgp_table_map
,
5338 "BGP table to RIB route download filter\n"
5339 "Name of the route map\n")
5342 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5343 argv
[idx_word
]->arg
);
5345 DEFUN (no_bgp_table_map
,
5346 no_bgp_table_map_cmd
,
5347 "no table-map WORD",
5349 "BGP table to RIB route download filter\n"
5350 "Name of the route map\n")
5353 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5354 argv
[idx_word
]->arg
);
5360 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5361 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5362 backdoor$backdoor}]",
5364 "Specify a network to announce via BGP\n"
5369 "Route-map to modify the attributes\n"
5370 "Name of the route map\n"
5371 "Label index to associate with the prefix\n"
5372 "Label index value\n"
5373 "Specify a BGP backdoor route\n")
5375 char addr_prefix_str
[BUFSIZ
];
5380 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5383 vty_out(vty
, "%% Inconsistent address and mask\n");
5384 return CMD_WARNING_CONFIG_FAILED
;
5388 return bgp_static_set(
5389 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5390 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5391 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5394 DEFPY(ipv6_bgp_network
,
5395 ipv6_bgp_network_cmd
,
5396 "[no] network X:X::X:X/M$prefix \
5397 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5399 "Specify a network to announce via BGP\n"
5401 "Route-map to modify the attributes\n"
5402 "Name of the route map\n"
5403 "Label index to associate with the prefix\n"
5404 "Label index value\n")
5406 return bgp_static_set(
5407 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5408 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5411 /* Aggreagete address:
5413 advertise-map Set condition to advertise attribute
5414 as-set Generate AS set path information
5415 attribute-map Set attributes of aggregate
5416 route-map Set parameters of aggregate
5417 summary-only Filter more specific routes from updates
5418 suppress-map Conditionally filter more specific routes from updates
5421 struct bgp_aggregate
{
5422 /* Summary-only flag. */
5423 uint8_t summary_only
;
5425 /* AS set generation. */
5428 /* Route-map for aggregated route. */
5429 struct route_map
*map
;
5431 /* Suppress-count. */
5432 unsigned long count
;
5434 /* SAFI configuration. */
5438 static struct bgp_aggregate
*bgp_aggregate_new(void)
5440 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5443 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5445 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5448 static int bgp_aggregate_info_same(struct bgp_info
*ri
, struct aspath
*aspath
,
5449 struct community
*comm
)
5451 static struct aspath
*ae
= NULL
;
5454 ae
= aspath_empty();
5459 if (!aspath_cmp(ri
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5462 if (!community_cmp(ri
->attr
->community
, comm
))
5468 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5469 struct prefix
*p
, uint8_t origin
,
5470 struct aspath
*aspath
,
5471 struct community
*community
,
5472 uint8_t atomic_aggregate
,
5473 struct bgp_aggregate
*aggregate
)
5475 struct bgp_node
*rn
;
5476 struct bgp_table
*table
;
5477 struct bgp_info
*ri
, *new;
5479 table
= bgp
->rib
[afi
][safi
];
5481 rn
= bgp_node_get(table
, p
);
5483 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5484 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5485 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5488 if (aggregate
->count
> 0) {
5490 * If the aggregate information has not changed
5491 * no need to re-install it again.
5493 if (bgp_aggregate_info_same(rn
->info
, aspath
, community
)) {
5494 bgp_unlock_node(rn
);
5497 aspath_free(aspath
);
5499 community_free(community
);
5505 * Mark the old as unusable
5508 bgp_info_delete(rn
, ri
);
5511 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5512 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5513 community
, aggregate
->as_set
,
5516 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5518 bgp_info_add(rn
, new);
5519 bgp_process(bgp
, rn
, afi
, safi
);
5521 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5522 if (ri
->peer
== bgp
->peer_self
5523 && ri
->type
== ZEBRA_ROUTE_BGP
5524 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5527 /* Withdraw static BGP route from routing table. */
5529 bgp_info_delete(rn
, ri
);
5530 bgp_process(bgp
, rn
, afi
, safi
);
5534 bgp_unlock_node(rn
);
5537 /* Update an aggregate as routes are added/removed from the BGP table */
5538 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5539 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5540 struct bgp_info
*del
,
5541 struct bgp_aggregate
*aggregate
)
5543 struct bgp_table
*table
;
5544 struct bgp_node
*top
;
5545 struct bgp_node
*rn
;
5547 struct aspath
*aspath
= NULL
;
5548 struct aspath
*asmerge
= NULL
;
5549 struct community
*community
= NULL
;
5550 struct community
*commerge
= NULL
;
5551 struct bgp_info
*ri
;
5552 unsigned long match
= 0;
5553 uint8_t atomic_aggregate
= 0;
5555 /* ORIGIN attribute: If at least one route among routes that are
5556 aggregated has ORIGIN with the value INCOMPLETE, then the
5557 aggregated route must have the ORIGIN attribute with the value
5558 INCOMPLETE. Otherwise, if at least one route among routes that
5559 are aggregated has ORIGIN with the value EGP, then the aggregated
5560 route must have the origin attribute with the value EGP. In all
5561 other case the value of the ORIGIN attribute of the aggregated
5562 route is INTERNAL. */
5563 origin
= BGP_ORIGIN_IGP
;
5565 table
= bgp
->rib
[afi
][safi
];
5567 top
= bgp_node_get(table
, p
);
5568 for (rn
= bgp_node_get(table
, p
); rn
;
5569 rn
= bgp_route_next_until(rn
, top
)) {
5570 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5575 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5576 if (BGP_INFO_HOLDDOWN(ri
))
5579 if (del
&& ri
== del
)
5583 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5584 atomic_aggregate
= 1;
5586 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5590 * summary-only aggregate route suppress
5591 * aggregated route announcements.
5593 if (aggregate
->summary_only
) {
5594 (bgp_info_extra_get(ri
))->suppress
++;
5595 bgp_info_set_flag(rn
, ri
,
5596 BGP_INFO_ATTR_CHANGED
);
5603 * If at least one route among routes that are
5604 * aggregated has ORIGIN with the value INCOMPLETE,
5605 * then the aggregated route MUST have the ORIGIN
5606 * attribute with the value INCOMPLETE. Otherwise, if
5607 * at least one route among routes that are aggregated
5608 * has ORIGIN with the value EGP, then the aggregated
5609 * route MUST have the ORIGIN attribute with the value
5612 if (origin
< ri
->attr
->origin
)
5613 origin
= ri
->attr
->origin
;
5615 if (!aggregate
->as_set
)
5619 * as-set aggregate route generate origin, as path,
5620 * and community aggregation.
5623 asmerge
= aspath_aggregate(aspath
,
5625 aspath_free(aspath
);
5628 aspath
= aspath_dup(ri
->attr
->aspath
);
5630 if (!ri
->attr
->community
)
5634 commerge
= community_merge(community
,
5635 ri
->attr
->community
);
5636 community
= community_uniq_sort(commerge
);
5637 community_free(commerge
);
5639 community
= community_dup(ri
->attr
->community
);
5642 bgp_process(bgp
, rn
, afi
, safi
);
5644 bgp_unlock_node(top
);
5649 if (aggregate
->summary_only
)
5650 (bgp_info_extra_get(rinew
))->suppress
++;
5652 if (origin
< rinew
->attr
->origin
)
5653 origin
= rinew
->attr
->origin
;
5655 if (aggregate
->as_set
) {
5657 asmerge
= aspath_aggregate(aspath
,
5658 rinew
->attr
->aspath
);
5659 aspath_free(aspath
);
5662 aspath
= aspath_dup(rinew
->attr
->aspath
);
5664 if (rinew
->attr
->community
) {
5666 commerge
= community_merge(
5668 rinew
->attr
->community
);
5670 community_uniq_sort(commerge
);
5671 community_free(commerge
);
5673 community
= community_dup(
5674 rinew
->attr
->community
);
5679 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5680 atomic_aggregate
, aggregate
);
5682 if (aggregate
->count
== 0) {
5684 aspath_free(aspath
);
5686 community_free(community
);
5690 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5691 safi_t safi
, struct bgp_aggregate
*aggregate
)
5693 struct bgp_table
*table
;
5694 struct bgp_node
*top
;
5695 struct bgp_node
*rn
;
5696 struct bgp_info
*ri
;
5697 unsigned long match
;
5699 table
= bgp
->rib
[afi
][safi
];
5701 /* If routes exists below this node, generate aggregate routes. */
5702 top
= bgp_node_get(table
, p
);
5703 for (rn
= bgp_node_get(table
, p
); rn
;
5704 rn
= bgp_route_next_until(rn
, top
)) {
5705 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5709 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5710 if (BGP_INFO_HOLDDOWN(ri
))
5713 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5716 if (aggregate
->summary_only
&& ri
->extra
) {
5717 ri
->extra
->suppress
--;
5719 if (ri
->extra
->suppress
== 0) {
5721 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5728 /* If this node was suppressed, process the change. */
5730 bgp_process(bgp
, rn
, afi
, safi
);
5732 bgp_unlock_node(top
);
5735 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5736 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5738 struct bgp_node
*child
;
5739 struct bgp_node
*rn
;
5740 struct bgp_aggregate
*aggregate
;
5741 struct bgp_table
*table
;
5743 table
= bgp
->aggregate
[afi
][safi
];
5745 /* No aggregates configured. */
5746 if (bgp_table_top_nolock(table
) == NULL
)
5749 if (p
->prefixlen
== 0)
5752 if (BGP_INFO_HOLDDOWN(ri
))
5755 child
= bgp_node_get(table
, p
);
5757 /* Aggregate address configuration check. */
5758 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5759 if ((aggregate
= rn
->info
) != NULL
5760 && rn
->p
.prefixlen
< p
->prefixlen
) {
5761 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5762 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5765 bgp_unlock_node(child
);
5768 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5769 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5771 struct bgp_node
*child
;
5772 struct bgp_node
*rn
;
5773 struct bgp_aggregate
*aggregate
;
5774 struct bgp_table
*table
;
5776 table
= bgp
->aggregate
[afi
][safi
];
5778 /* No aggregates configured. */
5779 if (bgp_table_top_nolock(table
) == NULL
)
5782 if (p
->prefixlen
== 0)
5785 child
= bgp_node_get(table
, p
);
5787 /* Aggregate address configuration check. */
5788 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5789 if ((aggregate
= rn
->info
) != NULL
5790 && rn
->p
.prefixlen
< p
->prefixlen
) {
5791 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5792 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5795 bgp_unlock_node(child
);
5798 /* Aggregate route attribute. */
5799 #define AGGREGATE_SUMMARY_ONLY 1
5800 #define AGGREGATE_AS_SET 1
5802 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5803 afi_t afi
, safi_t safi
)
5805 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5808 struct bgp_node
*rn
;
5809 struct bgp_aggregate
*aggregate
;
5811 /* Convert string to prefix structure. */
5812 ret
= str2prefix(prefix_str
, &p
);
5814 vty_out(vty
, "Malformed prefix\n");
5815 return CMD_WARNING_CONFIG_FAILED
;
5819 /* Old configuration check. */
5820 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5823 "%% There is no aggregate-address configuration.\n");
5824 return CMD_WARNING_CONFIG_FAILED
;
5827 aggregate
= rn
->info
;
5828 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5829 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
, 0, aggregate
);
5831 /* Unlock aggregate address configuration. */
5833 bgp_aggregate_free(aggregate
);
5834 bgp_unlock_node(rn
);
5835 bgp_unlock_node(rn
);
5840 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5841 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5843 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5846 struct bgp_node
*rn
;
5847 struct bgp_aggregate
*aggregate
;
5849 /* Convert string to prefix structure. */
5850 ret
= str2prefix(prefix_str
, &p
);
5852 vty_out(vty
, "Malformed prefix\n");
5853 return CMD_WARNING_CONFIG_FAILED
;
5857 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5858 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5859 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5861 return CMD_WARNING_CONFIG_FAILED
;
5864 /* Old configuration check. */
5865 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5868 vty_out(vty
, "There is already same aggregate network.\n");
5869 /* try to remove the old entry */
5870 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5872 vty_out(vty
, "Error deleting aggregate.\n");
5873 bgp_unlock_node(rn
);
5874 return CMD_WARNING_CONFIG_FAILED
;
5878 /* Make aggregate address structure. */
5879 aggregate
= bgp_aggregate_new();
5880 aggregate
->summary_only
= summary_only
;
5881 aggregate
->as_set
= as_set
;
5882 aggregate
->safi
= safi
;
5883 rn
->info
= aggregate
;
5885 /* Aggregate address insert into BGP routing table. */
5886 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
5891 DEFUN (aggregate_address
,
5892 aggregate_address_cmd
,
5893 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5894 "Configure BGP aggregate entries\n"
5895 "Aggregate prefix\n"
5896 "Generate AS set path information\n"
5897 "Filter more specific routes from updates\n"
5898 "Filter more specific routes from updates\n"
5899 "Generate AS set path information\n")
5902 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5903 char *prefix
= argv
[idx
]->arg
;
5905 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5907 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5908 ? AGGREGATE_SUMMARY_ONLY
5911 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5912 summary_only
, as_set
);
5915 DEFUN (aggregate_address_mask
,
5916 aggregate_address_mask_cmd
,
5917 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5918 "Configure BGP aggregate entries\n"
5919 "Aggregate address\n"
5921 "Generate AS set path information\n"
5922 "Filter more specific routes from updates\n"
5923 "Filter more specific routes from updates\n"
5924 "Generate AS set path information\n")
5927 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5928 char *prefix
= argv
[idx
]->arg
;
5929 char *mask
= argv
[idx
+ 1]->arg
;
5931 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5933 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5934 ? AGGREGATE_SUMMARY_ONLY
5937 char prefix_str
[BUFSIZ
];
5938 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5941 vty_out(vty
, "%% Inconsistent address and mask\n");
5942 return CMD_WARNING_CONFIG_FAILED
;
5945 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5946 summary_only
, as_set
);
5949 DEFUN (no_aggregate_address
,
5950 no_aggregate_address_cmd
,
5951 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5953 "Configure BGP aggregate entries\n"
5954 "Aggregate prefix\n"
5955 "Generate AS set path information\n"
5956 "Filter more specific routes from updates\n"
5957 "Filter more specific routes from updates\n"
5958 "Generate AS set path information\n")
5961 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5962 char *prefix
= argv
[idx
]->arg
;
5963 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5966 DEFUN (no_aggregate_address_mask
,
5967 no_aggregate_address_mask_cmd
,
5968 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5970 "Configure BGP aggregate entries\n"
5971 "Aggregate address\n"
5973 "Generate AS set path information\n"
5974 "Filter more specific routes from updates\n"
5975 "Filter more specific routes from updates\n"
5976 "Generate AS set path information\n")
5979 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5980 char *prefix
= argv
[idx
]->arg
;
5981 char *mask
= argv
[idx
+ 1]->arg
;
5983 char prefix_str
[BUFSIZ
];
5984 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5987 vty_out(vty
, "%% Inconsistent address and mask\n");
5988 return CMD_WARNING_CONFIG_FAILED
;
5991 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5994 DEFUN (ipv6_aggregate_address
,
5995 ipv6_aggregate_address_cmd
,
5996 "aggregate-address X:X::X:X/M [summary-only]",
5997 "Configure BGP aggregate entries\n"
5998 "Aggregate prefix\n"
5999 "Filter more specific routes from updates\n")
6002 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6003 char *prefix
= argv
[idx
]->arg
;
6004 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6005 ? AGGREGATE_SUMMARY_ONLY
6007 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6011 DEFUN (no_ipv6_aggregate_address
,
6012 no_ipv6_aggregate_address_cmd
,
6013 "no aggregate-address X:X::X:X/M [summary-only]",
6015 "Configure BGP aggregate entries\n"
6016 "Aggregate prefix\n"
6017 "Filter more specific routes from updates\n")
6020 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6021 char *prefix
= argv
[idx
]->arg
;
6022 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6025 /* Redistribute route treatment. */
6026 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6027 const union g_addr
*nexthop
, ifindex_t ifindex
,
6028 enum nexthop_types_t nhtype
, uint32_t metric
,
6029 uint8_t type
, unsigned short instance
,
6032 struct bgp_info
*new;
6033 struct bgp_info
*bi
;
6034 struct bgp_info info
;
6035 struct bgp_node
*bn
;
6037 struct attr
*new_attr
;
6040 struct bgp_redist
*red
;
6042 /* Make default attribute. */
6043 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6046 case NEXTHOP_TYPE_IFINDEX
:
6048 case NEXTHOP_TYPE_IPV4
:
6049 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6050 attr
.nexthop
= nexthop
->ipv4
;
6052 case NEXTHOP_TYPE_IPV6
:
6053 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6054 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6055 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6057 case NEXTHOP_TYPE_BLACKHOLE
:
6058 switch (p
->family
) {
6060 attr
.nexthop
.s_addr
= INADDR_ANY
;
6063 memset(&attr
.mp_nexthop_global
, 0,
6064 sizeof(attr
.mp_nexthop_global
));
6065 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6070 attr
.nh_ifindex
= ifindex
;
6073 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6076 afi
= family2afi(p
->family
);
6078 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6080 struct attr attr_new
;
6082 /* Copy attribute for modification. */
6083 bgp_attr_dup(&attr_new
, &attr
);
6085 if (red
->redist_metric_flag
)
6086 attr_new
.med
= red
->redist_metric
;
6088 /* Apply route-map. */
6089 if (red
->rmap
.name
) {
6090 memset(&info
, 0, sizeof(struct bgp_info
));
6091 info
.peer
= bgp
->peer_self
;
6092 info
.attr
= &attr_new
;
6094 SET_FLAG(bgp
->peer_self
->rmap_type
,
6095 PEER_RMAP_TYPE_REDISTRIBUTE
);
6097 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6100 bgp
->peer_self
->rmap_type
= 0;
6102 if (ret
== RMAP_DENYMATCH
) {
6103 /* Free uninterned attribute. */
6104 bgp_attr_flush(&attr_new
);
6106 /* Unintern original. */
6107 aspath_unintern(&attr
.aspath
);
6108 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6113 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6114 bgp_attr_add_gshut_community(&attr_new
);
6116 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6117 SAFI_UNICAST
, p
, NULL
);
6119 new_attr
= bgp_attr_intern(&attr_new
);
6121 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6122 if (bi
->peer
== bgp
->peer_self
6123 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6127 /* Ensure the (source route) type is updated. */
6129 if (attrhash_cmp(bi
->attr
, new_attr
)
6130 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6131 bgp_attr_unintern(&new_attr
);
6132 aspath_unintern(&attr
.aspath
);
6133 bgp_unlock_node(bn
);
6136 /* The attribute is changed. */
6137 bgp_info_set_flag(bn
, bi
,
6138 BGP_INFO_ATTR_CHANGED
);
6140 /* Rewrite BGP route information. */
6141 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6142 bgp_info_restore(bn
, bi
);
6144 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6146 bgp_attr_unintern(&bi
->attr
);
6147 bi
->attr
= new_attr
;
6148 bi
->uptime
= bgp_clock();
6150 /* Process change. */
6151 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6153 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6154 bgp_unlock_node(bn
);
6155 aspath_unintern(&attr
.aspath
);
6157 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6159 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6161 vpn_leak_from_vrf_update(
6162 bgp_get_default(), bgp
, bi
);
6168 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6169 bgp
->peer_self
, new_attr
, bn
);
6170 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6172 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6173 bgp_info_add(bn
, new);
6174 bgp_unlock_node(bn
);
6175 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6177 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6178 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6180 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6184 /* Unintern original. */
6185 aspath_unintern(&attr
.aspath
);
6188 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6189 unsigned short instance
)
6192 struct bgp_node
*rn
;
6193 struct bgp_info
*ri
;
6194 struct bgp_redist
*red
;
6196 afi
= family2afi(p
->family
);
6198 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6200 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6201 SAFI_UNICAST
, p
, NULL
);
6203 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6204 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6208 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6209 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6211 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6214 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6215 bgp_info_delete(rn
, ri
);
6216 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6218 bgp_unlock_node(rn
);
6222 /* Withdraw specified route type's route. */
6223 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6224 unsigned short instance
)
6226 struct bgp_node
*rn
;
6227 struct bgp_info
*ri
;
6228 struct bgp_table
*table
;
6230 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6232 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6233 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6234 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6235 && ri
->instance
== instance
)
6239 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6240 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6242 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6245 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6247 bgp_info_delete(rn
, ri
);
6248 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6253 /* Static function to display route. */
6254 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6260 if (p
->family
== AF_INET
) {
6264 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6267 json_object_string_add(json
, "prefix",
6268 inet_ntop(p
->family
,
6271 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6273 } else if (p
->family
== AF_ETHERNET
) {
6274 prefix2str(p
, buf
, PREFIX_STRLEN
);
6275 len
= vty_out(vty
, "%s", buf
);
6276 } else if (p
->family
== AF_EVPN
) {
6280 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6283 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6284 } else if (p
->family
== AF_FLOWSPEC
) {
6285 route_vty_out_flowspec(vty
, p
, NULL
,
6287 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6288 NLRI_STRING_FORMAT_MIN
, json
);
6293 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6300 vty_out(vty
, "\n%*s", 20, " ");
6302 vty_out(vty
, "%*s", len
, " ");
6306 enum bgp_display_type
{
6310 /* Print the short form route status for a bgp_info */
6311 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6312 json_object
*json_path
)
6316 /* Route status display. */
6317 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6318 json_object_boolean_true_add(json_path
, "removed");
6320 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6321 json_object_boolean_true_add(json_path
, "stale");
6323 if (binfo
->extra
&& binfo
->extra
->suppress
)
6324 json_object_boolean_true_add(json_path
, "suppressed");
6326 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6327 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6328 json_object_boolean_true_add(json_path
, "valid");
6331 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6332 json_object_boolean_true_add(json_path
, "history");
6334 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6335 json_object_boolean_true_add(json_path
, "damped");
6337 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6338 json_object_boolean_true_add(json_path
, "bestpath");
6340 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6341 json_object_boolean_true_add(json_path
, "multipath");
6343 /* Internal route. */
6344 if ((binfo
->peer
->as
)
6345 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6346 json_object_string_add(json_path
, "pathFrom",
6349 json_object_string_add(json_path
, "pathFrom",
6355 /* Route status display. */
6356 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6358 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6360 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6362 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6363 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6369 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6371 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6373 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6375 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6380 /* Internal route. */
6381 if (binfo
->peer
&& (binfo
->peer
->as
)
6382 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6388 /* called from terminal list command */
6389 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6390 int display
, safi_t safi
, json_object
*json_paths
)
6393 json_object
*json_path
= NULL
;
6394 json_object
*json_nexthops
= NULL
;
6395 json_object
*json_nexthop_global
= NULL
;
6396 json_object
*json_nexthop_ll
= NULL
;
6397 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6398 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6401 bool nexthop_othervrf
= false;
6402 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6403 const char *nexthop_vrfname
= "Default";
6406 json_path
= json_object_new_object();
6408 /* short status lead text */
6409 route_vty_short_status_out(vty
, binfo
, json_path
);
6412 /* print prefix and mask */
6414 route_vty_out_route(p
, vty
, json_path
);
6416 vty_out(vty
, "%*s", 17, " ");
6418 route_vty_out_route(p
, vty
, json_path
);
6421 /* Print attribute */
6425 json_object_array_add(json_paths
, json_path
);
6433 * If vrf id of nexthop is different from that of prefix,
6434 * set up printable string to append
6436 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6437 const char *self
= "";
6442 nexthop_othervrf
= true;
6443 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6445 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6446 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6447 "@%s%s", VRFID_NONE_STR
, self
);
6449 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6450 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6452 if (binfo
->extra
->bgp_orig
->inst_type
!=
6453 BGP_INSTANCE_TYPE_DEFAULT
)
6455 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6457 const char *self
= "";
6462 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6466 * For ENCAP and EVPN routes, nexthop address family is not
6467 * neccessarily the same as the prefix address family.
6468 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6469 * EVPN routes are also exchanged with a MP nexthop. Currently,
6471 * is only IPv4, the value will be present in either
6473 * attr->mp_nexthop_global_in
6475 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6478 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6482 sprintf(nexthop
, "%s",
6483 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6487 sprintf(nexthop
, "%s",
6488 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6492 sprintf(nexthop
, "?");
6497 json_nexthop_global
= json_object_new_object();
6499 json_object_string_add(json_nexthop_global
, "afi",
6500 (af
== AF_INET
) ? "ip" : "ipv6");
6501 json_object_string_add(json_nexthop_global
,
6502 (af
== AF_INET
) ? "ip" : "ipv6",
6504 json_object_boolean_true_add(json_nexthop_global
,
6507 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6508 } else if (safi
== SAFI_EVPN
) {
6510 json_nexthop_global
= json_object_new_object();
6512 json_object_string_add(json_nexthop_global
, "ip",
6513 inet_ntoa(attr
->nexthop
));
6514 json_object_string_add(json_nexthop_global
, "afi",
6516 json_object_boolean_true_add(json_nexthop_global
,
6519 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6521 } else if (safi
== SAFI_FLOWSPEC
) {
6522 if (attr
->nexthop
.s_addr
!= 0) {
6524 json_nexthop_global
= json_object_new_object();
6525 json_object_string_add(
6526 json_nexthop_global
, "ip",
6527 inet_ntoa(attr
->nexthop
));
6528 json_object_string_add(json_nexthop_global
,
6530 json_object_boolean_true_add(json_nexthop_global
,
6533 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6536 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6538 json_nexthop_global
= json_object_new_object();
6540 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6541 json_object_string_add(
6542 json_nexthop_global
, "ip",
6543 inet_ntoa(attr
->mp_nexthop_global_in
));
6545 json_object_string_add(
6546 json_nexthop_global
, "ip",
6547 inet_ntoa(attr
->nexthop
));
6549 json_object_string_add(json_nexthop_global
, "afi",
6551 json_object_boolean_true_add(json_nexthop_global
,
6556 snprintf(buf
, sizeof(buf
), "%s%s",
6557 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6558 vty_out(vty
, "%-16s", buf
);
6563 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6568 json_nexthop_global
= json_object_new_object();
6569 json_object_string_add(
6570 json_nexthop_global
, "ip",
6571 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6573 json_object_string_add(json_nexthop_global
, "afi",
6575 json_object_string_add(json_nexthop_global
, "scope",
6578 /* We display both LL & GL if both have been
6580 if ((attr
->mp_nexthop_len
== 32)
6581 || (binfo
->peer
->conf_if
)) {
6582 json_nexthop_ll
= json_object_new_object();
6583 json_object_string_add(
6584 json_nexthop_ll
, "ip",
6586 &attr
->mp_nexthop_local
, buf
,
6588 json_object_string_add(json_nexthop_ll
, "afi",
6590 json_object_string_add(json_nexthop_ll
, "scope",
6593 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6594 &attr
->mp_nexthop_local
)
6596 && !attr
->mp_nexthop_prefer_global
)
6597 json_object_boolean_true_add(
6598 json_nexthop_ll
, "used");
6600 json_object_boolean_true_add(
6601 json_nexthop_global
, "used");
6603 json_object_boolean_true_add(
6604 json_nexthop_global
, "used");
6606 /* Display LL if LL/Global both in table unless
6607 * prefer-global is set */
6608 if (((attr
->mp_nexthop_len
== 32)
6609 && !attr
->mp_nexthop_prefer_global
)
6610 || (binfo
->peer
->conf_if
)) {
6611 if (binfo
->peer
->conf_if
) {
6612 len
= vty_out(vty
, "%s",
6613 binfo
->peer
->conf_if
);
6614 len
= 16 - len
; /* len of IPv6
6620 vty_out(vty
, "\n%*s", 36, " ");
6622 vty_out(vty
, "%*s", len
, " ");
6628 &attr
->mp_nexthop_local
,
6634 vty_out(vty
, "\n%*s", 36, " ");
6636 vty_out(vty
, "%*s", len
, " ");
6642 &attr
->mp_nexthop_global
, buf
,
6648 vty_out(vty
, "\n%*s", 36, " ");
6650 vty_out(vty
, "%*s", len
, " ");
6656 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6658 json_object_int_add(json_path
, "med", attr
->med
);
6660 vty_out(vty
, "%10u", attr
->med
);
6661 else if (!json_paths
)
6665 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6667 json_object_int_add(json_path
, "localpref",
6670 vty_out(vty
, "%7u", attr
->local_pref
);
6671 else if (!json_paths
)
6675 json_object_int_add(json_path
, "weight", attr
->weight
);
6677 vty_out(vty
, "%7u ", attr
->weight
);
6681 json_object_string_add(
6682 json_path
, "peerId",
6683 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6689 json_object_string_add(json_path
, "aspath",
6692 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6697 json_object_string_add(json_path
, "origin",
6698 bgp_origin_long_str
[attr
->origin
]);
6700 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6704 json_object_boolean_true_add(json_path
,
6705 "announceNexthopSelf");
6706 if (nexthop_othervrf
) {
6707 json_object_string_add(json_path
, "nhVrfName",
6710 json_object_int_add(json_path
, "nhVrfId",
6711 ((nexthop_vrfid
== VRF_UNKNOWN
)
6713 : (int)nexthop_vrfid
));
6718 if (json_nexthop_global
|| json_nexthop_ll
) {
6719 json_nexthops
= json_object_new_array();
6721 if (json_nexthop_global
)
6722 json_object_array_add(json_nexthops
,
6723 json_nexthop_global
);
6725 if (json_nexthop_ll
)
6726 json_object_array_add(json_nexthops
,
6729 json_object_object_add(json_path
, "nexthops",
6733 json_object_array_add(json_paths
, json_path
);
6737 /* prints an additional line, indented, with VNC info, if
6739 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6740 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6745 /* called from terminal list command */
6746 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6747 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6749 json_object
*json_status
= NULL
;
6750 json_object
*json_net
= NULL
;
6752 /* Route status display. */
6754 json_status
= json_object_new_object();
6755 json_net
= json_object_new_object();
6762 /* print prefix and mask */
6764 json_object_string_add(
6765 json_net
, "addrPrefix",
6766 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6768 route_vty_out_route(p
, vty
, NULL
);
6770 /* Print attribute */
6773 if (p
->family
== AF_INET
6774 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6775 || safi
== SAFI_EVPN
6776 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6777 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6778 || safi
== SAFI_EVPN
)
6779 json_object_string_add(
6780 json_net
, "nextHop",
6782 attr
->mp_nexthop_global_in
));
6784 json_object_string_add(
6785 json_net
, "nextHop",
6786 inet_ntoa(attr
->nexthop
));
6787 } else if (p
->family
== AF_INET6
6788 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6791 json_object_string_add(
6792 json_net
, "netHopGloabal",
6794 &attr
->mp_nexthop_global
, buf
,
6799 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6800 json_object_int_add(json_net
, "metric",
6803 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6804 json_object_int_add(json_net
, "localPref",
6807 json_object_int_add(json_net
, "weight", attr
->weight
);
6811 json_object_string_add(json_net
, "asPath",
6815 json_object_string_add(json_net
, "bgpOriginCode",
6816 bgp_origin_str
[attr
->origin
]);
6818 if (p
->family
== AF_INET
6819 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6820 || safi
== SAFI_EVPN
6821 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6822 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6823 || safi
== SAFI_EVPN
)
6824 vty_out(vty
, "%-16s",
6826 attr
->mp_nexthop_global_in
));
6828 vty_out(vty
, "%-16s",
6829 inet_ntoa(attr
->nexthop
));
6830 } else if (p
->family
== AF_INET6
6831 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6838 &attr
->mp_nexthop_global
, buf
,
6842 vty_out(vty
, "\n%*s", 36, " ");
6844 vty_out(vty
, "%*s", len
, " ");
6847 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6848 vty_out(vty
, "%10u", attr
->med
);
6852 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6853 vty_out(vty
, "%7u", attr
->local_pref
);
6857 vty_out(vty
, "%7u ", attr
->weight
);
6861 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6864 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6868 json_object_boolean_true_add(json_status
, "*");
6869 json_object_boolean_true_add(json_status
, ">");
6870 json_object_object_add(json_net
, "appliedStatusSymbols",
6872 char buf_cut
[BUFSIZ
];
6873 json_object_object_add(
6875 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6881 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6882 struct bgp_info
*binfo
, int display
, safi_t safi
,
6885 json_object
*json_out
= NULL
;
6887 mpls_label_t label
= MPLS_INVALID_LABEL
;
6893 json_out
= json_object_new_object();
6895 /* short status lead text */
6896 route_vty_short_status_out(vty
, binfo
, json_out
);
6898 /* print prefix and mask */
6901 route_vty_out_route(p
, vty
, NULL
);
6903 vty_out(vty
, "%*s", 17, " ");
6906 /* Print attribute */
6909 if (((p
->family
== AF_INET
)
6910 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6911 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6912 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6913 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6914 || safi
== SAFI_EVPN
) {
6916 json_object_string_add(
6917 json_out
, "mpNexthopGlobalIn",
6919 attr
->mp_nexthop_global_in
));
6921 vty_out(vty
, "%-16s",
6923 attr
->mp_nexthop_global_in
));
6926 json_object_string_add(
6927 json_out
, "nexthop",
6928 inet_ntoa(attr
->nexthop
));
6930 vty_out(vty
, "%-16s",
6931 inet_ntoa(attr
->nexthop
));
6933 } else if (((p
->family
== AF_INET6
)
6934 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6935 || (safi
== SAFI_EVPN
6936 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6937 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6941 if (attr
->mp_nexthop_len
6942 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6944 json_object_string_add(
6945 json_out
, "mpNexthopGlobalIn",
6948 &attr
->mp_nexthop_global
,
6949 buf_a
, sizeof(buf_a
)));
6954 &attr
->mp_nexthop_global
,
6955 buf_a
, sizeof(buf_a
)));
6956 } else if (attr
->mp_nexthop_len
6957 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6960 &attr
->mp_nexthop_global
,
6961 buf_a
, sizeof(buf_a
));
6963 &attr
->mp_nexthop_local
,
6964 buf_b
, sizeof(buf_b
));
6965 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6966 json_object_string_add(
6968 "mpNexthopGlobalLocal", buf_c
);
6970 vty_out(vty
, "%s(%s)",
6973 &attr
->mp_nexthop_global
,
6974 buf_a
, sizeof(buf_a
)),
6977 &attr
->mp_nexthop_local
,
6978 buf_b
, sizeof(buf_b
)));
6983 label
= decode_label(&binfo
->extra
->label
[0]);
6985 if (bgp_is_valid_label(&label
)) {
6987 json_object_int_add(json_out
, "notag", label
);
6988 json_object_array_add(json
, json_out
);
6990 vty_out(vty
, "notag/%d", label
);
6996 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
6997 struct bgp_info
*binfo
, int display
,
6998 json_object
*json_paths
)
7002 json_object
*json_path
= NULL
;
7005 json_path
= json_object_new_object();
7010 /* short status lead text */
7011 route_vty_short_status_out(vty
, binfo
, json_path
);
7013 /* print prefix and mask */
7015 route_vty_out_route(p
, vty
, NULL
);
7017 vty_out(vty
, "%*s", 17, " ");
7019 /* Print attribute */
7023 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7027 vty_out(vty
, "%-16s",
7028 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7032 vty_out(vty
, "%s(%s)",
7033 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7035 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7042 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7044 vty_out(vty
, "%s", str
);
7045 XFREE(MTYPE_TMP
, str
);
7047 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7049 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7050 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7053 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7056 if (attr
->ecommunity
) {
7058 struct ecommunity_val
*routermac
= ecommunity_lookup(
7059 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7060 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7062 mac
= ecom_mac2str((char *)routermac
->val
);
7064 vty_out(vty
, "/%s", (char *)mac
);
7065 XFREE(MTYPE_TMP
, mac
);
7073 /* dampening route */
7074 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7075 struct bgp_info
*binfo
, int display
, safi_t safi
,
7076 uint8_t use_json
, json_object
*json
)
7080 char timebuf
[BGP_UPTIME_LEN
];
7082 /* short status lead text */
7083 route_vty_short_status_out(vty
, binfo
, json
);
7085 /* print prefix and mask */
7088 route_vty_out_route(p
, vty
, NULL
);
7090 vty_out(vty
, "%*s", 17, " ");
7093 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7097 vty_out(vty
, "\n%*s", 34, " ");
7100 json_object_int_add(json
, "peerHost", len
);
7102 vty_out(vty
, "%*s", len
, " ");
7106 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7109 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7113 /* Print attribute */
7119 json_object_string_add(json
, "asPath",
7122 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7127 json_object_string_add(json
, "origin",
7128 bgp_origin_str
[attr
->origin
]);
7130 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7137 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7138 struct bgp_info
*binfo
, int display
, safi_t safi
,
7139 uint8_t use_json
, json_object
*json
)
7142 struct bgp_damp_info
*bdi
;
7143 char timebuf
[BGP_UPTIME_LEN
];
7149 bdi
= binfo
->extra
->damp_info
;
7151 /* short status lead text */
7152 route_vty_short_status_out(vty
, binfo
, json
);
7154 /* print prefix and mask */
7157 route_vty_out_route(p
, vty
, NULL
);
7159 vty_out(vty
, "%*s", 17, " ");
7162 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7166 vty_out(vty
, "\n%*s", 33, " ");
7169 json_object_int_add(json
, "peerHost", len
);
7171 vty_out(vty
, "%*s", len
, " ");
7174 len
= vty_out(vty
, "%d", bdi
->flap
);
7181 json_object_int_add(json
, "bdiFlap", len
);
7183 vty_out(vty
, "%*s", len
, " ");
7187 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7190 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7191 BGP_UPTIME_LEN
, 0, NULL
));
7193 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7194 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7196 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7197 BGP_UPTIME_LEN
, use_json
, json
);
7200 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7205 vty_out(vty
, "%*s ", 8, " ");
7208 /* Print attribute */
7214 json_object_string_add(json
, "asPath",
7217 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7222 json_object_string_add(json
, "origin",
7223 bgp_origin_str
[attr
->origin
]);
7225 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7231 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7232 int *first
, const char *header
,
7233 json_object
*json_adv_to
)
7235 char buf1
[INET6_ADDRSTRLEN
];
7236 json_object
*json_peer
= NULL
;
7239 /* 'advertised-to' is a dictionary of peers we have advertised
7241 * prefix too. The key is the peer's IP or swpX, the value is
7243 * hostname if we know it and "" if not.
7245 json_peer
= json_object_new_object();
7248 json_object_string_add(json_peer
, "hostname",
7252 json_object_object_add(json_adv_to
, peer
->conf_if
,
7255 json_object_object_add(
7257 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7261 vty_out(vty
, "%s", header
);
7266 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7268 vty_out(vty
, " %s(%s)", peer
->hostname
,
7271 vty_out(vty
, " %s(%s)", peer
->hostname
,
7272 sockunion2str(&peer
->su
, buf1
,
7276 vty_out(vty
, " %s", peer
->conf_if
);
7279 sockunion2str(&peer
->su
, buf1
,
7285 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7286 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7287 json_object
*json_paths
)
7289 char buf
[INET6_ADDRSTRLEN
];
7291 char buf2
[EVPN_ROUTE_STRLEN
];
7293 int sockunion_vty_out(struct vty
*, union sockunion
*);
7295 json_object
*json_bestpath
= NULL
;
7296 json_object
*json_cluster_list
= NULL
;
7297 json_object
*json_cluster_list_list
= NULL
;
7298 json_object
*json_ext_community
= NULL
;
7299 json_object
*json_last_update
= NULL
;
7300 json_object
*json_pmsi
= NULL
;
7301 json_object
*json_nexthop_global
= NULL
;
7302 json_object
*json_nexthop_ll
= NULL
;
7303 json_object
*json_nexthops
= NULL
;
7304 json_object
*json_path
= NULL
;
7305 json_object
*json_peer
= NULL
;
7306 json_object
*json_string
= NULL
;
7307 json_object
*json_adv_to
= NULL
;
7309 struct listnode
*node
, *nnode
;
7311 int addpath_capable
;
7313 unsigned int first_as
;
7314 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7319 json_path
= json_object_new_object();
7320 json_peer
= json_object_new_object();
7321 json_nexthop_global
= json_object_new_object();
7324 if (!json_paths
&& safi
== SAFI_EVPN
) {
7327 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7328 vty_out(vty
, " Route %s", buf2
);
7330 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7331 bgp_evpn_label2str(binfo
->extra
->label
,
7332 binfo
->extra
->num_labels
, tag_buf
,
7334 vty_out(vty
, " VNI %s", tag_buf
);
7337 if (binfo
->extra
&& binfo
->extra
->parent
) {
7338 struct bgp_info
*parent_ri
;
7339 struct bgp_node
*rn
, *prn
;
7341 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7342 rn
= parent_ri
->net
;
7343 if (rn
&& rn
->prn
) {
7345 vty_out(vty
, " Imported from %s:%s\n",
7347 (struct prefix_rd
*)&prn
->p
,
7348 buf1
, sizeof(buf1
)),
7357 /* Line1 display AS-path, Aggregator */
7360 if (!attr
->aspath
->json
)
7361 aspath_str_update(attr
->aspath
, true);
7362 json_object_lock(attr
->aspath
->json
);
7363 json_object_object_add(json_path
, "aspath",
7364 attr
->aspath
->json
);
7366 if (attr
->aspath
->segments
)
7367 aspath_print_vty(vty
, " %s",
7370 vty_out(vty
, " Local");
7374 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7376 json_object_boolean_true_add(json_path
,
7379 vty_out(vty
, ", (removed)");
7382 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7384 json_object_boolean_true_add(json_path
,
7387 vty_out(vty
, ", (stale)");
7390 if (CHECK_FLAG(attr
->flag
,
7391 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7393 json_object_int_add(json_path
, "aggregatorAs",
7394 attr
->aggregator_as
);
7395 json_object_string_add(
7396 json_path
, "aggregatorId",
7397 inet_ntoa(attr
->aggregator_addr
));
7399 vty_out(vty
, ", (aggregated by %u %s)",
7400 attr
->aggregator_as
,
7401 inet_ntoa(attr
->aggregator_addr
));
7405 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7406 PEER_FLAG_REFLECTOR_CLIENT
)) {
7408 json_object_boolean_true_add(
7409 json_path
, "rxedFromRrClient");
7411 vty_out(vty
, ", (Received from a RR-client)");
7414 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7415 PEER_FLAG_RSERVER_CLIENT
)) {
7417 json_object_boolean_true_add(
7418 json_path
, "rxedFromRsClient");
7420 vty_out(vty
, ", (Received from a RS-client)");
7423 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7425 json_object_boolean_true_add(
7426 json_path
, "dampeningHistoryEntry");
7428 vty_out(vty
, ", (history entry)");
7429 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7431 json_object_boolean_true_add(
7432 json_path
, "dampeningSuppressed");
7434 vty_out(vty
, ", (suppressed due to dampening)");
7440 /* Line2 display Next-hop, Neighbor, Router-id */
7441 /* Display the nexthop */
7442 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7443 || p
->family
== AF_EVPN
)
7444 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7445 || safi
== SAFI_EVPN
7446 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7447 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7448 || safi
== SAFI_EVPN
) {
7450 json_object_string_add(
7451 json_nexthop_global
, "ip",
7453 attr
->mp_nexthop_global_in
));
7457 attr
->mp_nexthop_global_in
));
7460 json_object_string_add(
7461 json_nexthop_global
, "ip",
7462 inet_ntoa(attr
->nexthop
));
7465 inet_ntoa(attr
->nexthop
));
7469 json_object_string_add(json_nexthop_global
,
7473 json_object_string_add(
7474 json_nexthop_global
, "ip",
7476 &attr
->mp_nexthop_global
, buf
,
7478 json_object_string_add(json_nexthop_global
,
7480 json_object_string_add(json_nexthop_global
,
7485 &attr
->mp_nexthop_global
, buf
,
7490 /* Display the IGP cost or 'inaccessible' */
7491 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7493 json_object_boolean_false_add(
7494 json_nexthop_global
, "accessible");
7496 vty_out(vty
, " (inaccessible)");
7498 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7500 json_object_int_add(
7501 json_nexthop_global
, "metric",
7502 binfo
->extra
->igpmetric
);
7504 vty_out(vty
, " (metric %u)",
7505 binfo
->extra
->igpmetric
);
7508 /* IGP cost is 0, display this only for json */
7511 json_object_int_add(json_nexthop_global
,
7516 json_object_boolean_true_add(
7517 json_nexthop_global
, "accessible");
7520 /* Display peer "from" output */
7521 /* This path was originated locally */
7522 if (binfo
->peer
== bgp
->peer_self
) {
7524 if (safi
== SAFI_EVPN
7525 || (p
->family
== AF_INET
7526 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7528 json_object_string_add(
7529 json_peer
, "peerId", "0.0.0.0");
7531 vty_out(vty
, " from 0.0.0.0 ");
7534 json_object_string_add(json_peer
,
7537 vty_out(vty
, " from :: ");
7541 json_object_string_add(
7542 json_peer
, "routerId",
7543 inet_ntoa(bgp
->router_id
));
7545 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7548 /* We RXed this path from one of our peers */
7552 json_object_string_add(
7553 json_peer
, "peerId",
7554 sockunion2str(&binfo
->peer
->su
, buf
,
7556 json_object_string_add(
7557 json_peer
, "routerId",
7559 &binfo
->peer
->remote_id
, buf1
,
7562 if (binfo
->peer
->hostname
)
7563 json_object_string_add(
7564 json_peer
, "hostname",
7565 binfo
->peer
->hostname
);
7567 if (binfo
->peer
->domainname
)
7568 json_object_string_add(
7569 json_peer
, "domainname",
7570 binfo
->peer
->domainname
);
7572 if (binfo
->peer
->conf_if
)
7573 json_object_string_add(
7574 json_peer
, "interface",
7575 binfo
->peer
->conf_if
);
7577 if (binfo
->peer
->conf_if
) {
7578 if (binfo
->peer
->hostname
7581 BGP_FLAG_SHOW_HOSTNAME
))
7582 vty_out(vty
, " from %s(%s)",
7583 binfo
->peer
->hostname
,
7584 binfo
->peer
->conf_if
);
7586 vty_out(vty
, " from %s",
7587 binfo
->peer
->conf_if
);
7589 if (binfo
->peer
->hostname
7592 BGP_FLAG_SHOW_HOSTNAME
))
7593 vty_out(vty
, " from %s(%s)",
7594 binfo
->peer
->hostname
,
7597 vty_out(vty
, " from %s",
7606 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7607 vty_out(vty
, " (%s)",
7608 inet_ntoa(attr
->originator_id
));
7610 vty_out(vty
, " (%s)",
7613 &binfo
->peer
->remote_id
,
7614 buf1
, sizeof(buf1
)));
7619 * Note when vrfid of nexthop is different from that of prefix
7621 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7622 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7627 if (binfo
->extra
->bgp_orig
->inst_type
==
7628 BGP_INSTANCE_TYPE_DEFAULT
)
7632 vn
= binfo
->extra
->bgp_orig
->name
;
7634 json_object_string_add(json_path
, "nhVrfName",
7637 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7638 json_object_int_add(json_path
,
7641 json_object_int_add(json_path
,
7642 "nhVrfId", (int)nexthop_vrfid
);
7645 if (nexthop_vrfid
== VRF_UNKNOWN
)
7646 vty_out(vty
, " vrf ?");
7648 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7654 json_object_boolean_true_add(json_path
,
7655 "announceNexthopSelf");
7657 vty_out(vty
, " announce-nh-self");
7664 /* display the link-local nexthop */
7665 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7667 json_nexthop_ll
= json_object_new_object();
7668 json_object_string_add(
7669 json_nexthop_ll
, "ip",
7671 &attr
->mp_nexthop_local
, buf
,
7673 json_object_string_add(json_nexthop_ll
, "afi",
7675 json_object_string_add(json_nexthop_ll
, "scope",
7678 json_object_boolean_true_add(json_nexthop_ll
,
7681 if (!attr
->mp_nexthop_prefer_global
)
7682 json_object_boolean_true_add(
7683 json_nexthop_ll
, "used");
7685 json_object_boolean_true_add(
7686 json_nexthop_global
, "used");
7688 vty_out(vty
, " (%s) %s\n",
7690 &attr
->mp_nexthop_local
, buf
,
7692 attr
->mp_nexthop_prefer_global
7697 /* If we do not have a link-local nexthop then we must flag the
7701 json_object_boolean_true_add(
7702 json_nexthop_global
, "used");
7705 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7706 * Int/Ext/Local, Atomic, best */
7708 json_object_string_add(
7709 json_path
, "origin",
7710 bgp_origin_long_str
[attr
->origin
]);
7712 vty_out(vty
, " Origin %s",
7713 bgp_origin_long_str
[attr
->origin
]);
7715 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7717 json_object_int_add(json_path
, "med",
7720 vty_out(vty
, ", metric %u", attr
->med
);
7723 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7725 json_object_int_add(json_path
, "localpref",
7728 vty_out(vty
, ", localpref %u",
7732 if (attr
->weight
!= 0) {
7734 json_object_int_add(json_path
, "weight",
7737 vty_out(vty
, ", weight %u", attr
->weight
);
7740 if (attr
->tag
!= 0) {
7742 json_object_int_add(json_path
, "tag",
7745 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7749 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7751 json_object_boolean_false_add(json_path
,
7754 vty_out(vty
, ", invalid");
7755 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7757 json_object_boolean_true_add(json_path
,
7760 vty_out(vty
, ", valid");
7763 if (binfo
->peer
!= bgp
->peer_self
) {
7764 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7765 if (CHECK_FLAG(bgp
->config
,
7766 BGP_CONFIG_CONFEDERATION
)) {
7768 json_object_string_add(
7773 ", confed-internal");
7776 json_object_string_add(
7780 vty_out(vty
, ", internal");
7783 if (bgp_confederation_peers_check(
7784 bgp
, binfo
->peer
->as
)) {
7786 json_object_string_add(
7791 ", confed-external");
7794 json_object_string_add(
7798 vty_out(vty
, ", external");
7801 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7803 json_object_boolean_true_add(json_path
,
7805 json_object_boolean_true_add(json_path
,
7808 vty_out(vty
, ", aggregated, local");
7810 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7812 json_object_boolean_true_add(json_path
,
7815 vty_out(vty
, ", sourced");
7818 json_object_boolean_true_add(json_path
,
7820 json_object_boolean_true_add(json_path
,
7823 vty_out(vty
, ", sourced, local");
7827 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7829 json_object_boolean_true_add(json_path
,
7832 vty_out(vty
, ", atomic-aggregate");
7835 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7836 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7837 && bgp_info_mpath_count(binfo
))) {
7839 json_object_boolean_true_add(json_path
,
7842 vty_out(vty
, ", multipath");
7845 // Mark the bestpath(s)
7846 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7847 first_as
= aspath_get_first_as(attr
->aspath
);
7852 json_object_new_object();
7853 json_object_int_add(json_bestpath
,
7854 "bestpathFromAs", first_as
);
7857 vty_out(vty
, ", bestpath-from-AS %u",
7861 ", bestpath-from-AS Local");
7865 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7869 json_object_new_object();
7870 json_object_boolean_true_add(json_bestpath
,
7873 vty_out(vty
, ", best");
7877 json_object_object_add(json_path
, "bestpath",
7883 /* Line 4 display Community */
7884 if (attr
->community
) {
7886 if (!attr
->community
->json
)
7887 community_str(attr
->community
, true);
7888 json_object_lock(attr
->community
->json
);
7889 json_object_object_add(json_path
, "community",
7890 attr
->community
->json
);
7892 vty_out(vty
, " Community: %s\n",
7893 attr
->community
->str
);
7897 /* Line 5 display Extended-community */
7898 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7900 json_ext_community
= json_object_new_object();
7901 json_object_string_add(json_ext_community
,
7903 attr
->ecommunity
->str
);
7904 json_object_object_add(json_path
,
7905 "extendedCommunity",
7906 json_ext_community
);
7908 vty_out(vty
, " Extended Community: %s\n",
7909 attr
->ecommunity
->str
);
7913 /* Line 6 display Large community */
7914 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7916 if (!attr
->lcommunity
->json
)
7917 lcommunity_str(attr
->lcommunity
, true);
7918 json_object_lock(attr
->lcommunity
->json
);
7919 json_object_object_add(json_path
,
7921 attr
->lcommunity
->json
);
7923 vty_out(vty
, " Large Community: %s\n",
7924 attr
->lcommunity
->str
);
7928 /* Line 7 display Originator, Cluster-id */
7929 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7930 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7932 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7934 json_object_string_add(
7935 json_path
, "originatorId",
7936 inet_ntoa(attr
->originator_id
));
7938 vty_out(vty
, " Originator: %s",
7939 inet_ntoa(attr
->originator_id
));
7942 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7947 json_object_new_object();
7948 json_cluster_list_list
=
7949 json_object_new_array();
7952 i
< attr
->cluster
->length
/ 4;
7954 json_string
= json_object_new_string(
7958 json_object_array_add(
7959 json_cluster_list_list
,
7963 /* struct cluster_list does not have
7965 * aspath and community do. Add this
7968 json_object_string_add(json_cluster_list,
7969 "string", attr->cluster->str);
7971 json_object_object_add(
7972 json_cluster_list
, "list",
7973 json_cluster_list_list
);
7974 json_object_object_add(
7975 json_path
, "clusterList",
7978 vty_out(vty
, ", Cluster list: ");
7981 i
< attr
->cluster
->length
/ 4;
7995 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7996 bgp_damp_info_vty(vty
, binfo
, json_path
);
7999 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8000 && safi
!= SAFI_EVPN
) {
8001 mpls_label_t label
=
8002 label_pton(&binfo
->extra
->label
[0]);
8004 json_object_int_add(json_path
, "remoteLabel",
8007 vty_out(vty
, " Remote label: %d\n", label
);
8011 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8013 json_object_int_add(json_path
, "labelIndex",
8016 vty_out(vty
, " Label Index: %d\n",
8020 /* Line 8 display Addpath IDs */
8021 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8023 json_object_int_add(json_path
, "addpathRxId",
8024 binfo
->addpath_rx_id
);
8025 json_object_int_add(json_path
, "addpathTxId",
8026 binfo
->addpath_tx_id
);
8028 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8029 binfo
->addpath_rx_id
,
8030 binfo
->addpath_tx_id
);
8034 /* If we used addpath to TX a non-bestpath we need to display
8035 * "Advertised to" on a path-by-path basis */
8036 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8039 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8041 bgp_addpath_encode_tx(peer
, afi
, safi
);
8042 has_adj
= bgp_adj_out_lookup(
8043 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8045 if ((addpath_capable
&& has_adj
)
8046 || (!addpath_capable
&& has_adj
8047 && CHECK_FLAG(binfo
->flags
,
8048 BGP_INFO_SELECTED
))) {
8049 if (json_path
&& !json_adv_to
)
8051 json_object_new_object();
8053 route_vty_out_advertised_to(
8062 json_object_object_add(json_path
,
8073 /* Line 9 display Uptime */
8074 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8076 json_last_update
= json_object_new_object();
8077 json_object_int_add(json_last_update
, "epoch", tbuf
);
8078 json_object_string_add(json_last_update
, "string",
8080 json_object_object_add(json_path
, "lastUpdate",
8083 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8085 /* Line 10 display PMSI tunnel attribute, if present */
8086 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8087 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8088 attr
->pmsi_tnl_type
,
8089 PMSI_TNLTYPE_STR_DEFAULT
);
8092 json_pmsi
= json_object_new_object();
8093 json_object_string_add(json_pmsi
,
8095 json_object_object_add(json_path
, "pmsi",
8098 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8104 /* We've constructed the json object for this path, add it to the json
8108 if (json_nexthop_global
|| json_nexthop_ll
) {
8109 json_nexthops
= json_object_new_array();
8111 if (json_nexthop_global
)
8112 json_object_array_add(json_nexthops
,
8113 json_nexthop_global
);
8115 if (json_nexthop_ll
)
8116 json_object_array_add(json_nexthops
,
8119 json_object_object_add(json_path
, "nexthops",
8123 json_object_object_add(json_path
, "peer", json_peer
);
8124 json_object_array_add(json_paths
, json_path
);
8129 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8130 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8131 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8133 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8134 const char *prefix_list_str
, afi_t afi
,
8135 safi_t safi
, enum bgp_show_type type
);
8136 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8137 const char *filter
, afi_t afi
, safi_t safi
,
8138 enum bgp_show_type type
);
8139 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8140 const char *rmap_str
, afi_t afi
, safi_t safi
,
8141 enum bgp_show_type type
);
8142 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8143 const char *com
, int exact
, afi_t afi
,
8145 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8146 const char *prefix
, afi_t afi
, safi_t safi
,
8147 enum bgp_show_type type
);
8148 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8149 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8150 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8151 const char *comstr
, int exact
, afi_t afi
,
8152 safi_t safi
, uint8_t use_json
);
8155 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8156 struct bgp_table
*table
, enum bgp_show_type type
,
8157 void *output_arg
, uint8_t use_json
, char *rd
,
8158 int is_last
, unsigned long *output_cum
,
8159 unsigned long *total_cum
,
8160 unsigned long *json_header_depth
)
8162 struct bgp_info
*ri
;
8163 struct bgp_node
*rn
;
8166 unsigned long output_count
= 0;
8167 unsigned long total_count
= 0;
8171 json_object
*json_paths
= NULL
;
8174 if (output_cum
&& *output_cum
!= 0)
8177 if (use_json
&& !*json_header_depth
) {
8179 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8180 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8181 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8182 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8184 table
->version
, inet_ntoa(bgp
->router_id
));
8185 *json_header_depth
= 2;
8187 vty_out(vty
, " \"routeDistinguishers\" : {");
8188 ++*json_header_depth
;
8190 json_paths
= json_object_new_object();
8193 if (use_json
&& rd
) {
8194 vty_out(vty
, " \"%s\" : { ", rd
);
8197 /* Start processing of routes. */
8198 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8199 if (rn
->info
== NULL
)
8204 json_paths
= json_object_new_array();
8208 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8210 if (type
== bgp_show_type_flap_statistics
8211 || type
== bgp_show_type_flap_neighbor
8212 || type
== bgp_show_type_dampend_paths
8213 || type
== bgp_show_type_damp_neighbor
) {
8214 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8217 if (type
== bgp_show_type_regexp
) {
8218 regex_t
*regex
= output_arg
;
8220 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8224 if (type
== bgp_show_type_prefix_list
) {
8225 struct prefix_list
*plist
= output_arg
;
8227 if (prefix_list_apply(plist
, &rn
->p
)
8231 if (type
== bgp_show_type_filter_list
) {
8232 struct as_list
*as_list
= output_arg
;
8234 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8235 != AS_FILTER_PERMIT
)
8238 if (type
== bgp_show_type_route_map
) {
8239 struct route_map
*rmap
= output_arg
;
8240 struct bgp_info binfo
;
8241 struct attr dummy_attr
;
8244 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8246 binfo
.peer
= ri
->peer
;
8247 binfo
.attr
= &dummy_attr
;
8249 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8251 if (ret
== RMAP_DENYMATCH
)
8254 if (type
== bgp_show_type_neighbor
8255 || type
== bgp_show_type_flap_neighbor
8256 || type
== bgp_show_type_damp_neighbor
) {
8257 union sockunion
*su
= output_arg
;
8259 if (ri
->peer
== NULL
8260 || ri
->peer
->su_remote
== NULL
8261 || !sockunion_same(ri
->peer
->su_remote
, su
))
8264 if (type
== bgp_show_type_cidr_only
) {
8265 uint32_t destination
;
8267 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8268 if (IN_CLASSC(destination
)
8269 && rn
->p
.prefixlen
== 24)
8271 if (IN_CLASSB(destination
)
8272 && rn
->p
.prefixlen
== 16)
8274 if (IN_CLASSA(destination
)
8275 && rn
->p
.prefixlen
== 8)
8278 if (type
== bgp_show_type_prefix_longer
) {
8279 struct prefix
*p
= output_arg
;
8281 if (!prefix_match(p
, &rn
->p
))
8284 if (type
== bgp_show_type_community_all
) {
8285 if (!ri
->attr
->community
)
8288 if (type
== bgp_show_type_community
) {
8289 struct community
*com
= output_arg
;
8291 if (!ri
->attr
->community
8292 || !community_match(ri
->attr
->community
,
8296 if (type
== bgp_show_type_community_exact
) {
8297 struct community
*com
= output_arg
;
8299 if (!ri
->attr
->community
8300 || !community_cmp(ri
->attr
->community
, com
))
8303 if (type
== bgp_show_type_community_list
) {
8304 struct community_list
*list
= output_arg
;
8306 if (!community_list_match(ri
->attr
->community
,
8310 if (type
== bgp_show_type_community_list_exact
) {
8311 struct community_list
*list
= output_arg
;
8313 if (!community_list_exact_match(
8314 ri
->attr
->community
, list
))
8317 if (type
== bgp_show_type_lcommunity
) {
8318 struct lcommunity
*lcom
= output_arg
;
8320 if (!ri
->attr
->lcommunity
8321 || !lcommunity_match(ri
->attr
->lcommunity
,
8325 if (type
== bgp_show_type_lcommunity_list
) {
8326 struct community_list
*list
= output_arg
;
8328 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8332 if (type
== bgp_show_type_lcommunity_all
) {
8333 if (!ri
->attr
->lcommunity
)
8336 if (type
== bgp_show_type_dampend_paths
8337 || type
== bgp_show_type_damp_neighbor
) {
8338 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8339 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8343 if (!use_json
&& header
) {
8344 vty_out(vty
, "BGP table version is %" PRIu64
8345 ", local router ID is %s, vrf id ",
8347 inet_ntoa(bgp
->router_id
));
8348 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8349 vty_out(vty
, "%s", VRFID_NONE_STR
);
8351 vty_out(vty
, "%u", bgp
->vrf_id
);
8353 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8354 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8355 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8356 if (type
== bgp_show_type_dampend_paths
8357 || type
== bgp_show_type_damp_neighbor
)
8358 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8359 else if (type
== bgp_show_type_flap_statistics
8360 || type
== bgp_show_type_flap_neighbor
)
8361 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8363 vty_out(vty
, BGP_SHOW_HEADER
);
8366 if (rd
!= NULL
&& !display
&& !output_count
) {
8369 "Route Distinguisher: %s\n",
8372 if (type
== bgp_show_type_dampend_paths
8373 || type
== bgp_show_type_damp_neighbor
)
8374 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8375 safi
, use_json
, json_paths
);
8376 else if (type
== bgp_show_type_flap_statistics
8377 || type
== bgp_show_type_flap_neighbor
)
8378 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8379 safi
, use_json
, json_paths
);
8381 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8392 sprintf(buf2
, "%s/%d",
8393 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8396 vty_out(vty
, "\"%s\": ", buf2
);
8398 vty_out(vty
, ",\"%s\": ", buf2
);
8401 json_object_to_json_string(json_paths
));
8402 json_object_free(json_paths
);
8409 output_count
+= *output_cum
;
8410 *output_cum
= output_count
;
8413 total_count
+= *total_cum
;
8414 *total_cum
= total_count
;
8418 json_object_free(json_paths
);
8420 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8424 for (i
= 0; i
< *json_header_depth
; ++i
)
8425 vty_out(vty
, " } ");
8429 /* No route is displayed */
8430 if (output_count
== 0) {
8431 if (type
== bgp_show_type_normal
)
8433 "No BGP prefixes displayed, %ld exist\n",
8437 "\nDisplayed %ld routes and %ld total paths\n",
8438 output_count
, total_count
);
8445 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8446 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8447 enum bgp_show_type type
, void *output_arg
,
8450 struct bgp_node
*rn
, *next
;
8451 unsigned long output_cum
= 0;
8452 unsigned long total_cum
= 0;
8453 unsigned long json_header_depth
= 0;
8456 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8458 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8459 next
= bgp_route_next(rn
);
8460 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8462 if (rn
->info
!= NULL
) {
8463 struct prefix_rd prd
;
8464 char rd
[RD_ADDRSTRLEN
];
8466 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8467 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8468 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8469 output_arg
, use_json
, rd
, next
== NULL
,
8470 &output_cum
, &total_cum
,
8471 &json_header_depth
);
8477 if (output_cum
== 0)
8478 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8482 "\nDisplayed %ld routes and %ld total paths\n",
8483 output_cum
, total_cum
);
8487 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8488 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8490 struct bgp_table
*table
;
8491 unsigned long json_header_depth
= 0;
8494 bgp
= bgp_get_default();
8499 vty_out(vty
, "No BGP process is configured\n");
8501 vty_out(vty
, "{}\n");
8505 table
= bgp
->rib
[afi
][safi
];
8506 /* use MPLS and ENCAP specific shows until they are merged */
8507 if (safi
== SAFI_MPLS_VPN
) {
8508 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8509 output_arg
, use_json
);
8512 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8513 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8514 output_arg
, use_json
,
8517 /* labeled-unicast routes live in the unicast table */
8518 else if (safi
== SAFI_LABELED_UNICAST
)
8519 safi
= SAFI_UNICAST
;
8521 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8522 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8525 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8526 safi_t safi
, uint8_t use_json
)
8528 struct listnode
*node
, *nnode
;
8533 vty_out(vty
, "{\n");
8535 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8538 vty_out(vty
, ",\n");
8542 vty_out(vty
, "\"%s\":",
8543 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8547 vty_out(vty
, "\nInstance %s:\n",
8548 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8552 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8557 vty_out(vty
, "}\n");
8560 /* Header of detailed BGP route information */
8561 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8562 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8563 afi_t afi
, safi_t safi
, json_object
*json
)
8565 struct bgp_info
*ri
;
8568 struct listnode
*node
, *nnode
;
8569 char buf1
[RD_ADDRSTRLEN
];
8570 char buf2
[INET6_ADDRSTRLEN
];
8571 char buf3
[EVPN_ROUTE_STRLEN
];
8572 char prefix_str
[BUFSIZ
];
8577 int no_advertise
= 0;
8580 int has_valid_label
= 0;
8581 mpls_label_t label
= 0;
8582 json_object
*json_adv_to
= NULL
;
8585 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8587 if (has_valid_label
)
8588 label
= label_pton(&rn
->local_label
);
8591 if (has_valid_label
)
8592 json_object_int_add(json
, "localLabel", label
);
8594 json_object_string_add(
8596 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8598 if (safi
== SAFI_EVPN
)
8599 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8600 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8603 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8604 buf3
, sizeof(buf3
)));
8606 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8607 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8608 ? prefix_rd2str(prd
, buf1
,
8611 safi
== SAFI_MPLS_VPN
? ":" : "",
8612 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8616 if (has_valid_label
)
8617 vty_out(vty
, "Local label: %d\n", label
);
8618 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8619 vty_out(vty
, "not allocated\n");
8622 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8624 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8626 if (ri
->extra
&& ri
->extra
->suppress
)
8628 if (ri
->attr
->community
!= NULL
) {
8629 if (community_include(ri
->attr
->community
,
8630 COMMUNITY_NO_ADVERTISE
))
8632 if (community_include(ri
->attr
->community
,
8633 COMMUNITY_NO_EXPORT
))
8635 if (community_include(ri
->attr
->community
,
8636 COMMUNITY_LOCAL_AS
))
8643 vty_out(vty
, "Paths: (%d available", count
);
8645 vty_out(vty
, ", best #%d", best
);
8646 if (safi
== SAFI_UNICAST
)
8647 vty_out(vty
, ", table %s",
8649 == BGP_INSTANCE_TYPE_DEFAULT
)
8650 ? "Default-IP-Routing-Table"
8653 vty_out(vty
, ", no best path");
8656 vty_out(vty
, ", not advertised to any peer");
8658 vty_out(vty
, ", not advertised to EBGP peer");
8660 vty_out(vty
, ", not advertised outside local AS");
8664 ", Advertisements suppressed by an aggregate.");
8665 vty_out(vty
, ")\n");
8668 /* If we are not using addpath then we can display Advertised to and
8670 * show what peers we advertised the bestpath to. If we are using
8672 * though then we must display Advertised to on a path-by-path basis. */
8673 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8674 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8675 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8676 if (json
&& !json_adv_to
)
8677 json_adv_to
= json_object_new_object();
8679 route_vty_out_advertised_to(
8681 " Advertised to non peer-group peers:\n ",
8688 json_object_object_add(json
, "advertisedTo",
8693 vty_out(vty
, " Not advertised to any peer");
8699 /* Display specified route of BGP table. */
8700 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8701 struct bgp_table
*rib
, const char *ip_str
,
8702 afi_t afi
, safi_t safi
,
8703 struct prefix_rd
*prd
, int prefix_check
,
8704 enum bgp_path_type pathtype
,
8710 struct prefix match
;
8711 struct bgp_node
*rn
;
8712 struct bgp_node
*rm
;
8713 struct bgp_info
*ri
;
8714 struct bgp_table
*table
;
8715 json_object
*json
= NULL
;
8716 json_object
*json_paths
= NULL
;
8718 /* Check IP address argument. */
8719 ret
= str2prefix(ip_str
, &match
);
8721 vty_out(vty
, "address is malformed\n");
8725 match
.family
= afi2family(afi
);
8728 json
= json_object_new_object();
8729 json_paths
= json_object_new_array();
8732 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8733 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8734 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8737 if ((table
= rn
->info
) == NULL
)
8742 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8746 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8747 bgp_unlock_node(rm
);
8751 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8753 route_vty_out_detail_header(
8755 (struct prefix_rd
*)&rn
->p
,
8756 AFI_IP
, safi
, json
);
8761 if (pathtype
== BGP_PATH_ALL
8762 || (pathtype
== BGP_PATH_BESTPATH
8763 && CHECK_FLAG(ri
->flags
,
8765 || (pathtype
== BGP_PATH_MULTIPATH
8766 && (CHECK_FLAG(ri
->flags
,
8768 || CHECK_FLAG(ri
->flags
,
8769 BGP_INFO_SELECTED
))))
8770 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8775 bgp_unlock_node(rm
);
8777 } else if (safi
== SAFI_FLOWSPEC
) {
8778 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
8779 &match
, prefix_check
,
8786 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8788 || rn
->p
.prefixlen
== match
.prefixlen
) {
8789 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8791 route_vty_out_detail_header(
8792 vty
, bgp
, rn
, NULL
, afi
,
8798 if (pathtype
== BGP_PATH_ALL
8799 || (pathtype
== BGP_PATH_BESTPATH
8803 || (pathtype
== BGP_PATH_MULTIPATH
8809 BGP_INFO_SELECTED
))))
8810 route_vty_out_detail(
8811 vty
, bgp
, &rn
->p
, ri
,
8812 afi
, safi
, json_paths
);
8816 bgp_unlock_node(rn
);
8822 json_object_object_add(json
, "paths", json_paths
);
8824 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8825 json
, JSON_C_TO_STRING_PRETTY
));
8826 json_object_free(json
);
8829 vty_out(vty
, "%% Network not in table\n");
8837 /* Display specified route of Main RIB */
8838 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8839 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8840 int prefix_check
, enum bgp_path_type pathtype
,
8844 bgp
= bgp_get_default();
8847 vty_out(vty
, "No BGP process is configured\n");
8849 vty_out(vty
, "{}\n");
8854 /* labeled-unicast routes live in the unicast table */
8855 if (safi
== SAFI_LABELED_UNICAST
)
8856 safi
= SAFI_UNICAST
;
8858 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8859 afi
, safi
, prd
, prefix_check
, pathtype
,
8863 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8864 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8867 struct lcommunity
*lcom
;
8873 b
= buffer_new(1024);
8874 for (i
= 0; i
< argc
; i
++) {
8876 buffer_putc(b
, ' ');
8878 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8880 buffer_putstr(b
, argv
[i
]->arg
);
8884 buffer_putc(b
, '\0');
8886 str
= buffer_getstr(b
);
8889 lcom
= lcommunity_str2com(str
);
8890 XFREE(MTYPE_TMP
, str
);
8892 vty_out(vty
, "%% Large-community malformed\n");
8896 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8900 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8901 const char *lcom
, afi_t afi
, safi_t safi
,
8904 struct community_list
*list
;
8906 list
= community_list_lookup(bgp_clist
, lcom
,
8907 LARGE_COMMUNITY_LIST_MASTER
);
8909 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8914 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8918 DEFUN (show_ip_bgp_large_community_list
,
8919 show_ip_bgp_large_community_list_cmd
,
8920 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8924 BGP_INSTANCE_HELP_STR
8926 BGP_SAFI_WITH_LABEL_HELP_STR
8927 "Display routes matching the large-community-list\n"
8928 "large-community-list number\n"
8929 "large-community-list name\n"
8933 afi_t afi
= AFI_IP6
;
8934 safi_t safi
= SAFI_UNICAST
;
8937 if (argv_find(argv
, argc
, "ip", &idx
))
8939 if (argv_find(argv
, argc
, "view", &idx
)
8940 || argv_find(argv
, argc
, "vrf", &idx
))
8941 vrf
= argv
[++idx
]->arg
;
8942 if (argv_find(argv
, argc
, "ipv4", &idx
)
8943 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8944 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8945 if (argv_find(argv
, argc
, "unicast", &idx
)
8946 || argv_find(argv
, argc
, "multicast", &idx
))
8947 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8950 int uj
= use_json(argc
, argv
);
8952 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8954 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8958 argv_find(argv
, argc
, "large-community-list", &idx
);
8959 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8962 DEFUN (show_ip_bgp_large_community
,
8963 show_ip_bgp_large_community_cmd
,
8964 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8968 BGP_INSTANCE_HELP_STR
8970 BGP_SAFI_WITH_LABEL_HELP_STR
8971 "Display routes matching the large-communities\n"
8972 "List of large-community numbers\n"
8976 afi_t afi
= AFI_IP6
;
8977 safi_t safi
= SAFI_UNICAST
;
8980 if (argv_find(argv
, argc
, "ip", &idx
))
8982 if (argv_find(argv
, argc
, "view", &idx
)
8983 || argv_find(argv
, argc
, "vrf", &idx
))
8984 vrf
= argv
[++idx
]->arg
;
8985 if (argv_find(argv
, argc
, "ipv4", &idx
)
8986 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8987 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8988 if (argv_find(argv
, argc
, "unicast", &idx
)
8989 || argv_find(argv
, argc
, "multicast", &idx
))
8990 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8993 int uj
= use_json(argc
, argv
);
8995 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8997 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9001 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9002 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9004 return bgp_show(vty
, bgp
, afi
, safi
,
9005 bgp_show_type_lcommunity_all
, NULL
, uj
);
9008 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9012 /* BGP route print out function without JSON */
9015 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9016 <dampening <parameters>\
9021 |community-list <(1-500)|WORD> [exact-match]\
9022 |A.B.C.D/M longer-prefixes\
9023 |X:X::X:X/M longer-prefixes\
9028 BGP_INSTANCE_HELP_STR
9030 BGP_SAFI_WITH_LABEL_HELP_STR
9031 "Display detailed information about dampening\n"
9032 "Display detail of configured dampening parameters\n"
9033 "Display routes matching the route-map\n"
9034 "A route-map to match on\n"
9035 "Display routes conforming to the prefix-list\n"
9036 "Prefix-list name\n"
9037 "Display routes conforming to the filter-list\n"
9038 "Regular expression access list name\n"
9039 "BGP RIB advertisement statistics\n"
9040 "Display routes matching the community-list\n"
9041 "community-list number\n"
9042 "community-list name\n"
9043 "Exact match of the communities\n"
9045 "Display route and more specific routes\n"
9047 "Display route and more specific routes\n")
9049 afi_t afi
= AFI_IP6
;
9050 safi_t safi
= SAFI_UNICAST
;
9051 int exact_match
= 0;
9052 struct bgp
*bgp
= NULL
;
9055 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9060 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9061 if (argv_find(argv
, argc
, "parameters", &idx
))
9062 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9065 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9066 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9067 safi
, bgp_show_type_prefix_list
);
9069 if (argv_find(argv
, argc
, "filter-list", &idx
))
9070 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9071 safi
, bgp_show_type_filter_list
);
9073 if (argv_find(argv
, argc
, "statistics", &idx
))
9074 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9076 if (argv_find(argv
, argc
, "route-map", &idx
))
9077 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9078 safi
, bgp_show_type_route_map
);
9080 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9081 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9082 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9084 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9085 exact_match
, afi
, safi
);
9088 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9089 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9090 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9092 bgp_show_type_prefix_longer
);
9097 /* BGP route print out function with JSON */
9098 DEFUN (show_ip_bgp_json
,
9099 show_ip_bgp_json_cmd
,
9100 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9103 |dampening <flap-statistics|dampened-paths>\
9104 |community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown>] [exact-match]\
9109 BGP_INSTANCE_HELP_STR
9111 BGP_SAFI_WITH_LABEL_HELP_STR
9112 "Display only routes with non-natural netmasks\n"
9113 "Display detailed information about dampening\n"
9114 "Display flap statistics of routes\n"
9115 "Display paths suppressed due to dampening\n"
9116 "Display routes matching the communities\n"
9118 "Do not send outside local AS (well-known community)\n"
9119 "Do not advertise to any peer (well-known community)\n"
9120 "Do not export to next AS (well-known community)\n"
9121 "Graceful shutdown (well-known community)\n"
9122 "Exact match of the communities\n"
9125 afi_t afi
= AFI_IP6
;
9126 safi_t safi
= SAFI_UNICAST
;
9127 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9128 struct bgp
*bgp
= NULL
;
9130 int idx_community_type
= 0;
9131 int exact_match
= 0;
9133 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9138 int uj
= use_json(argc
, argv
);
9142 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9143 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9146 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9147 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9148 return bgp_show(vty
, bgp
, afi
, safi
,
9149 bgp_show_type_dampend_paths
, NULL
, uj
);
9150 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9151 return bgp_show(vty
, bgp
, afi
, safi
,
9152 bgp_show_type_flap_statistics
, NULL
,
9156 if (argv_find(argv
, argc
, "community", &idx
)) {
9158 /* show a specific community */
9159 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
) ||
9160 argv_find(argv
, argc
, "no-advertise",
9161 &idx_community_type
) ||
9162 argv_find(argv
, argc
, "no-export",
9163 &idx_community_type
) ||
9164 argv_find(argv
, argc
, "graceful-shutdown",
9165 &idx_community_type
) ||
9166 argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9167 if (argv_find(argv
, argc
, "exact-match", &idx
))
9170 return (bgp_show_community(vty
, bgp
,
9171 argv
[idx_community_type
]->arg
,
9172 exact_match
, afi
, safi
, uj
));
9175 /* show all communities */
9176 return (bgp_show(vty
, bgp
, afi
, safi
,
9177 bgp_show_type_community_all
, NULL
,
9182 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9185 DEFUN (show_ip_bgp_route
,
9186 show_ip_bgp_route_cmd
,
9187 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9188 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9192 BGP_INSTANCE_HELP_STR
9194 BGP_SAFI_WITH_LABEL_HELP_STR
9195 "Network in the BGP routing table to display\n"
9197 "Network in the BGP routing table to display\n"
9199 "Display only the bestpath\n"
9200 "Display only multipaths\n"
9203 int prefix_check
= 0;
9205 afi_t afi
= AFI_IP6
;
9206 safi_t safi
= SAFI_UNICAST
;
9207 char *prefix
= NULL
;
9208 struct bgp
*bgp
= NULL
;
9209 enum bgp_path_type path_type
;
9210 uint8_t uj
= use_json(argc
, argv
);
9214 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9221 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9225 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9226 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9227 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9229 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9230 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9233 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9234 && afi
!= AFI_IP6
) {
9236 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9239 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9242 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9246 prefix
= argv
[idx
]->arg
;
9248 /* [<bestpath|multipath>] */
9249 if (argv_find(argv
, argc
, "bestpath", &idx
))
9250 path_type
= BGP_PATH_BESTPATH
;
9251 else if (argv_find(argv
, argc
, "multipath", &idx
))
9252 path_type
= BGP_PATH_MULTIPATH
;
9254 path_type
= BGP_PATH_ALL
;
9256 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9260 DEFUN (show_ip_bgp_regexp
,
9261 show_ip_bgp_regexp_cmd
,
9262 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9266 BGP_INSTANCE_HELP_STR
9268 BGP_SAFI_WITH_LABEL_HELP_STR
9269 "Display routes matching the AS path regular expression\n"
9270 "A regular-expression to match the BGP AS paths\n")
9272 afi_t afi
= AFI_IP6
;
9273 safi_t safi
= SAFI_UNICAST
;
9274 struct bgp
*bgp
= NULL
;
9277 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9282 // get index of regex
9283 argv_find(argv
, argc
, "regexp", &idx
);
9286 char *regstr
= argv_concat(argv
, argc
, idx
);
9287 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9288 bgp_show_type_regexp
);
9289 XFREE(MTYPE_TMP
, regstr
);
9293 DEFUN (show_ip_bgp_instance_all
,
9294 show_ip_bgp_instance_all_cmd
,
9295 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9299 BGP_INSTANCE_ALL_HELP_STR
9301 BGP_SAFI_WITH_LABEL_HELP_STR
9305 safi_t safi
= SAFI_UNICAST
;
9306 struct bgp
*bgp
= NULL
;
9309 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9314 int uj
= use_json(argc
, argv
);
9318 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9322 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9323 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9328 regex
= bgp_regcomp(regstr
);
9330 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9334 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9335 bgp_regex_free(regex
);
9339 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9340 const char *prefix_list_str
, afi_t afi
,
9341 safi_t safi
, enum bgp_show_type type
)
9343 struct prefix_list
*plist
;
9345 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9346 if (plist
== NULL
) {
9347 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9352 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9355 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9356 const char *filter
, afi_t afi
, safi_t safi
,
9357 enum bgp_show_type type
)
9359 struct as_list
*as_list
;
9361 as_list
= as_list_lookup(filter
);
9362 if (as_list
== NULL
) {
9363 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9368 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9371 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9372 const char *rmap_str
, afi_t afi
, safi_t safi
,
9373 enum bgp_show_type type
)
9375 struct route_map
*rmap
;
9377 rmap
= route_map_lookup_by_name(rmap_str
);
9379 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9383 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9386 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9387 const char *comstr
, int exact
, afi_t afi
,
9388 safi_t safi
, uint8_t use_json
)
9390 struct community
*com
;
9393 com
= community_str2com(comstr
);
9395 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9399 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9400 (exact
? bgp_show_type_community_exact
9401 : bgp_show_type_community
),
9403 community_free(com
);
9408 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9409 const char *com
, int exact
, afi_t afi
,
9412 struct community_list
*list
;
9414 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9416 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9420 return bgp_show(vty
, bgp
, afi
, safi
,
9421 (exact
? bgp_show_type_community_list_exact
9422 : bgp_show_type_community_list
),
9426 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9427 const char *prefix
, afi_t afi
, safi_t safi
,
9428 enum bgp_show_type type
)
9435 ret
= str2prefix(prefix
, p
);
9437 vty_out(vty
, "%% Malformed Prefix\n");
9441 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9446 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9447 const char *ip_str
, uint8_t use_json
)
9453 /* Get peer sockunion. */
9454 ret
= str2sockunion(ip_str
, &su
);
9456 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9458 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9462 json_object
*json_no
= NULL
;
9463 json_no
= json_object_new_object();
9464 json_object_string_add(
9466 "malformedAddressOrName",
9468 vty_out(vty
, "%s\n",
9469 json_object_to_json_string_ext(
9471 JSON_C_TO_STRING_PRETTY
));
9472 json_object_free(json_no
);
9475 "%% Malformed address or name: %s\n",
9483 /* Peer structure lookup. */
9484 peer
= peer_lookup(bgp
, &su
);
9487 json_object
*json_no
= NULL
;
9488 json_no
= json_object_new_object();
9489 json_object_string_add(json_no
, "warning",
9490 "No such neighbor in this view/vrf");
9491 vty_out(vty
, "%s\n",
9492 json_object_to_json_string_ext(
9493 json_no
, JSON_C_TO_STRING_PRETTY
));
9494 json_object_free(json_no
);
9496 vty_out(vty
, "No such neighbor in this view/vrf\n");
9504 BGP_STATS_MAXBITLEN
= 0,
9508 BGP_STATS_UNAGGREGATEABLE
,
9509 BGP_STATS_MAX_AGGREGATEABLE
,
9510 BGP_STATS_AGGREGATES
,
9512 BGP_STATS_ASPATH_COUNT
,
9513 BGP_STATS_ASPATH_MAXHOPS
,
9514 BGP_STATS_ASPATH_TOTHOPS
,
9515 BGP_STATS_ASPATH_MAXSIZE
,
9516 BGP_STATS_ASPATH_TOTSIZE
,
9517 BGP_STATS_ASN_HIGHEST
,
9521 static const char *table_stats_strs
[] = {
9522 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9523 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9524 [BGP_STATS_RIB
] = "Total Advertisements",
9525 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9526 [BGP_STATS_MAX_AGGREGATEABLE
] =
9527 "Maximum aggregateable prefixes",
9528 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9529 [BGP_STATS_SPACE
] = "Address space advertised",
9530 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9531 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9532 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9533 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9534 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9535 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9536 [BGP_STATS_MAX
] = NULL
,
9539 struct bgp_table_stats
{
9540 struct bgp_table
*table
;
9541 unsigned long long counts
[BGP_STATS_MAX
];
9546 #define TALLY_SIGFIG 100000
9547 static unsigned long
9548 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9550 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9551 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9552 unsigned long ret
= newtot
/ count
;
9554 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9561 static int bgp_table_stats_walker(struct thread
*t
)
9563 struct bgp_node
*rn
;
9564 struct bgp_node
*top
;
9565 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9566 unsigned int space
= 0;
9568 if (!(top
= bgp_table_top(ts
->table
)))
9571 switch (top
->p
.family
) {
9573 space
= IPV4_MAX_BITLEN
;
9576 space
= IPV6_MAX_BITLEN
;
9580 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9582 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9583 struct bgp_info
*ri
;
9584 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9585 unsigned int rinum
= 0;
9593 ts
->counts
[BGP_STATS_PREFIXES
]++;
9594 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9597 ts
->counts
[BGP_STATS_AVGPLEN
]
9598 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9599 ts
->counts
[BGP_STATS_AVGPLEN
],
9603 /* check if the prefix is included by any other announcements */
9604 while (prn
&& !prn
->info
)
9605 prn
= bgp_node_parent_nolock(prn
);
9607 if (prn
== NULL
|| prn
== top
) {
9608 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9609 /* announced address space */
9612 pow(2.0, space
- rn
->p
.prefixlen
);
9613 } else if (prn
->info
)
9614 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9616 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9618 ts
->counts
[BGP_STATS_RIB
]++;
9621 && (CHECK_FLAG(ri
->attr
->flag
,
9623 BGP_ATTR_ATOMIC_AGGREGATE
))))
9624 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9627 if (ri
->attr
&& ri
->attr
->aspath
) {
9629 aspath_count_hops(ri
->attr
->aspath
);
9631 aspath_size(ri
->attr
->aspath
);
9632 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9634 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9636 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9637 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9640 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9641 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9644 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9645 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9647 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9648 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9649 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9651 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9652 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9653 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9656 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9657 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9665 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9668 struct bgp_table_stats ts
;
9671 if (!bgp
->rib
[afi
][safi
]) {
9672 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9677 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9679 /* labeled-unicast routes live in the unicast table */
9680 if (safi
== SAFI_LABELED_UNICAST
)
9681 safi
= SAFI_UNICAST
;
9683 memset(&ts
, 0, sizeof(ts
));
9684 ts
.table
= bgp
->rib
[afi
][safi
];
9685 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9687 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9688 if (!table_stats_strs
[i
])
9693 case BGP_STATS_ASPATH_AVGHOPS
:
9694 case BGP_STATS_ASPATH_AVGSIZE
:
9695 case BGP_STATS_AVGPLEN
:
9696 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9697 vty_out (vty
, "%12.2f",
9698 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9701 case BGP_STATS_ASPATH_TOTHOPS
:
9702 case BGP_STATS_ASPATH_TOTSIZE
:
9703 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9704 vty_out(vty
, "%12.2f",
9706 ? (float)ts
.counts
[i
]
9708 [BGP_STATS_ASPATH_COUNT
]
9711 case BGP_STATS_TOTPLEN
:
9712 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9713 vty_out(vty
, "%12.2f",
9715 ? (float)ts
.counts
[i
]
9717 [BGP_STATS_PREFIXES
]
9720 case BGP_STATS_SPACE
:
9721 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9722 vty_out(vty
, "%12g\n", ts
.total_space
);
9724 if (afi
== AFI_IP6
) {
9725 vty_out(vty
, "%30s: ", "/32 equivalent ");
9726 vty_out(vty
, "%12g\n",
9727 ts
.total_space
* pow(2.0, -128 + 32));
9728 vty_out(vty
, "%30s: ", "/48 equivalent ");
9729 vty_out(vty
, "%12g\n",
9730 ts
.total_space
* pow(2.0, -128 + 48));
9732 vty_out(vty
, "%30s: ", "% announced ");
9733 vty_out(vty
, "%12.2f\n",
9734 ts
.total_space
* 100. * pow(2.0, -32));
9735 vty_out(vty
, "%30s: ", "/8 equivalent ");
9736 vty_out(vty
, "%12.2f\n",
9737 ts
.total_space
* pow(2.0, -32 + 8));
9738 vty_out(vty
, "%30s: ", "/24 equivalent ");
9739 vty_out(vty
, "%12.2f\n",
9740 ts
.total_space
* pow(2.0, -32 + 24));
9744 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9745 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9762 PCOUNT_PFCNT
, /* the figure we display to users */
9766 static const char *pcount_strs
[] = {
9767 [PCOUNT_ADJ_IN
] = "Adj-in",
9768 [PCOUNT_DAMPED
] = "Damped",
9769 [PCOUNT_REMOVED
] = "Removed",
9770 [PCOUNT_HISTORY
] = "History",
9771 [PCOUNT_STALE
] = "Stale",
9772 [PCOUNT_VALID
] = "Valid",
9773 [PCOUNT_ALL
] = "All RIB",
9774 [PCOUNT_COUNTED
] = "PfxCt counted",
9775 [PCOUNT_PFCNT
] = "Useable",
9776 [PCOUNT_MAX
] = NULL
,
9779 struct peer_pcounts
{
9780 unsigned int count
[PCOUNT_MAX
];
9781 const struct peer
*peer
;
9782 const struct bgp_table
*table
;
9785 static int bgp_peer_count_walker(struct thread
*t
)
9787 struct bgp_node
*rn
;
9788 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9789 const struct peer
*peer
= pc
->peer
;
9791 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9792 struct bgp_adj_in
*ain
;
9793 struct bgp_info
*ri
;
9795 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9796 if (ain
->peer
== peer
)
9797 pc
->count
[PCOUNT_ADJ_IN
]++;
9799 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9800 char buf
[SU_ADDRSTRLEN
];
9802 if (ri
->peer
!= peer
)
9805 pc
->count
[PCOUNT_ALL
]++;
9807 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9808 pc
->count
[PCOUNT_DAMPED
]++;
9809 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9810 pc
->count
[PCOUNT_HISTORY
]++;
9811 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9812 pc
->count
[PCOUNT_REMOVED
]++;
9813 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9814 pc
->count
[PCOUNT_STALE
]++;
9815 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9816 pc
->count
[PCOUNT_VALID
]++;
9817 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9818 pc
->count
[PCOUNT_PFCNT
]++;
9820 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9821 pc
->count
[PCOUNT_COUNTED
]++;
9822 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9824 "%s [pcount] %s/%d is counted but flags 0x%x",
9826 inet_ntop(rn
->p
.family
,
9827 &rn
->p
.u
.prefix
, buf
,
9829 rn
->p
.prefixlen
, ri
->flags
);
9831 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9833 "%s [pcount] %s/%d not counted but flags 0x%x",
9835 inet_ntop(rn
->p
.family
,
9836 &rn
->p
.u
.prefix
, buf
,
9838 rn
->p
.prefixlen
, ri
->flags
);
9845 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9846 safi_t safi
, uint8_t use_json
)
9848 struct peer_pcounts pcounts
= {.peer
= peer
};
9850 json_object
*json
= NULL
;
9851 json_object
*json_loop
= NULL
;
9854 json
= json_object_new_object();
9855 json_loop
= json_object_new_object();
9858 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9859 || !peer
->bgp
->rib
[afi
][safi
]) {
9861 json_object_string_add(
9863 "No such neighbor or address family");
9864 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9865 json_object_free(json
);
9867 vty_out(vty
, "%% No such neighbor or address family\n");
9872 memset(&pcounts
, 0, sizeof(pcounts
));
9873 pcounts
.peer
= peer
;
9874 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9876 /* in-place call via thread subsystem so as to record execution time
9877 * stats for the thread-walk (i.e. ensure this can't be blamed on
9878 * on just vty_read()).
9880 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9883 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9884 json_object_string_add(json
, "multiProtocol",
9885 afi_safi_print(afi
, safi
));
9886 json_object_int_add(json
, "pfxCounter",
9887 peer
->pcount
[afi
][safi
]);
9889 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9890 json_object_int_add(json_loop
, pcount_strs
[i
],
9893 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9895 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9896 json_object_string_add(json
, "pfxctDriftFor",
9898 json_object_string_add(
9899 json
, "recommended",
9900 "Please report this bug, with the above command output");
9902 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9903 json
, JSON_C_TO_STRING_PRETTY
));
9904 json_object_free(json
);
9908 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9909 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9910 peer
->hostname
, peer
->host
,
9911 afi_safi_print(afi
, safi
));
9913 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9914 afi_safi_print(afi
, safi
));
9917 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9918 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9920 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9921 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9924 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9925 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9927 "Please report this bug, with the above command output\n");
9934 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9935 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9936 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9937 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9941 BGP_INSTANCE_HELP_STR
9944 "Detailed information on TCP and BGP neighbor connections\n"
9945 "Neighbor to display information about\n"
9946 "Neighbor to display information about\n"
9947 "Neighbor on BGP configured interface\n"
9948 "Display detailed prefix count information\n"
9951 afi_t afi
= AFI_IP6
;
9952 safi_t safi
= SAFI_UNICAST
;
9955 struct bgp
*bgp
= NULL
;
9957 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9962 int uj
= use_json(argc
, argv
);
9966 argv_find(argv
, argc
, "neighbors", &idx
);
9967 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9971 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9974 #ifdef KEEP_OLD_VPN_COMMANDS
9975 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9976 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9977 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9982 "Display information about all VPNv4 NLRIs\n"
9983 "Detailed information on TCP and BGP neighbor connections\n"
9984 "Neighbor to display information about\n"
9985 "Neighbor to display information about\n"
9986 "Neighbor on BGP configured interface\n"
9987 "Display detailed prefix count information\n"
9992 uint8_t uj
= use_json(argc
, argv
);
9994 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9998 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10001 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10002 show_ip_bgp_vpn_all_route_prefix_cmd
,
10003 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10008 "Display information about all VPNv4 NLRIs\n"
10009 "Network in the BGP routing table to display\n"
10010 "Network in the BGP routing table to display\n"
10014 char *network
= NULL
;
10015 struct bgp
*bgp
= bgp_get_default();
10017 vty_out(vty
, "Can't find default instance\n");
10018 return CMD_WARNING
;
10021 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10022 network
= argv
[idx
]->arg
;
10023 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10024 network
= argv
[idx
]->arg
;
10026 vty_out(vty
, "Unable to figure out Network\n");
10027 return CMD_WARNING
;
10030 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10031 BGP_PATH_ALL
, use_json(argc
, argv
));
10033 #endif /* KEEP_OLD_VPN_COMMANDS */
10035 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10036 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10037 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10043 "Display information about all EVPN NLRIs\n"
10044 "Network in the BGP routing table to display\n"
10045 "Network in the BGP routing table to display\n"
10049 char *network
= NULL
;
10051 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10052 network
= argv
[idx
]->arg
;
10053 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10054 network
= argv
[idx
]->arg
;
10056 vty_out(vty
, "Unable to figure out Network\n");
10057 return CMD_WARNING
;
10059 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10060 BGP_PATH_ALL
, use_json(argc
, argv
));
10063 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10064 safi_t safi
, enum bgp_show_adj_route_type type
,
10065 const char *rmap_name
, uint8_t use_json
,
10068 struct bgp_table
*table
;
10069 struct bgp_adj_in
*ain
;
10070 struct bgp_adj_out
*adj
;
10071 unsigned long output_count
;
10072 unsigned long filtered_count
;
10073 struct bgp_node
*rn
;
10079 struct update_subgroup
*subgrp
;
10080 json_object
*json_scode
= NULL
;
10081 json_object
*json_ocode
= NULL
;
10082 json_object
*json_ar
= NULL
;
10083 struct peer_af
*paf
;
10084 bool route_filtered
;
10087 json_scode
= json_object_new_object();
10088 json_ocode
= json_object_new_object();
10089 json_ar
= json_object_new_object();
10091 json_object_string_add(json_scode
, "suppressed", "s");
10092 json_object_string_add(json_scode
, "damped", "d");
10093 json_object_string_add(json_scode
, "history", "h");
10094 json_object_string_add(json_scode
, "valid", "*");
10095 json_object_string_add(json_scode
, "best", ">");
10096 json_object_string_add(json_scode
, "multipath", "=");
10097 json_object_string_add(json_scode
, "internal", "i");
10098 json_object_string_add(json_scode
, "ribFailure", "r");
10099 json_object_string_add(json_scode
, "stale", "S");
10100 json_object_string_add(json_scode
, "removed", "R");
10102 json_object_string_add(json_ocode
, "igp", "i");
10103 json_object_string_add(json_ocode
, "egp", "e");
10104 json_object_string_add(json_ocode
, "incomplete", "?");
10111 json_object_string_add(json
, "alert", "no BGP");
10112 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10113 json_object_free(json
);
10115 vty_out(vty
, "%% No bgp\n");
10119 table
= bgp
->rib
[afi
][safi
];
10121 output_count
= filtered_count
= 0;
10122 subgrp
= peer_subgroup(peer
, afi
, safi
);
10124 if (type
== bgp_show_adj_route_advertised
&& subgrp
10125 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10127 json_object_int_add(json
, "bgpTableVersion",
10129 json_object_string_add(json
, "bgpLocalRouterId",
10130 inet_ntoa(bgp
->router_id
));
10131 json_object_object_add(json
, "bgpStatusCodes",
10133 json_object_object_add(json
, "bgpOriginCodes",
10135 json_object_string_add(
10136 json
, "bgpOriginatingDefaultNetwork",
10137 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10139 vty_out(vty
, "BGP table version is %" PRIu64
10140 ", local router ID is %s, vrf id ",
10141 table
->version
, inet_ntoa(bgp
->router_id
));
10142 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10143 vty_out(vty
, "%s", VRFID_NONE_STR
);
10145 vty_out(vty
, "%u", bgp
->vrf_id
);
10146 vty_out(vty
, "\n");
10147 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10148 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10149 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10151 vty_out(vty
, "Originating default network %s\n\n",
10152 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10157 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10158 if (type
== bgp_show_adj_route_received
10159 || type
== bgp_show_adj_route_filtered
) {
10160 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10161 if (ain
->peer
!= peer
|| !ain
->attr
)
10166 json_object_int_add(
10167 json
, "bgpTableVersion",
10169 json_object_string_add(
10171 "bgpLocalRouterId",
10174 json_object_object_add(
10175 json
, "bgpStatusCodes",
10177 json_object_object_add(
10178 json
, "bgpOriginCodes",
10182 "BGP table version is 0, local router ID is %s, vrf id ",
10185 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10191 vty_out(vty
, "\n");
10193 BGP_SHOW_SCODE_HEADER
);
10195 BGP_SHOW_NCODE_HEADER
);
10197 BGP_SHOW_OCODE_HEADER
);
10203 vty_out(vty
, BGP_SHOW_HEADER
);
10207 bgp_attr_dup(&attr
, ain
->attr
);
10208 route_filtered
= false;
10210 /* Filter prefix using distribute list,
10211 * filter list or prefix list
10213 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10214 safi
)) == FILTER_DENY
)
10215 route_filtered
= true;
10217 /* Filter prefix using route-map */
10218 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10219 afi
, safi
, rmap_name
);
10221 if (type
== bgp_show_adj_route_filtered
&&
10222 !route_filtered
&& ret
!= RMAP_DENY
) {
10223 bgp_attr_undup(&attr
, ain
->attr
);
10227 if (type
== bgp_show_adj_route_received
&&
10228 (route_filtered
|| ret
== RMAP_DENY
))
10231 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10232 use_json
, json_ar
);
10233 bgp_attr_undup(&attr
, ain
->attr
);
10236 } else if (type
== bgp_show_adj_route_advertised
) {
10237 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10238 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10239 if (paf
->peer
!= peer
|| !adj
->attr
)
10244 json_object_int_add(
10248 json_object_string_add(
10250 "bgpLocalRouterId",
10253 json_object_object_add(
10257 json_object_object_add(
10263 "BGP table version is %" PRIu64
10264 ", local router ID is %s, vrf id ",
10277 vty_out(vty
, "\n");
10279 BGP_SHOW_SCODE_HEADER
);
10281 BGP_SHOW_NCODE_HEADER
);
10283 BGP_SHOW_OCODE_HEADER
);
10294 bgp_attr_dup(&attr
, adj
->attr
);
10295 ret
= bgp_output_modifier(
10296 peer
, &rn
->p
, &attr
, afi
, safi
,
10299 if (ret
!= RMAP_DENY
) {
10300 route_vty_out_tmp(vty
, &rn
->p
,
10309 bgp_attr_undup(&attr
, adj
->attr
);
10315 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10316 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10317 json_object_int_add(json
, "filteredPrefixCounter",
10320 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10321 json
, JSON_C_TO_STRING_PRETTY
));
10322 json_object_free(json
);
10323 } else if (output_count
> 0) {
10324 if (filtered_count
> 0)
10326 "\nTotal number of prefixes %ld (%ld filtered)\n",
10327 output_count
, filtered_count
);
10329 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10334 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10335 safi_t safi
, enum bgp_show_adj_route_type type
,
10336 const char *rmap_name
, uint8_t use_json
)
10338 json_object
*json
= NULL
;
10341 json
= json_object_new_object();
10343 /* labeled-unicast routes live in the unicast table */
10344 if (safi
== SAFI_LABELED_UNICAST
)
10345 safi
= SAFI_UNICAST
;
10347 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10349 json_object_string_add(
10351 "No such neighbor or address family");
10352 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10353 json_object_free(json
);
10355 vty_out(vty
, "%% No such neighbor or address family\n");
10357 return CMD_WARNING
;
10360 if ((type
== bgp_show_adj_route_received
10361 || type
== bgp_show_adj_route_filtered
)
10362 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10363 PEER_FLAG_SOFT_RECONFIG
)) {
10365 json_object_string_add(
10367 "Inbound soft reconfiguration not enabled");
10368 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10369 json_object_free(json
);
10372 "%% Inbound soft reconfiguration not enabled\n");
10374 return CMD_WARNING
;
10377 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10379 return CMD_SUCCESS
;
10382 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10383 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10384 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10385 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10389 BGP_INSTANCE_HELP_STR
10391 BGP_SAFI_WITH_LABEL_HELP_STR
10392 "Detailed information on TCP and BGP neighbor connections\n"
10393 "Neighbor to display information about\n"
10394 "Neighbor to display information about\n"
10395 "Neighbor on BGP configured interface\n"
10396 "Display the routes advertised to a BGP neighbor\n"
10397 "Display the received routes from neighbor\n"
10398 "Display the filtered routes received from neighbor\n"
10399 "Route-map to modify the attributes\n"
10400 "Name of the route map\n"
10403 afi_t afi
= AFI_IP6
;
10404 safi_t safi
= SAFI_UNICAST
;
10405 char *rmap_name
= NULL
;
10406 char *peerstr
= NULL
;
10407 struct bgp
*bgp
= NULL
;
10409 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10412 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10415 return CMD_WARNING
;
10417 int uj
= use_json(argc
, argv
);
10422 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10423 argv_find(argv
, argc
, "neighbors", &idx
);
10424 peerstr
= argv
[++idx
]->arg
;
10426 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10428 return CMD_WARNING
;
10430 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10431 type
= bgp_show_adj_route_advertised
;
10432 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10433 type
= bgp_show_adj_route_received
;
10434 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10435 type
= bgp_show_adj_route_filtered
;
10437 if (argv_find(argv
, argc
, "route-map", &idx
))
10438 rmap_name
= argv
[++idx
]->arg
;
10440 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10443 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10444 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10445 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10451 "Address Family modifier\n"
10452 "Detailed information on TCP and BGP neighbor connections\n"
10453 "Neighbor to display information about\n"
10454 "Neighbor to display information about\n"
10455 "Neighbor on BGP configured interface\n"
10456 "Display information received from a BGP neighbor\n"
10457 "Display the prefixlist filter\n"
10460 afi_t afi
= AFI_IP6
;
10461 safi_t safi
= SAFI_UNICAST
;
10462 char *peerstr
= NULL
;
10465 union sockunion su
;
10471 /* show [ip] bgp */
10472 if (argv_find(argv
, argc
, "ip", &idx
))
10474 /* [<ipv4|ipv6> [unicast]] */
10475 if (argv_find(argv
, argc
, "ipv4", &idx
))
10477 if (argv_find(argv
, argc
, "ipv6", &idx
))
10479 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10480 argv_find(argv
, argc
, "neighbors", &idx
);
10481 peerstr
= argv
[++idx
]->arg
;
10483 uint8_t uj
= use_json(argc
, argv
);
10485 ret
= str2sockunion(peerstr
, &su
);
10487 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10490 vty_out(vty
, "{}\n");
10493 "%% Malformed address or name: %s\n",
10495 return CMD_WARNING
;
10498 peer
= peer_lookup(NULL
, &su
);
10501 vty_out(vty
, "{}\n");
10503 vty_out(vty
, "No peer\n");
10504 return CMD_WARNING
;
10508 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10509 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10512 vty_out(vty
, "Address Family: %s\n",
10513 afi_safi_print(afi
, safi
));
10514 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10517 vty_out(vty
, "{}\n");
10519 vty_out(vty
, "No functional output\n");
10522 return CMD_SUCCESS
;
10525 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10526 afi_t afi
, safi_t safi
,
10527 enum bgp_show_type type
, uint8_t use_json
)
10529 /* labeled-unicast routes live in the unicast table */
10530 if (safi
== SAFI_LABELED_UNICAST
)
10531 safi
= SAFI_UNICAST
;
10533 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10535 json_object
*json_no
= NULL
;
10536 json_no
= json_object_new_object();
10537 json_object_string_add(
10538 json_no
, "warning",
10539 "No such neighbor or address family");
10540 vty_out(vty
, "%s\n",
10541 json_object_to_json_string(json_no
));
10542 json_object_free(json_no
);
10544 vty_out(vty
, "%% No such neighbor or address family\n");
10545 return CMD_WARNING
;
10548 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10551 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10552 show_ip_bgp_flowspec_routes_detailed_cmd
,
10553 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10557 BGP_INSTANCE_HELP_STR
10560 "Detailed information on flowspec entries\n"
10563 afi_t afi
= AFI_IP
;
10564 safi_t safi
= SAFI_UNICAST
;
10565 struct bgp
*bgp
= NULL
;
10568 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10571 return CMD_WARNING
;
10573 return bgp_show(vty
, bgp
, afi
, safi
,
10574 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10577 DEFUN (show_ip_bgp_neighbor_routes
,
10578 show_ip_bgp_neighbor_routes_cmd
,
10579 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10580 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10584 BGP_INSTANCE_HELP_STR
10586 BGP_SAFI_WITH_LABEL_HELP_STR
10587 "Detailed information on TCP and BGP neighbor connections\n"
10588 "Neighbor to display information about\n"
10589 "Neighbor to display information about\n"
10590 "Neighbor on BGP configured interface\n"
10591 "Display flap statistics of the routes learned from neighbor\n"
10592 "Display the dampened routes received from neighbor\n"
10593 "Display routes learned from neighbor\n"
10596 char *peerstr
= NULL
;
10597 struct bgp
*bgp
= NULL
;
10598 afi_t afi
= AFI_IP6
;
10599 safi_t safi
= SAFI_UNICAST
;
10601 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10605 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10608 return CMD_WARNING
;
10610 int uj
= use_json(argc
, argv
);
10614 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10615 argv_find(argv
, argc
, "neighbors", &idx
);
10616 peerstr
= argv
[++idx
]->arg
;
10618 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10620 return CMD_WARNING
;
10622 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10623 sh_type
= bgp_show_type_flap_neighbor
;
10624 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10625 sh_type
= bgp_show_type_damp_neighbor
;
10626 else if (argv_find(argv
, argc
, "routes", &idx
))
10627 sh_type
= bgp_show_type_neighbor
;
10629 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10632 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10634 struct bgp_distance
{
10635 /* Distance value for the IP source prefix. */
10638 /* Name of the access-list to be matched. */
10642 DEFUN (show_bgp_afi_vpn_rd_route
,
10643 show_bgp_afi_vpn_rd_route_cmd
,
10644 "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]",
10648 "Address Family modifier\n"
10649 "Display information for a route distinguisher\n"
10650 "Route Distinguisher\n"
10651 "Network in the BGP routing table to display\n"
10652 "Network in the BGP routing table to display\n"
10656 struct prefix_rd prd
;
10657 afi_t afi
= AFI_MAX
;
10660 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10661 vty_out(vty
, "%% Malformed Address Family\n");
10662 return CMD_WARNING
;
10665 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10667 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10668 return CMD_WARNING
;
10671 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10672 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10675 static struct bgp_distance
*bgp_distance_new(void)
10677 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10680 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10682 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10685 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10686 const char *ip_str
, const char *access_list_str
)
10693 struct bgp_node
*rn
;
10694 struct bgp_distance
*bdistance
;
10696 afi
= bgp_node_afi(vty
);
10697 safi
= bgp_node_safi(vty
);
10699 ret
= str2prefix(ip_str
, &p
);
10701 vty_out(vty
, "Malformed prefix\n");
10702 return CMD_WARNING_CONFIG_FAILED
;
10705 distance
= atoi(distance_str
);
10707 /* Get BGP distance node. */
10708 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10710 bdistance
= rn
->info
;
10711 bgp_unlock_node(rn
);
10713 bdistance
= bgp_distance_new();
10714 rn
->info
= bdistance
;
10717 /* Set distance value. */
10718 bdistance
->distance
= distance
;
10720 /* Reset access-list configuration. */
10721 if (bdistance
->access_list
) {
10722 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10723 bdistance
->access_list
= NULL
;
10725 if (access_list_str
)
10726 bdistance
->access_list
=
10727 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10729 return CMD_SUCCESS
;
10732 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10733 const char *ip_str
, const char *access_list_str
)
10740 struct bgp_node
*rn
;
10741 struct bgp_distance
*bdistance
;
10743 afi
= bgp_node_afi(vty
);
10744 safi
= bgp_node_safi(vty
);
10746 ret
= str2prefix(ip_str
, &p
);
10748 vty_out(vty
, "Malformed prefix\n");
10749 return CMD_WARNING_CONFIG_FAILED
;
10752 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10753 (struct prefix
*)&p
);
10755 vty_out(vty
, "Can't find specified prefix\n");
10756 return CMD_WARNING_CONFIG_FAILED
;
10759 bdistance
= rn
->info
;
10760 distance
= atoi(distance_str
);
10762 if (bdistance
->distance
!= distance
) {
10763 vty_out(vty
, "Distance does not match configured\n");
10764 return CMD_WARNING_CONFIG_FAILED
;
10767 if (bdistance
->access_list
)
10768 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10769 bgp_distance_free(bdistance
);
10772 bgp_unlock_node(rn
);
10773 bgp_unlock_node(rn
);
10775 return CMD_SUCCESS
;
10778 /* Apply BGP information to distance method. */
10779 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10780 safi_t safi
, struct bgp
*bgp
)
10782 struct bgp_node
*rn
;
10785 struct bgp_distance
*bdistance
;
10786 struct access_list
*alist
;
10787 struct bgp_static
*bgp_static
;
10792 peer
= rinfo
->peer
;
10794 /* Check source address. */
10795 sockunion2hostprefix(&peer
->su
, &q
);
10796 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10798 bdistance
= rn
->info
;
10799 bgp_unlock_node(rn
);
10801 if (bdistance
->access_list
) {
10802 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10804 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10805 return bdistance
->distance
;
10807 return bdistance
->distance
;
10810 /* Backdoor check. */
10811 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10813 bgp_static
= rn
->info
;
10814 bgp_unlock_node(rn
);
10816 if (bgp_static
->backdoor
) {
10817 if (bgp
->distance_local
[afi
][safi
])
10818 return bgp
->distance_local
[afi
][safi
];
10820 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10824 if (peer
->sort
== BGP_PEER_EBGP
) {
10825 if (bgp
->distance_ebgp
[afi
][safi
])
10826 return bgp
->distance_ebgp
[afi
][safi
];
10827 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10829 if (bgp
->distance_ibgp
[afi
][safi
])
10830 return bgp
->distance_ibgp
[afi
][safi
];
10831 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10835 DEFUN (bgp_distance
,
10837 "distance bgp (1-255) (1-255) (1-255)",
10838 "Define an administrative distance\n"
10840 "Distance for routes external to the AS\n"
10841 "Distance for routes internal to the AS\n"
10842 "Distance for local routes\n")
10844 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10845 int idx_number
= 2;
10846 int idx_number_2
= 3;
10847 int idx_number_3
= 4;
10851 afi
= bgp_node_afi(vty
);
10852 safi
= bgp_node_safi(vty
);
10854 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10855 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10856 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10857 return CMD_SUCCESS
;
10860 DEFUN (no_bgp_distance
,
10861 no_bgp_distance_cmd
,
10862 "no distance bgp [(1-255) (1-255) (1-255)]",
10864 "Define an administrative distance\n"
10866 "Distance for routes external to the AS\n"
10867 "Distance for routes internal to the AS\n"
10868 "Distance for local routes\n")
10870 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10874 afi
= bgp_node_afi(vty
);
10875 safi
= bgp_node_safi(vty
);
10877 bgp
->distance_ebgp
[afi
][safi
] = 0;
10878 bgp
->distance_ibgp
[afi
][safi
] = 0;
10879 bgp
->distance_local
[afi
][safi
] = 0;
10880 return CMD_SUCCESS
;
10884 DEFUN (bgp_distance_source
,
10885 bgp_distance_source_cmd
,
10886 "distance (1-255) A.B.C.D/M",
10887 "Define an administrative distance\n"
10888 "Administrative distance\n"
10889 "IP source prefix\n")
10891 int idx_number
= 1;
10892 int idx_ipv4_prefixlen
= 2;
10893 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10894 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10895 return CMD_SUCCESS
;
10898 DEFUN (no_bgp_distance_source
,
10899 no_bgp_distance_source_cmd
,
10900 "no distance (1-255) A.B.C.D/M",
10902 "Define an administrative distance\n"
10903 "Administrative distance\n"
10904 "IP source prefix\n")
10906 int idx_number
= 2;
10907 int idx_ipv4_prefixlen
= 3;
10908 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10909 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10910 return CMD_SUCCESS
;
10913 DEFUN (bgp_distance_source_access_list
,
10914 bgp_distance_source_access_list_cmd
,
10915 "distance (1-255) A.B.C.D/M WORD",
10916 "Define an administrative distance\n"
10917 "Administrative distance\n"
10918 "IP source prefix\n"
10919 "Access list name\n")
10921 int idx_number
= 1;
10922 int idx_ipv4_prefixlen
= 2;
10924 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10925 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10926 return CMD_SUCCESS
;
10929 DEFUN (no_bgp_distance_source_access_list
,
10930 no_bgp_distance_source_access_list_cmd
,
10931 "no distance (1-255) A.B.C.D/M WORD",
10933 "Define an administrative distance\n"
10934 "Administrative distance\n"
10935 "IP source prefix\n"
10936 "Access list name\n")
10938 int idx_number
= 2;
10939 int idx_ipv4_prefixlen
= 3;
10941 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10942 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10943 return CMD_SUCCESS
;
10946 DEFUN (ipv6_bgp_distance_source
,
10947 ipv6_bgp_distance_source_cmd
,
10948 "distance (1-255) X:X::X:X/M",
10949 "Define an administrative distance\n"
10950 "Administrative distance\n"
10951 "IP source prefix\n")
10953 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10954 return CMD_SUCCESS
;
10957 DEFUN (no_ipv6_bgp_distance_source
,
10958 no_ipv6_bgp_distance_source_cmd
,
10959 "no distance (1-255) X:X::X:X/M",
10961 "Define an administrative distance\n"
10962 "Administrative distance\n"
10963 "IP source prefix\n")
10965 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10966 return CMD_SUCCESS
;
10969 DEFUN (ipv6_bgp_distance_source_access_list
,
10970 ipv6_bgp_distance_source_access_list_cmd
,
10971 "distance (1-255) X:X::X:X/M WORD",
10972 "Define an administrative distance\n"
10973 "Administrative distance\n"
10974 "IP source prefix\n"
10975 "Access list name\n")
10977 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10978 return CMD_SUCCESS
;
10981 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10982 no_ipv6_bgp_distance_source_access_list_cmd
,
10983 "no distance (1-255) X:X::X:X/M WORD",
10985 "Define an administrative distance\n"
10986 "Administrative distance\n"
10987 "IP source prefix\n"
10988 "Access list name\n")
10990 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10991 return CMD_SUCCESS
;
10994 DEFUN (bgp_damp_set
,
10996 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10997 "BGP Specific commands\n"
10998 "Enable route-flap dampening\n"
10999 "Half-life time for the penalty\n"
11000 "Value to start reusing a route\n"
11001 "Value to start suppressing a route\n"
11002 "Maximum duration to suppress a stable route\n")
11004 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11005 int idx_half_life
= 2;
11007 int idx_suppress
= 4;
11008 int idx_max_suppress
= 5;
11009 int half
= DEFAULT_HALF_LIFE
* 60;
11010 int reuse
= DEFAULT_REUSE
;
11011 int suppress
= DEFAULT_SUPPRESS
;
11012 int max
= 4 * half
;
11015 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11016 reuse
= atoi(argv
[idx_reuse
]->arg
);
11017 suppress
= atoi(argv
[idx_suppress
]->arg
);
11018 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11019 } else if (argc
== 3) {
11020 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11024 if (suppress
< reuse
) {
11026 "Suppress value cannot be less than reuse value \n");
11030 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11031 reuse
, suppress
, max
);
11034 DEFUN (bgp_damp_unset
,
11035 bgp_damp_unset_cmd
,
11036 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11038 "BGP Specific commands\n"
11039 "Enable route-flap dampening\n"
11040 "Half-life time for the penalty\n"
11041 "Value to start reusing a route\n"
11042 "Value to start suppressing a route\n"
11043 "Maximum duration to suppress a stable route\n")
11045 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11046 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11049 /* Display specified route of BGP table. */
11050 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11051 const char *ip_str
, afi_t afi
, safi_t safi
,
11052 struct prefix_rd
*prd
, int prefix_check
)
11055 struct prefix match
;
11056 struct bgp_node
*rn
;
11057 struct bgp_node
*rm
;
11058 struct bgp_info
*ri
;
11059 struct bgp_info
*ri_temp
;
11061 struct bgp_table
*table
;
11063 /* BGP structure lookup. */
11065 bgp
= bgp_lookup_by_name(view_name
);
11067 vty_out(vty
, "%% Can't find BGP instance %s\n",
11069 return CMD_WARNING
;
11072 bgp
= bgp_get_default();
11074 vty_out(vty
, "%% No BGP process is configured\n");
11075 return CMD_WARNING
;
11079 /* Check IP address argument. */
11080 ret
= str2prefix(ip_str
, &match
);
11082 vty_out(vty
, "%% address is malformed\n");
11083 return CMD_WARNING
;
11086 match
.family
= afi2family(afi
);
11088 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11089 || (safi
== SAFI_EVPN
)) {
11090 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11091 rn
= bgp_route_next(rn
)) {
11092 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11094 if ((table
= rn
->info
) == NULL
)
11096 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11100 || rm
->p
.prefixlen
== match
.prefixlen
) {
11103 if (ri
->extra
&& ri
->extra
->damp_info
) {
11104 ri_temp
= ri
->next
;
11105 bgp_damp_info_free(
11106 ri
->extra
->damp_info
,
11114 bgp_unlock_node(rm
);
11117 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11120 || rn
->p
.prefixlen
== match
.prefixlen
) {
11123 if (ri
->extra
&& ri
->extra
->damp_info
) {
11124 ri_temp
= ri
->next
;
11125 bgp_damp_info_free(
11126 ri
->extra
->damp_info
,
11134 bgp_unlock_node(rn
);
11138 return CMD_SUCCESS
;
11141 DEFUN (clear_ip_bgp_dampening
,
11142 clear_ip_bgp_dampening_cmd
,
11143 "clear ip bgp dampening",
11147 "Clear route flap dampening information\n")
11149 bgp_damp_info_clean();
11150 return CMD_SUCCESS
;
11153 DEFUN (clear_ip_bgp_dampening_prefix
,
11154 clear_ip_bgp_dampening_prefix_cmd
,
11155 "clear ip bgp dampening A.B.C.D/M",
11159 "Clear route flap dampening information\n"
11162 int idx_ipv4_prefixlen
= 4;
11163 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11164 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11167 DEFUN (clear_ip_bgp_dampening_address
,
11168 clear_ip_bgp_dampening_address_cmd
,
11169 "clear ip bgp dampening A.B.C.D",
11173 "Clear route flap dampening information\n"
11174 "Network to clear damping information\n")
11177 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11178 SAFI_UNICAST
, NULL
, 0);
11181 DEFUN (clear_ip_bgp_dampening_address_mask
,
11182 clear_ip_bgp_dampening_address_mask_cmd
,
11183 "clear ip bgp dampening A.B.C.D A.B.C.D",
11187 "Clear route flap dampening information\n"
11188 "Network to clear damping information\n"
11192 int idx_ipv4_2
= 5;
11194 char prefix_str
[BUFSIZ
];
11196 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11199 vty_out(vty
, "%% Inconsistent address and mask\n");
11200 return CMD_WARNING
;
11203 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11207 /* also used for encap safi */
11208 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11209 afi_t afi
, safi_t safi
)
11211 struct bgp_node
*prn
;
11212 struct bgp_node
*rn
;
11213 struct bgp_table
*table
;
11215 struct prefix_rd
*prd
;
11216 struct bgp_static
*bgp_static
;
11217 mpls_label_t label
;
11218 char buf
[SU_ADDRSTRLEN
];
11219 char rdbuf
[RD_ADDRSTRLEN
];
11221 /* Network configuration. */
11222 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11223 prn
= bgp_route_next(prn
)) {
11224 if ((table
= prn
->info
) == NULL
)
11227 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11228 if ((bgp_static
= rn
->info
) == NULL
)
11232 prd
= (struct prefix_rd
*)&prn
->p
;
11234 /* "network" configuration display. */
11235 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11236 label
= decode_label(&bgp_static
->label
);
11238 vty_out(vty
, " network %s/%d rd %s",
11239 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11241 p
->prefixlen
, rdbuf
);
11242 if (safi
== SAFI_MPLS_VPN
)
11243 vty_out(vty
, " label %u", label
);
11245 if (bgp_static
->rmap
.name
)
11246 vty_out(vty
, " route-map %s",
11247 bgp_static
->rmap
.name
);
11249 if (bgp_static
->backdoor
)
11250 vty_out(vty
, " backdoor");
11252 vty_out(vty
, "\n");
11257 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11258 afi_t afi
, safi_t safi
)
11260 struct bgp_node
*prn
;
11261 struct bgp_node
*rn
;
11262 struct bgp_table
*table
;
11264 struct prefix_rd
*prd
;
11265 struct bgp_static
*bgp_static
;
11266 char buf
[PREFIX_STRLEN
* 2];
11267 char buf2
[SU_ADDRSTRLEN
];
11268 char rdbuf
[RD_ADDRSTRLEN
];
11270 /* Network configuration. */
11271 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11272 prn
= bgp_route_next(prn
)) {
11273 if ((table
= prn
->info
) == NULL
)
11276 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11277 if ((bgp_static
= rn
->info
) == NULL
)
11280 char *macrouter
= NULL
;
11283 if (bgp_static
->router_mac
)
11284 macrouter
= prefix_mac2str(
11285 bgp_static
->router_mac
, NULL
, 0);
11286 if (bgp_static
->eth_s_id
)
11287 esi
= esi2str(bgp_static
->eth_s_id
);
11289 prd
= (struct prefix_rd
*)&prn
->p
;
11291 /* "network" configuration display. */
11292 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11293 if (p
->u
.prefix_evpn
.route_type
== 5) {
11294 char local_buf
[PREFIX_STRLEN
];
11295 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11296 struct prefix_evpn
*)p
)
11300 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11301 local_buf
, PREFIX_STRLEN
);
11302 sprintf(buf
, "%s/%u", local_buf
,
11303 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11305 prefix2str(p
, buf
, sizeof(buf
));
11308 if (bgp_static
->gatewayIp
.family
== AF_INET
11309 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11310 inet_ntop(bgp_static
->gatewayIp
.family
,
11311 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11314 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11316 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11317 decode_label(&bgp_static
->label
), esi
, buf2
,
11321 XFREE(MTYPE_TMP
, macrouter
);
11323 XFREE(MTYPE_TMP
, esi
);
11328 /* Configuration of static route announcement and aggregate
11330 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11333 struct bgp_node
*rn
;
11335 struct bgp_static
*bgp_static
;
11336 struct bgp_aggregate
*bgp_aggregate
;
11337 char buf
[SU_ADDRSTRLEN
];
11339 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11340 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11344 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11345 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11349 /* Network configuration. */
11350 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11351 rn
= bgp_route_next(rn
)) {
11352 if ((bgp_static
= rn
->info
) == NULL
)
11357 /* "network" configuration display. */
11358 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11359 uint32_t destination
;
11360 struct in_addr netmask
;
11362 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11363 masklen2ip(p
->prefixlen
, &netmask
);
11364 vty_out(vty
, " network %s",
11365 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11368 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11369 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11370 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11371 || p
->u
.prefix4
.s_addr
== 0) {
11372 /* Natural mask is not display. */
11374 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11376 vty_out(vty
, " network %s/%d",
11377 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11382 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11383 vty_out(vty
, " label-index %u",
11384 bgp_static
->label_index
);
11386 if (bgp_static
->rmap
.name
)
11387 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11389 if (bgp_static
->backdoor
)
11390 vty_out(vty
, " backdoor");
11392 vty_out(vty
, "\n");
11395 /* Aggregate-address configuration. */
11396 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11397 rn
= bgp_route_next(rn
)) {
11398 if ((bgp_aggregate
= rn
->info
) == NULL
)
11403 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11404 struct in_addr netmask
;
11406 masklen2ip(p
->prefixlen
, &netmask
);
11407 vty_out(vty
, " aggregate-address %s %s",
11408 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11410 inet_ntoa(netmask
));
11412 vty_out(vty
, " aggregate-address %s/%d",
11413 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11418 if (bgp_aggregate
->as_set
)
11419 vty_out(vty
, " as-set");
11421 if (bgp_aggregate
->summary_only
)
11422 vty_out(vty
, " summary-only");
11424 vty_out(vty
, "\n");
11428 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11431 struct bgp_node
*rn
;
11432 struct bgp_distance
*bdistance
;
11434 /* Distance configuration. */
11435 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11436 && bgp
->distance_local
[afi
][safi
]
11437 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11438 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11439 || bgp
->distance_local
[afi
][safi
]
11440 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11441 vty_out(vty
, " distance bgp %d %d %d\n",
11442 bgp
->distance_ebgp
[afi
][safi
],
11443 bgp
->distance_ibgp
[afi
][safi
],
11444 bgp
->distance_local
[afi
][safi
]);
11447 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11448 rn
= bgp_route_next(rn
))
11449 if ((bdistance
= rn
->info
) != NULL
) {
11450 char buf
[PREFIX_STRLEN
];
11452 vty_out(vty
, " distance %d %s %s\n",
11453 bdistance
->distance
,
11454 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11455 bdistance
->access_list
? bdistance
->access_list
11460 /* Allocate routing table structure and install commands. */
11461 void bgp_route_init(void)
11466 /* Init BGP distance table. */
11467 FOREACH_AFI_SAFI (afi
, safi
)
11468 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11470 /* IPv4 BGP commands. */
11471 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11472 install_element(BGP_NODE
, &bgp_network_cmd
);
11473 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11475 install_element(BGP_NODE
, &aggregate_address_cmd
);
11476 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11477 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11478 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11480 /* IPv4 unicast configuration. */
11481 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11482 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11483 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11485 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11486 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11487 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11488 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11490 /* IPv4 multicast configuration. */
11491 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11492 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11493 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11494 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11495 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11496 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11497 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11499 /* IPv4 labeled-unicast configuration. */
11500 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11501 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11502 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11503 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11504 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11506 install_element(VIEW_NODE
,
11507 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11508 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11509 install_element(VIEW_NODE
,
11510 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11511 #ifdef KEEP_OLD_VPN_COMMANDS
11512 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11513 #endif /* KEEP_OLD_VPN_COMMANDS */
11514 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11515 install_element(VIEW_NODE
,
11516 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11518 /* BGP dampening clear commands */
11519 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11520 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11522 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11523 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11526 install_element(ENABLE_NODE
,
11527 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11528 #ifdef KEEP_OLD_VPN_COMMANDS
11529 install_element(ENABLE_NODE
,
11530 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11531 #endif /* KEEP_OLD_VPN_COMMANDS */
11533 /* New config IPv6 BGP commands. */
11534 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11535 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11536 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11538 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11539 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11541 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11543 install_element(BGP_NODE
, &bgp_distance_cmd
);
11544 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11545 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11546 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11547 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11548 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11549 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11550 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11551 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11552 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11553 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11554 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11555 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11556 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11557 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11558 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11559 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11560 install_element(BGP_IPV4M_NODE
,
11561 &no_bgp_distance_source_access_list_cmd
);
11562 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11563 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11564 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11565 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11566 install_element(BGP_IPV6_NODE
,
11567 &ipv6_bgp_distance_source_access_list_cmd
);
11568 install_element(BGP_IPV6_NODE
,
11569 &no_ipv6_bgp_distance_source_access_list_cmd
);
11570 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11571 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11572 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11573 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11574 install_element(BGP_IPV6M_NODE
,
11575 &ipv6_bgp_distance_source_access_list_cmd
);
11576 install_element(BGP_IPV6M_NODE
,
11577 &no_ipv6_bgp_distance_source_access_list_cmd
);
11579 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11580 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11581 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11582 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11584 /* IPv4 Multicast Mode */
11585 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11586 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11588 /* Large Communities */
11589 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11590 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11592 /* show bgp ipv4 flowspec detailed */
11593 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11597 void bgp_route_finish(void)
11602 FOREACH_AFI_SAFI (afi
, safi
) {
11603 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11604 bgp_distance_table
[afi
][safi
] = NULL
;