1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "sockunion.h"
37 #include "workqueue.h"
41 #include "lib_errors.h"
43 #include "bgpd/bgpd.h"
44 #include "bgpd/bgp_table.h"
45 #include "bgpd/bgp_route.h"
46 #include "bgpd/bgp_attr.h"
47 #include "bgpd/bgp_debug.h"
48 #include "bgpd/bgp_errors.h"
49 #include "bgpd/bgp_aspath.h"
50 #include "bgpd/bgp_regex.h"
51 #include "bgpd/bgp_community.h"
52 #include "bgpd/bgp_ecommunity.h"
53 #include "bgpd/bgp_lcommunity.h"
54 #include "bgpd/bgp_clist.h"
55 #include "bgpd/bgp_packet.h"
56 #include "bgpd/bgp_filter.h"
57 #include "bgpd/bgp_fsm.h"
58 #include "bgpd/bgp_mplsvpn.h"
59 #include "bgpd/bgp_nexthop.h"
60 #include "bgpd/bgp_damp.h"
61 #include "bgpd/bgp_advertise.h"
62 #include "bgpd/bgp_zebra.h"
63 #include "bgpd/bgp_vty.h"
64 #include "bgpd/bgp_mpath.h"
65 #include "bgpd/bgp_nht.h"
66 #include "bgpd/bgp_updgrp.h"
67 #include "bgpd/bgp_label.h"
70 #include "bgpd/rfapi/rfapi_backend.h"
71 #include "bgpd/rfapi/vnc_import_bgp.h"
72 #include "bgpd/rfapi/vnc_export_bgp.h"
74 #include "bgpd/bgp_encap_types.h"
75 #include "bgpd/bgp_encap_tlv.h"
76 #include "bgpd/bgp_evpn.h"
77 #include "bgpd/bgp_evpn_vty.h"
78 #include "bgpd/bgp_flowspec.h"
79 #include "bgpd/bgp_flowspec_util.h"
80 #include "bgpd/bgp_pbr.h"
82 #ifndef VTYSH_EXTRACT_PL
83 #include "bgpd/bgp_route_clippy.c"
86 /* Extern from bgp_dump.c */
87 extern const char *bgp_origin_str
[];
88 extern const char *bgp_origin_long_str
[];
91 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
92 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
93 static const struct message bgp_pmsi_tnltype_str
[] = {
94 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
95 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
96 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
97 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
98 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
99 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
100 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
101 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
105 #define VRFID_NONE_STR "-"
107 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
108 safi_t safi
, struct prefix
*p
,
109 struct prefix_rd
*prd
)
112 struct bgp_node
*prn
= NULL
;
118 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
119 || (safi
== SAFI_EVPN
)) {
120 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
122 if (prn
->info
== NULL
)
123 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
125 bgp_unlock_node(prn
);
129 rn
= bgp_node_get(table
, p
);
131 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
132 || (safi
== SAFI_EVPN
))
138 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
139 safi_t safi
, struct prefix
*p
,
140 struct prefix_rd
*prd
)
143 struct bgp_node
*prn
= NULL
;
148 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
149 || (safi
== SAFI_EVPN
)) {
150 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
154 if (prn
->info
== NULL
) {
155 bgp_unlock_node(prn
);
162 rn
= bgp_node_lookup(table
, p
);
167 /* Allocate bgp_info_extra */
168 static struct bgp_info_extra
*bgp_info_extra_new(void)
170 struct bgp_info_extra
*new;
171 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
172 new->label
[0] = MPLS_INVALID_LABEL
;
177 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
179 struct bgp_info_extra
*e
;
181 if (!extra
|| !*extra
)
186 bgp_damp_info_free(e
->damp_info
, 0);
190 struct bgp_info
*bi
= (struct bgp_info
*)e
->parent
;
193 /* FIXME: since multiple e may have the same e->parent
194 * and e->parent->net is holding a refcount for each
195 * of them, we need to do some fudging here.
197 * WARNING: if bi->net->lock drops to 0, bi may be
198 * freed as well (because bi->net was holding the
199 * last reference to bi) => write after free!
203 bi
= bgp_info_lock(bi
);
204 refcount
= bi
->net
->lock
- 1;
205 bgp_unlock_node((struct bgp_node
*)bi
->net
);
210 bgp_info_unlock(e
->parent
);
215 bgp_unlock(e
->bgp_orig
);
217 if ((*extra
)->bgp_fs_pbr
)
218 list_delete(&((*extra
)->bgp_fs_pbr
));
219 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
224 /* Get bgp_info extra information for the given bgp_info, lazy allocated
227 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
230 ri
->extra
= bgp_info_extra_new();
234 /* Allocate new bgp info structure. */
235 struct bgp_info
*bgp_info_new(void)
237 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
240 /* Free bgp route information. */
241 static void bgp_info_free(struct bgp_info
*binfo
)
244 bgp_attr_unintern(&binfo
->attr
);
246 bgp_unlink_nexthop(binfo
);
247 bgp_info_extra_free(&binfo
->extra
);
248 bgp_info_mpath_free(&binfo
->mpath
);
250 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
252 XFREE(MTYPE_BGP_ROUTE
, binfo
);
255 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
261 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
263 assert(binfo
&& binfo
->lock
> 0);
266 if (binfo
->lock
== 0) {
268 zlog_debug ("%s: unlocked and freeing", __func__
);
269 zlog_backtrace (LOG_DEBUG
);
271 bgp_info_free(binfo
);
276 if (binfo
->lock
== 1)
278 zlog_debug ("%s: unlocked to 1", __func__
);
279 zlog_backtrace (LOG_DEBUG
);
286 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
288 struct bgp_info
*top
;
300 peer_lock(ri
->peer
); /* bgp_info peer reference */
303 /* Do the actual removal of info from RIB, for use by bgp_process
304 completion callback *only* */
305 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
308 ri
->next
->prev
= ri
->prev
;
310 ri
->prev
->next
= ri
->next
;
314 bgp_info_mpath_dequeue(ri
);
319 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
321 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
322 /* set of previous already took care of pcount */
323 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
326 /* undo the effects of a previous call to bgp_info_delete; typically
327 called when a route is deleted and then quickly re-added before the
328 deletion has been processed */
329 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
331 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
332 /* unset of previous already took care of pcount */
333 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
336 /* Adjust pcount as required */
337 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
339 struct bgp_table
*table
;
341 assert(rn
&& bgp_node_table(rn
));
342 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
344 table
= bgp_node_table(rn
);
346 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
349 if (!BGP_INFO_COUNTABLE(ri
)
350 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
352 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
354 /* slight hack, but more robust against errors. */
355 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
356 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
358 flog_err(EC_LIB_DEVELOPMENT
,
359 "Asked to decrement 0 prefix count for peer");
360 } else if (BGP_INFO_COUNTABLE(ri
)
361 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
362 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
363 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
367 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
369 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
372 /* Set/unset bgp_info flags, adjusting any other state as needed.
373 * This is here primarily to keep prefix-count in check.
375 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, uint32_t flag
)
377 SET_FLAG(ri
->flags
, flag
);
379 /* early bath if we know it's not a flag that changes countability state
381 if (!CHECK_FLAG(flag
,
382 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
385 bgp_pcount_adjust(rn
, ri
);
388 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
391 UNSET_FLAG(ri
->flags
, flag
);
393 /* early bath if we know it's not a flag that changes countability state
395 if (!CHECK_FLAG(flag
,
396 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
399 bgp_pcount_adjust(rn
, ri
);
402 /* Get MED value. If MED value is missing and "bgp bestpath
403 missing-as-worst" is specified, treat it as the worst value. */
404 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
406 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
409 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
416 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
418 if (ri
->addpath_rx_id
)
419 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
422 sprintf(buf
, "path %s", ri
->peer
->host
);
425 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
427 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
428 struct bgp_info
*exist
, int *paths_eq
,
429 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
430 char *pfx_buf
, afi_t afi
, safi_t safi
)
432 struct attr
*newattr
, *existattr
;
433 bgp_peer_sort_t new_sort
;
434 bgp_peer_sort_t exist_sort
;
440 uint32_t exist_weight
;
441 uint32_t newm
, existm
;
442 struct in_addr new_id
;
443 struct in_addr exist_id
;
446 int internal_as_route
;
449 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
450 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
452 uint32_t exist_mm_seq
;
459 zlog_debug("%s: new is NULL", pfx_buf
);
464 bgp_info_path_with_addpath_rx_str(new, new_buf
);
468 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
474 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
475 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
476 pfx_buf
, new_buf
, new->flags
, exist_buf
,
481 existattr
= exist
->attr
;
483 /* For EVPN routes, we cannot just go by local vs remote, we have to
484 * look at the MAC mobility sequence number, if present.
486 if (safi
== SAFI_EVPN
) {
487 /* This is an error condition described in RFC 7432 Section
489 * states that in this scenario "the PE MUST alert the operator"
491 * does not state what other action to take. In order to provide
493 * consistency in this scenario we are going to prefer the path
497 if (newattr
->sticky
!= existattr
->sticky
) {
499 prefix2str(&new->net
->p
, pfx_buf
,
501 * PREFIX2STR_BUFFER
);
502 bgp_info_path_with_addpath_rx_str(new, new_buf
);
503 bgp_info_path_with_addpath_rx_str(exist
,
507 if (newattr
->sticky
&& !existattr
->sticky
) {
510 "%s: %s wins over %s due to sticky MAC flag",
511 pfx_buf
, new_buf
, exist_buf
);
515 if (!newattr
->sticky
&& existattr
->sticky
) {
518 "%s: %s loses to %s due to sticky MAC flag",
519 pfx_buf
, new_buf
, exist_buf
);
524 new_mm_seq
= mac_mobility_seqnum(newattr
);
525 exist_mm_seq
= mac_mobility_seqnum(existattr
);
527 if (new_mm_seq
> exist_mm_seq
) {
530 "%s: %s wins over %s due to MM seq %u > %u",
531 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
536 if (new_mm_seq
< exist_mm_seq
) {
539 "%s: %s loses to %s due to MM seq %u < %u",
540 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
546 /* 1. Weight check. */
547 new_weight
= newattr
->weight
;
548 exist_weight
= existattr
->weight
;
550 if (new_weight
> exist_weight
) {
552 zlog_debug("%s: %s wins over %s due to weight %d > %d",
553 pfx_buf
, new_buf
, exist_buf
, new_weight
,
558 if (new_weight
< exist_weight
) {
560 zlog_debug("%s: %s loses to %s due to weight %d < %d",
561 pfx_buf
, new_buf
, exist_buf
, new_weight
,
566 /* 2. Local preference check. */
567 new_pref
= exist_pref
= bgp
->default_local_pref
;
569 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
570 new_pref
= newattr
->local_pref
;
571 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
572 exist_pref
= existattr
->local_pref
;
574 if (new_pref
> exist_pref
) {
577 "%s: %s wins over %s due to localpref %d > %d",
578 pfx_buf
, new_buf
, exist_buf
, new_pref
,
583 if (new_pref
< exist_pref
) {
586 "%s: %s loses to %s due to localpref %d < %d",
587 pfx_buf
, new_buf
, exist_buf
, new_pref
,
592 /* 3. Local route check. We prefer:
594 * - BGP_ROUTE_AGGREGATE
595 * - BGP_ROUTE_REDISTRIBUTE
597 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
598 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
601 "%s: %s wins over %s due to preferred BGP_ROUTE type",
602 pfx_buf
, new_buf
, exist_buf
);
606 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
607 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
610 "%s: %s loses to %s due to preferred BGP_ROUTE type",
611 pfx_buf
, new_buf
, exist_buf
);
615 /* 4. AS path length check. */
616 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
617 int exist_hops
= aspath_count_hops(existattr
->aspath
);
618 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
620 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
623 aspath_hops
= aspath_count_hops(newattr
->aspath
);
624 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
626 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
629 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
630 pfx_buf
, new_buf
, exist_buf
,
632 (exist_hops
+ exist_confeds
));
636 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
639 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
640 pfx_buf
, new_buf
, exist_buf
,
642 (exist_hops
+ exist_confeds
));
646 int newhops
= aspath_count_hops(newattr
->aspath
);
648 if (newhops
< exist_hops
) {
651 "%s: %s wins over %s due to aspath hopcount %d < %d",
652 pfx_buf
, new_buf
, exist_buf
,
653 newhops
, exist_hops
);
657 if (newhops
> exist_hops
) {
660 "%s: %s loses to %s due to aspath hopcount %d > %d",
661 pfx_buf
, new_buf
, exist_buf
,
662 newhops
, exist_hops
);
668 /* 5. Origin check. */
669 if (newattr
->origin
< existattr
->origin
) {
671 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
672 pfx_buf
, new_buf
, exist_buf
,
673 bgp_origin_long_str
[newattr
->origin
],
674 bgp_origin_long_str
[existattr
->origin
]);
678 if (newattr
->origin
> existattr
->origin
) {
680 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
681 pfx_buf
, new_buf
, exist_buf
,
682 bgp_origin_long_str
[newattr
->origin
],
683 bgp_origin_long_str
[existattr
->origin
]);
688 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
689 && aspath_count_hops(existattr
->aspath
) == 0);
690 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
691 && aspath_count_confeds(existattr
->aspath
) > 0
692 && aspath_count_hops(newattr
->aspath
) == 0
693 && aspath_count_hops(existattr
->aspath
) == 0);
695 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
696 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
697 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
698 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
699 || internal_as_route
) {
700 new_med
= bgp_med_value(new->attr
, bgp
);
701 exist_med
= bgp_med_value(exist
->attr
, bgp
);
703 if (new_med
< exist_med
) {
706 "%s: %s wins over %s due to MED %d < %d",
707 pfx_buf
, new_buf
, exist_buf
, new_med
,
712 if (new_med
> exist_med
) {
715 "%s: %s loses to %s due to MED %d > %d",
716 pfx_buf
, new_buf
, exist_buf
, new_med
,
722 /* 7. Peer type check. */
723 new_sort
= new->peer
->sort
;
724 exist_sort
= exist
->peer
->sort
;
726 if (new_sort
== BGP_PEER_EBGP
727 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
730 "%s: %s wins over %s due to eBGP peer > iBGP peer",
731 pfx_buf
, new_buf
, exist_buf
);
735 if (exist_sort
== BGP_PEER_EBGP
736 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
739 "%s: %s loses to %s due to iBGP peer < eBGP peer",
740 pfx_buf
, new_buf
, exist_buf
);
744 /* 8. IGP metric check. */
748 newm
= new->extra
->igpmetric
;
750 existm
= exist
->extra
->igpmetric
;
755 "%s: %s wins over %s due to IGP metric %d < %d",
756 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
763 "%s: %s loses to %s due to IGP metric %d > %d",
764 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
768 /* 9. Same IGP metric. Compare the cluster list length as
769 representative of IGP hops metric. Rewrite the metric value
770 pair (newm, existm) with the cluster list length. Prefer the
771 path with smaller cluster list length. */
772 if (newm
== existm
) {
773 if (peer_sort(new->peer
) == BGP_PEER_IBGP
774 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
775 && (mpath_cfg
== NULL
777 mpath_cfg
->ibgp_flags
,
778 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
779 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
780 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
785 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
786 pfx_buf
, new_buf
, exist_buf
,
794 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
795 pfx_buf
, new_buf
, exist_buf
,
802 /* 10. confed-external vs. confed-internal */
803 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
804 if (new_sort
== BGP_PEER_CONFED
805 && exist_sort
== BGP_PEER_IBGP
) {
808 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
809 pfx_buf
, new_buf
, exist_buf
);
813 if (exist_sort
== BGP_PEER_CONFED
814 && new_sort
== BGP_PEER_IBGP
) {
817 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
818 pfx_buf
, new_buf
, exist_buf
);
823 /* 11. Maximum path check. */
824 if (newm
== existm
) {
825 /* If one path has a label but the other does not, do not treat
826 * them as equals for multipath
828 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
830 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
833 "%s: %s and %s cannot be multipath, one has a label while the other does not",
834 pfx_buf
, new_buf
, exist_buf
);
835 } else if (bgp_flag_check(bgp
,
836 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
839 * For the two paths, all comparison steps till IGP
841 * have succeeded - including AS_PATH hop count. Since
843 * bestpath as-path multipath-relax' knob is on, we
845 * an exact match of AS_PATH. Thus, mark the paths are
847 * That will trigger both these paths to get into the
855 "%s: %s and %s are equal via multipath-relax",
856 pfx_buf
, new_buf
, exist_buf
);
857 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
858 if (aspath_cmp(new->attr
->aspath
,
859 exist
->attr
->aspath
)) {
864 "%s: %s and %s are equal via matching aspaths",
865 pfx_buf
, new_buf
, exist_buf
);
867 } else if (new->peer
->as
== exist
->peer
->as
) {
872 "%s: %s and %s are equal via same remote-as",
873 pfx_buf
, new_buf
, exist_buf
);
877 * TODO: If unequal cost ibgp multipath is enabled we can
878 * mark the paths as equal here instead of returning
883 "%s: %s wins over %s after IGP metric comparison",
884 pfx_buf
, new_buf
, exist_buf
);
887 "%s: %s loses to %s after IGP metric comparison",
888 pfx_buf
, new_buf
, exist_buf
);
893 /* 12. If both paths are external, prefer the path that was received
894 first (the oldest one). This step minimizes route-flap, since a
895 newer path won't displace an older one, even if it was the
896 preferred route based on the additional decision criteria below. */
897 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
898 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
899 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
902 "%s: %s wins over %s due to oldest external",
903 pfx_buf
, new_buf
, exist_buf
);
907 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
910 "%s: %s loses to %s due to oldest external",
911 pfx_buf
, new_buf
, exist_buf
);
916 /* 13. Router-ID comparision. */
917 /* If one of the paths is "stale", the corresponding peer router-id will
918 * be 0 and would always win over the other path. If originator id is
919 * used for the comparision, it will decide which path is better.
921 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
922 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
924 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
925 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
926 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
928 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
930 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
933 "%s: %s wins over %s due to Router-ID comparison",
934 pfx_buf
, new_buf
, exist_buf
);
938 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
941 "%s: %s loses to %s due to Router-ID comparison",
942 pfx_buf
, new_buf
, exist_buf
);
946 /* 14. Cluster length comparision. */
947 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
948 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
950 if (new_cluster
< exist_cluster
) {
953 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
954 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
959 if (new_cluster
> exist_cluster
) {
962 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
963 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
968 /* 15. Neighbor address comparision. */
969 /* Do this only if neither path is "stale" as stale paths do not have
970 * valid peer information (as the connection may or may not be up).
972 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
975 "%s: %s wins over %s due to latter path being STALE",
976 pfx_buf
, new_buf
, exist_buf
);
980 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
983 "%s: %s loses to %s due to former path being STALE",
984 pfx_buf
, new_buf
, exist_buf
);
988 /* locally configured routes to advertise do not have su_remote */
989 if (new->peer
->su_remote
== NULL
)
991 if (exist
->peer
->su_remote
== NULL
)
994 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
999 "%s: %s loses to %s due to Neighor IP comparison",
1000 pfx_buf
, new_buf
, exist_buf
);
1007 "%s: %s wins over %s due to Neighor IP comparison",
1008 pfx_buf
, new_buf
, exist_buf
);
1013 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1014 pfx_buf
, new_buf
, exist_buf
);
1019 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1020 * is preferred, or 0 if they are the same (usually will only occur if
1021 * multipath is enabled
1022 * This version is compatible with */
1023 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
1024 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
1029 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
1043 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1044 struct attr
*attr
, afi_t afi
,
1047 struct bgp_filter
*filter
;
1049 filter
= &peer
->filter
[afi
][safi
];
1051 #define FILTER_EXIST_WARN(F, f, filter) \
1052 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1053 zlog_debug("%s: Could not find configured input %s-list %s!", \
1054 peer->host, #f, F##_IN_NAME(filter));
1056 if (DISTRIBUTE_IN_NAME(filter
)) {
1057 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1059 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1063 if (PREFIX_LIST_IN_NAME(filter
)) {
1064 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1066 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1070 if (FILTER_LIST_IN_NAME(filter
)) {
1071 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1073 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1078 return FILTER_PERMIT
;
1079 #undef FILTER_EXIST_WARN
1082 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1083 struct attr
*attr
, afi_t afi
,
1086 struct bgp_filter
*filter
;
1088 filter
= &peer
->filter
[afi
][safi
];
1090 #define FILTER_EXIST_WARN(F, f, filter) \
1091 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1092 zlog_debug("%s: Could not find configured output %s-list %s!", \
1093 peer->host, #f, F##_OUT_NAME(filter));
1095 if (DISTRIBUTE_OUT_NAME(filter
)) {
1096 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1098 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1102 if (PREFIX_LIST_OUT_NAME(filter
)) {
1103 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1105 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1110 if (FILTER_LIST_OUT_NAME(filter
)) {
1111 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1113 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1118 return FILTER_PERMIT
;
1119 #undef FILTER_EXIST_WARN
1122 /* If community attribute includes no_export then return 1. */
1123 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1125 if (attr
->community
) {
1126 /* NO_ADVERTISE check. */
1127 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1130 /* NO_EXPORT check. */
1131 if (peer
->sort
== BGP_PEER_EBGP
1132 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1135 /* NO_EXPORT_SUBCONFED check. */
1136 if (peer
->sort
== BGP_PEER_EBGP
1137 || peer
->sort
== BGP_PEER_CONFED
)
1138 if (community_include(attr
->community
,
1139 COMMUNITY_NO_EXPORT_SUBCONFED
))
1145 /* Route reflection loop check. */
1146 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1148 struct in_addr cluster_id
;
1150 if (attr
->cluster
) {
1151 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1152 cluster_id
= peer
->bgp
->cluster_id
;
1154 cluster_id
= peer
->bgp
->router_id
;
1156 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1162 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1163 struct attr
*attr
, afi_t afi
, safi_t safi
,
1164 const char *rmap_name
)
1166 struct bgp_filter
*filter
;
1167 struct bgp_info info
;
1168 route_map_result_t ret
;
1169 struct route_map
*rmap
= NULL
;
1171 filter
= &peer
->filter
[afi
][safi
];
1173 /* Apply default weight value. */
1174 if (peer
->weight
[afi
][safi
])
1175 attr
->weight
= peer
->weight
[afi
][safi
];
1178 rmap
= route_map_lookup_by_name(rmap_name
);
1183 if (ROUTE_MAP_IN_NAME(filter
)) {
1184 rmap
= ROUTE_MAP_IN(filter
);
1191 /* Route map apply. */
1193 memset(&info
, 0, sizeof(struct bgp_info
));
1194 /* Duplicate current value to new strucutre for modification. */
1198 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1200 /* Apply BGP route map to the attribute. */
1201 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1203 peer
->rmap_type
= 0;
1205 if (ret
== RMAP_DENYMATCH
)
1211 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1212 struct attr
*attr
, afi_t afi
, safi_t safi
,
1213 const char *rmap_name
)
1215 struct bgp_info info
;
1216 route_map_result_t ret
;
1217 struct route_map
*rmap
= NULL
;
1221 * So if we get to this point and have no rmap_name
1222 * we want to just show the output as it currently
1228 /* Apply default weight value. */
1229 if (peer
->weight
[afi
][safi
])
1230 attr
->weight
= peer
->weight
[afi
][safi
];
1232 rmap
= route_map_lookup_by_name(rmap_name
);
1235 * If we have a route map name and we do not find
1236 * the routemap that means we have an implicit
1242 memset(&info
, 0, sizeof(struct bgp_info
));
1243 /* Route map apply. */
1244 /* Duplicate current value to new strucutre for modification. */
1248 rmap_type
= peer
->rmap_type
;
1249 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1251 /* Apply BGP route map to the attribute. */
1252 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1254 peer
->rmap_type
= rmap_type
;
1256 if (ret
== RMAP_DENYMATCH
)
1258 * caller has multiple error paths with bgp_attr_flush()
1265 /* If this is an EBGP peer with remove-private-AS */
1266 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1267 struct peer
*peer
, struct attr
*attr
)
1269 if (peer
->sort
== BGP_PEER_EBGP
1270 && (peer_af_flag_check(peer
, afi
, safi
,
1271 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1272 || peer_af_flag_check(peer
, afi
, safi
,
1273 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1274 || peer_af_flag_check(peer
, afi
, safi
,
1275 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1276 || peer_af_flag_check(peer
, afi
, safi
,
1277 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1278 // Take action on the entire aspath
1279 if (peer_af_flag_check(peer
, afi
, safi
,
1280 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1281 || peer_af_flag_check(peer
, afi
, safi
,
1282 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1283 if (peer_af_flag_check(
1285 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1286 attr
->aspath
= aspath_replace_private_asns(
1287 attr
->aspath
, bgp
->as
);
1289 // The entire aspath consists of private ASNs so create
1291 else if (aspath_private_as_check(attr
->aspath
))
1292 attr
->aspath
= aspath_empty_get();
1294 // There are some public and some private ASNs, remove
1297 attr
->aspath
= aspath_remove_private_asns(
1301 // 'all' was not specified so the entire aspath must be private
1303 // for us to do anything
1304 else if (aspath_private_as_check(attr
->aspath
)) {
1305 if (peer_af_flag_check(
1307 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1308 attr
->aspath
= aspath_replace_private_asns(
1309 attr
->aspath
, bgp
->as
);
1311 attr
->aspath
= aspath_empty_get();
1316 /* If this is an EBGP peer with as-override */
1317 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1318 struct peer
*peer
, struct attr
*attr
)
1320 if (peer
->sort
== BGP_PEER_EBGP
1321 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1322 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1323 attr
->aspath
= aspath_replace_specific_asn(
1324 attr
->aspath
, peer
->as
, bgp
->as
);
1328 void bgp_attr_add_gshut_community(struct attr
*attr
)
1330 struct community
*old
;
1331 struct community
*new;
1332 struct community
*merge
;
1333 struct community
*gshut
;
1335 old
= attr
->community
;
1336 gshut
= community_str2com("graceful-shutdown");
1341 merge
= community_merge(community_dup(old
), gshut
);
1343 if (old
->refcnt
== 0)
1344 community_free(old
);
1346 new = community_uniq_sort(merge
);
1347 community_free(merge
);
1349 new = community_dup(gshut
);
1352 community_free(gshut
);
1353 attr
->community
= new;
1354 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1356 /* When we add the graceful-shutdown community we must also
1357 * lower the local-preference */
1358 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1359 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1363 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1365 if (family
== AF_INET
) {
1366 attr
->nexthop
.s_addr
= 0;
1367 attr
->mp_nexthop_global_in
.s_addr
= 0;
1369 if (family
== AF_INET6
)
1370 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1371 if (family
== AF_EVPN
)
1372 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1375 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1376 struct update_subgroup
*subgrp
, struct prefix
*p
,
1379 struct bgp_filter
*filter
;
1382 struct peer
*onlypeer
;
1384 struct attr
*riattr
;
1385 char buf
[PREFIX_STRLEN
];
1391 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1393 if (DISABLE_BGP_ANNOUNCE
)
1396 afi
= SUBGRP_AFI(subgrp
);
1397 safi
= SUBGRP_SAFI(subgrp
);
1398 peer
= SUBGRP_PEER(subgrp
);
1400 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1401 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1404 filter
= &peer
->filter
[afi
][safi
];
1405 bgp
= SUBGRP_INST(subgrp
);
1406 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1409 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1410 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1411 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1414 * direct and direct_ext type routes originate internally even
1415 * though they can have peer pointers that reference other
1418 prefix2str(p
, buf
, PREFIX_STRLEN
);
1419 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1425 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1426 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1427 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1428 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1430 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1435 /* With addpath we may be asked to TX all kinds of paths so make sure
1437 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1438 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1439 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1443 /* If this is not the bestpath then check to see if there is an enabled
1445 * feature that requires us to advertise it */
1446 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1447 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1452 /* Aggregate-address suppress check. */
1453 if (ri
->extra
&& ri
->extra
->suppress
)
1454 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1459 * If we are doing VRF 2 VRF leaking via the import
1460 * statement, we want to prevent the route going
1461 * off box as that the RT and RD created are localy
1462 * significant and globaly useless.
1464 if (safi
== SAFI_MPLS_VPN
&& ri
->extra
&& ri
->extra
->num_labels
1465 && ri
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1468 /* If it's labeled safi, make sure the route has a valid label. */
1469 if (safi
== SAFI_LABELED_UNICAST
) {
1470 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1471 if (!bgp_is_valid_label(&label
)) {
1472 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1473 zlog_debug("u%" PRIu64
":s%" PRIu64
1474 " %s/%d is filtered - no label (%p)",
1475 subgrp
->update_group
->id
, subgrp
->id
,
1476 inet_ntop(p
->family
, &p
->u
.prefix
,
1477 buf
, SU_ADDRSTRLEN
),
1478 p
->prefixlen
, &label
);
1483 /* Do not send back route to sender. */
1484 if (onlypeer
&& from
== onlypeer
) {
1488 /* Do not send the default route in the BGP table if the neighbor is
1489 * configured for default-originate */
1490 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1491 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1492 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1494 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1498 /* Transparency check. */
1499 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1500 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1505 /* If community is not disabled check the no-export and local. */
1506 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1507 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1509 "subgrpannouncecheck: community filter check fail");
1513 /* If the attribute has originator-id and it is same as remote
1515 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1516 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1517 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1519 "%s [Update:SEND] %s originator-id is same as "
1522 prefix2str(p
, buf
, sizeof(buf
)));
1526 /* ORF prefix-list filter check */
1527 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1528 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1529 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1530 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1531 if (peer
->orf_plist
[afi
][safi
]) {
1532 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1534 if (bgp_debug_update(NULL
, p
,
1535 subgrp
->update_group
, 0))
1537 "%s [Update:SEND] %s is filtered via ORF",
1545 /* Output filter check. */
1546 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1547 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1548 zlog_debug("%s [Update:SEND] %s is filtered",
1549 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1553 #ifdef BGP_SEND_ASPATH_CHECK
1554 /* AS path loop check. */
1555 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1556 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1558 "%s [Update:SEND] suppress announcement to peer AS %u "
1559 "that is part of AS path.",
1560 onlypeer
->host
, onlypeer
->as
);
1563 #endif /* BGP_SEND_ASPATH_CHECK */
1565 /* If we're a CONFED we need to loop check the CONFED ID too */
1566 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1567 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1568 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1570 "%s [Update:SEND] suppress announcement to peer AS %u"
1572 peer
->host
, bgp
->confed_id
);
1577 /* Route-Reflect check. */
1578 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1583 /* IBGP reflection check. */
1584 if (reflect
&& !samepeer_safe
) {
1585 /* A route from a Client peer. */
1586 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1587 PEER_FLAG_REFLECTOR_CLIENT
)) {
1588 /* Reflect to all the Non-Client peers and also to the
1589 Client peers other than the originator. Originator
1591 is already done. So there is noting to do. */
1592 /* no bgp client-to-client reflection check. */
1593 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1594 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1595 PEER_FLAG_REFLECTOR_CLIENT
))
1598 /* A route from a Non-client peer. Reflect to all other
1600 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1601 PEER_FLAG_REFLECTOR_CLIENT
))
1606 /* For modify attribute, copy it to temporary structure. */
1607 bgp_attr_dup(attr
, riattr
);
1609 /* If local-preference is not set. */
1610 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1611 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1612 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1613 attr
->local_pref
= bgp
->default_local_pref
;
1616 /* If originator-id is not set and the route is to be reflected,
1617 set the originator id */
1619 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1620 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1621 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1624 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1626 if (peer
->sort
== BGP_PEER_EBGP
1627 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1628 if (from
!= bgp
->peer_self
&& !transparent
1629 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1630 PEER_FLAG_MED_UNCHANGED
))
1632 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1635 /* Since the nexthop attribute can vary per peer, it is not explicitly
1637 * in announce check, only certain flags and length (or number of
1639 * -- for IPv6/MP_REACH) are set here in order to guide the update
1641 * code in setting the nexthop(s) on a per peer basis in
1643 * Typically, the source nexthop in the attribute is preserved but in
1645 * scenarios where we know it will always be overwritten, we reset the
1646 * nexthop to "0" in an attempt to achieve better Update packing. An
1647 * example of this is when a prefix from each of 2 IBGP peers needs to
1649 * announced to an EBGP peer (and they have the same attributes barring
1653 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1655 #define NEXTHOP_IS_V6 \
1656 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1657 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1658 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1659 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1661 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1663 * the peer (group) is configured to receive link-local nexthop
1665 * and it is available in the prefix OR we're not reflecting the route
1667 * the peer (group) to whom we're going to announce is on a shared
1669 * and this is either a self-originated route or the peer is EBGP.
1671 if (NEXTHOP_IS_V6
) {
1672 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1673 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1674 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1675 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1676 || (!reflect
&& peer
->shared_network
1677 && (from
== bgp
->peer_self
1678 || peer
->sort
== BGP_PEER_EBGP
))) {
1679 attr
->mp_nexthop_len
=
1680 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1683 /* Clear off link-local nexthop in source, whenever it is not
1685 * ensure more prefixes share the same attribute for
1688 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1689 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1690 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1693 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1694 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1696 /* Route map & unsuppress-map apply. */
1697 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1698 struct bgp_info info
;
1699 struct bgp_info_extra dummy_info_extra
;
1700 struct attr dummy_attr
;
1702 memset(&info
, 0, sizeof(struct bgp_info
));
1707 memcpy(&dummy_info_extra
, ri
->extra
,
1708 sizeof(struct bgp_info_extra
));
1709 info
.extra
= &dummy_info_extra
;
1712 /* don't confuse inbound and outbound setting */
1713 RESET_FLAG(attr
->rmap_change_flags
);
1716 * The route reflector is not allowed to modify the attributes
1717 * of the reflected IBGP routes unless explicitly allowed.
1719 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1720 && !bgp_flag_check(bgp
,
1721 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1722 bgp_attr_dup(&dummy_attr
, attr
);
1723 info
.attr
= &dummy_attr
;
1726 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1728 if (ri
->extra
&& ri
->extra
->suppress
)
1729 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1732 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1735 peer
->rmap_type
= 0;
1737 if (ret
== RMAP_DENYMATCH
) {
1738 bgp_attr_flush(attr
);
1743 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1744 if (peer
->sort
== BGP_PEER_IBGP
1745 || peer
->sort
== BGP_PEER_CONFED
) {
1746 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1747 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1749 bgp_attr_add_gshut_community(attr
);
1753 /* After route-map has been applied, we check to see if the nexthop to
1754 * be carried in the attribute (that is used for the announcement) can
1755 * be cleared off or not. We do this in all cases where we would be
1756 * setting the nexthop to "ourselves". For IPv6, we only need to
1758 * the global nexthop here; the link-local nexthop would have been
1760 * already, and if not, it is required by the update formation code.
1761 * Also see earlier comments in this function.
1764 * If route-map has performed some operation on the nexthop or the peer
1765 * configuration says to pass it unchanged, we cannot reset the nexthop
1766 * here, so only attempt to do it if these aren't true. Note that the
1767 * route-map handler itself might have cleared the nexthop, if for
1769 * it is configured as 'peer-address'.
1771 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1772 riattr
->rmap_change_flags
)
1774 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1775 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1776 /* We can reset the nexthop, if setting (or forcing) it to
1778 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1779 PEER_FLAG_NEXTHOP_SELF
)
1780 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1781 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1783 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1784 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1785 subgroup_announce_reset_nhop(
1786 (peer_cap_enhe(peer
, afi
, safi
)
1790 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1791 /* Can also reset the nexthop if announcing to EBGP, but
1793 * no peer in the subgroup is on a shared subnet.
1794 * Note: 3rd party nexthop currently implemented for
1797 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1799 subgroup_announce_reset_nhop(
1800 (peer_cap_enhe(peer
, afi
, safi
)
1804 } else if (CHECK_FLAG(ri
->flags
, BGP_INFO_ANNC_NH_SELF
)) {
1806 * This flag is used for leaked vpn-vrf routes
1808 int family
= p
->family
;
1810 if (peer_cap_enhe(peer
, afi
, safi
))
1813 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1815 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1816 __func__
, family2str(family
));
1817 subgroup_announce_reset_nhop(family
, attr
);
1820 /* If IPv6/MP and nexthop does not have any override and happens
1822 * be a link-local address, reset it so that we don't pass along
1824 * source's link-local IPv6 address to recipients who may not be
1826 * the same interface.
1828 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1829 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1830 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1837 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1838 struct bgp_maxpaths_cfg
*mpath_cfg
,
1839 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1841 struct bgp_info
*new_select
;
1842 struct bgp_info
*old_select
;
1843 struct bgp_info
*ri
;
1844 struct bgp_info
*ri1
;
1845 struct bgp_info
*ri2
;
1846 struct bgp_info
*nextri
= NULL
;
1847 int paths_eq
, do_mpath
, debug
;
1848 struct list mp_list
;
1849 char pfx_buf
[PREFIX2STR_BUFFER
];
1850 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1852 bgp_mp_list_init(&mp_list
);
1854 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1856 debug
= bgp_debug_bestpath(&rn
->p
);
1859 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1861 /* bgp deterministic-med */
1863 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1865 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1866 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1867 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1869 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1870 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1872 if (BGP_INFO_HOLDDOWN(ri1
))
1874 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1875 if (ri1
->peer
->status
!= Established
)
1880 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1881 if (CHECK_FLAG(ri2
->flags
,
1882 BGP_INFO_DMED_CHECK
))
1884 if (BGP_INFO_HOLDDOWN(ri2
))
1887 && ri2
->peer
!= bgp
->peer_self
1890 PEER_STATUS_NSF_WAIT
))
1891 if (ri2
->peer
->status
1895 if (aspath_cmp_left(ri1
->attr
->aspath
,
1897 || aspath_cmp_left_confed(
1899 ri2
->attr
->aspath
)) {
1900 if (bgp_info_cmp(bgp
, ri2
,
1906 bgp_info_unset_flag(
1908 BGP_INFO_DMED_SELECTED
);
1914 BGP_INFO_DMED_CHECK
);
1918 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1919 bgp_info_set_flag(rn
, new_select
,
1920 BGP_INFO_DMED_SELECTED
);
1923 bgp_info_path_with_addpath_rx_str(new_select
,
1925 zlog_debug("%s: %s is the bestpath from AS %u",
1927 aspath_get_first_as(
1928 new_select
->attr
->aspath
));
1933 /* Check old selected route and new selected route. */
1936 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1938 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1941 if (BGP_INFO_HOLDDOWN(ri
)) {
1942 /* reap REMOVED routes, if needs be
1943 * selected route must stay for a while longer though
1945 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1946 && (ri
!= old_select
))
1947 bgp_info_reap(rn
, ri
);
1950 zlog_debug("%s: ri %p in holddown", __func__
,
1956 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1957 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1958 if (ri
->peer
->status
!= Established
) {
1962 "%s: ri %p non self peer %s not estab state",
1963 __func__
, ri
, ri
->peer
->host
);
1968 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1969 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1970 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1972 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1976 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1978 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1979 debug
, pfx_buf
, afi
, safi
)) {
1984 /* Now that we know which path is the bestpath see if any of the other
1986 * qualify as multipaths
1990 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1992 sprintf(path_buf
, "NONE");
1994 "%s: After path selection, newbest is %s oldbest was %s",
1996 old_select
? old_select
->peer
->host
: "NONE");
1999 if (do_mpath
&& new_select
) {
2000 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
2004 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
2006 if (ri
== new_select
) {
2009 "%s: %s is the bestpath, add to the multipath list",
2011 bgp_mp_list_add(&mp_list
, ri
);
2015 if (BGP_INFO_HOLDDOWN(ri
))
2018 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
2019 && !CHECK_FLAG(ri
->peer
->sflags
,
2020 PEER_STATUS_NSF_WAIT
))
2021 if (ri
->peer
->status
!= Established
)
2024 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
2027 "%s: %s has the same nexthop as the bestpath, skip it",
2032 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
2033 debug
, pfx_buf
, afi
, safi
);
2038 "%s: %s is equivalent to the bestpath, add to the multipath list",
2040 bgp_mp_list_add(&mp_list
, ri
);
2045 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
2046 bgp_info_mpath_aggregate_update(new_select
, old_select
);
2047 bgp_mp_list_clear(&mp_list
);
2049 result
->old
= old_select
;
2050 result
->new = new_select
;
2056 * A new route/change in bestpath of an existing route. Evaluate the path
2057 * for advertisement to the subgroup.
2059 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2060 struct bgp_info
*selected
,
2061 struct bgp_node
*rn
,
2062 uint32_t addpath_tx_id
)
2065 struct peer
*onlypeer
;
2071 afi
= SUBGRP_AFI(subgrp
);
2072 safi
= SUBGRP_SAFI(subgrp
);
2073 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2076 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2077 char buf_prefix
[PREFIX_STRLEN
];
2078 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2079 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2083 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2084 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2085 PEER_STATUS_ORF_WAIT_REFRESH
))
2088 memset(&attr
, 0, sizeof(struct attr
));
2089 /* It's initialized in bgp_announce_check() */
2091 /* Announcement to the subgroup. If the route is filtered withdraw it.
2094 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2095 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2097 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2098 selected
->addpath_tx_id
);
2101 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2103 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2110 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2111 * This is called at the end of route processing.
2113 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2115 struct bgp_info
*ri
;
2117 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2118 if (BGP_INFO_HOLDDOWN(ri
))
2120 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2121 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2126 * Has the route changed from the RIB's perspective? This is invoked only
2127 * if the route selection returns the same best route as earlier - to
2128 * determine if we need to update zebra or not.
2130 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2132 struct bgp_info
*mpinfo
;
2134 /* If this is multipath, check all selected paths for any nexthop
2135 * change or attribute change. Some attribute changes (e.g., community)
2136 * aren't of relevance to the RIB, but we'll update zebra to ensure
2137 * we handle the case of BGP nexthop change. This is the behavior
2138 * when the best path has an attribute change anyway.
2140 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2141 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2145 * If this is multipath, check all selected paths for any nexthop change
2147 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2148 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2149 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2150 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2154 /* Nothing has changed from the RIB's perspective. */
2158 struct bgp_process_queue
{
2160 STAILQ_HEAD(, bgp_node
) pqueue
;
2161 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2163 unsigned int queued
;
2167 * old_select = The old best path
2168 * new_select = the new best path
2170 * if (!old_select && new_select)
2171 * We are sending new information on.
2173 * if (old_select && new_select) {
2174 * if (new_select != old_select)
2175 * We have a new best path send a change
2177 * We've received a update with new attributes that needs
2181 * if (old_select && !new_select)
2182 * We have no eligible route that we can announce or the rn
2185 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2186 afi_t afi
, safi_t safi
)
2188 struct bgp_info
*new_select
;
2189 struct bgp_info
*old_select
;
2190 struct bgp_info_pair old_and_new
;
2191 char pfx_buf
[PREFIX2STR_BUFFER
];
2194 /* Is it end of initial update? (after startup) */
2196 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2197 sizeof(bgp
->update_delay_zebra_resume_time
));
2199 bgp
->main_zebra_update_hold
= 0;
2200 FOREACH_AFI_SAFI (afi
, safi
) {
2201 if (bgp_fibupd_safi(safi
))
2202 bgp_zebra_announce_table(bgp
, afi
, safi
);
2204 bgp
->main_peers_update_hold
= 0;
2206 bgp_start_routeadv(bgp
);
2210 struct prefix
*p
= &rn
->p
;
2212 debug
= bgp_debug_bestpath(&rn
->p
);
2214 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2215 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2216 afi2str(afi
), safi2str(safi
));
2219 /* Best path selection. */
2220 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2222 old_select
= old_and_new
.old
;
2223 new_select
= old_and_new
.new;
2225 /* Do we need to allocate or free labels?
2226 * Right now, since we only deal with per-prefix labels, it is not
2227 * necessary to do this upon changes to best path except if the label
2230 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2233 || bgp_label_index_differs(new_select
, old_select
)
2234 || new_select
->sub_type
!= old_select
->sub_type
) {
2235 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2236 && new_select
->attr
->flag
2238 BGP_ATTR_PREFIX_SID
)
2239 && new_select
->attr
->label_index
2240 != BGP_INVALID_LABEL_INDEX
) {
2243 BGP_NODE_REGISTERED_FOR_LABEL
))
2244 bgp_unregister_for_label(rn
);
2245 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2247 bgp_set_valid_label(&rn
->local_label
);
2249 bgp_register_for_label(rn
, new_select
);
2251 } else if (CHECK_FLAG(rn
->flags
,
2252 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2253 bgp_unregister_for_label(rn
);
2255 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2256 bgp_unregister_for_label(rn
);
2260 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2262 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2263 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2264 old_select
, new_select
);
2267 /* If best route remains the same and this is not due to user-initiated
2268 * clear, see exactly what needs to be done.
2270 if (old_select
&& old_select
== new_select
2271 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2272 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2273 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2274 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2276 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2277 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2279 if (bgp_fibupd_safi(safi
)
2280 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2282 if (new_select
->type
== ZEBRA_ROUTE_BGP
2283 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2284 || new_select
->sub_type
2285 == BGP_ROUTE_IMPORTED
))
2287 bgp_zebra_announce(rn
, p
, old_select
,
2291 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2292 bgp_zebra_clear_route_change_flags(rn
);
2294 /* If there is a change of interest to peers, reannounce the
2296 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2297 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2298 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2300 /* unicast routes must also be annouced to
2301 * labeled-unicast update-groups */
2302 if (safi
== SAFI_UNICAST
)
2303 group_announce_route(bgp
, afi
,
2304 SAFI_LABELED_UNICAST
, rn
,
2307 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2308 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2311 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2315 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2317 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2319 /* bestpath has changed; bump version */
2320 if (old_select
|| new_select
) {
2321 bgp_bump_version(rn
);
2323 if (!bgp
->t_rmap_def_originate_eval
) {
2327 update_group_refresh_default_originate_route_map
,
2328 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2329 &bgp
->t_rmap_def_originate_eval
);
2334 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2337 zlog_debug("%s: setting SELECTED flag", __func__
);
2338 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2339 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2340 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2344 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2345 if (old_select
!= new_select
) {
2347 vnc_import_bgp_exterior_del_route(bgp
, p
,
2349 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2352 vnc_import_bgp_exterior_add_route(bgp
, p
,
2354 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2360 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2362 /* unicast routes must also be annouced to labeled-unicast update-groups
2364 if (safi
== SAFI_UNICAST
)
2365 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2369 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2370 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2371 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2372 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2373 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2374 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2376 /* if this is an evpn imported type-5 prefix,
2377 * we need to withdraw the route first to clear
2378 * the nh neigh and the RMAC entry.
2381 is_route_parent_evpn(old_select
))
2382 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2384 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2386 /* Withdraw the route from the kernel. */
2387 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2388 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2389 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2390 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2392 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2396 /* advertise/withdraw type-5 routes */
2397 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2398 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2399 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2401 /* apply the route-map */
2402 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2405 ret
= route_map_apply(
2406 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2407 &rn
->p
, RMAP_BGP
, new_select
);
2408 if (ret
== RMAP_MATCH
)
2409 bgp_evpn_advertise_type5_route(
2410 bgp
, &rn
->p
, new_select
->attr
,
2413 bgp_evpn_advertise_type5_route(bgp
,
2419 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2420 (!old_select
->extra
|| !old_select
->extra
->parent
))
2421 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2424 /* Clear any route change flags. */
2425 bgp_zebra_clear_route_change_flags(rn
);
2427 /* Reap old select bgp_info, if it has been removed */
2428 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2429 bgp_info_reap(rn
, old_select
);
2431 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2435 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2437 struct bgp_process_queue
*pqnode
= data
;
2438 struct bgp
*bgp
= pqnode
->bgp
;
2439 struct bgp_table
*table
;
2440 struct bgp_node
*rn
;
2443 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2444 bgp_process_main_one(bgp
, NULL
, 0, 0);
2445 /* should always have dedicated wq call */
2446 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2450 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2451 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2452 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2453 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2454 table
= bgp_node_table(rn
);
2455 /* note, new RNs may be added as part of processing */
2456 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2458 bgp_unlock_node(rn
);
2459 bgp_table_unlock(table
);
2465 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2467 struct bgp_process_queue
*pqnode
= data
;
2469 bgp_unlock(pqnode
->bgp
);
2471 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2474 void bgp_process_queue_init(void)
2476 if (!bm
->process_main_queue
)
2477 bm
->process_main_queue
=
2478 work_queue_new(bm
->master
, "process_main_queue");
2480 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2481 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2482 bm
->process_main_queue
->spec
.max_retries
= 0;
2483 bm
->process_main_queue
->spec
.hold
= 50;
2484 /* Use a higher yield value of 50ms for main queue processing */
2485 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2488 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2490 struct bgp_process_queue
*pqnode
;
2492 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2493 sizeof(struct bgp_process_queue
));
2495 /* unlocked in bgp_processq_del */
2496 pqnode
->bgp
= bgp_lock(bgp
);
2497 STAILQ_INIT(&pqnode
->pqueue
);
2502 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2504 #define ARBITRARY_PROCESS_QLEN 10000
2505 struct work_queue
*wq
= bm
->process_main_queue
;
2506 struct bgp_process_queue
*pqnode
;
2507 int pqnode_reuse
= 0;
2509 /* already scheduled for processing? */
2510 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2516 /* Add route nodes to an existing work queue item until reaching the
2517 limit only if is from the same BGP view and it's not an EOIU marker
2519 if (work_queue_item_count(wq
)) {
2520 struct work_queue_item
*item
= work_queue_last_item(wq
);
2521 pqnode
= item
->data
;
2523 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2524 || pqnode
->bgp
!= bgp
2525 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2526 pqnode
= bgp_processq_alloc(bgp
);
2530 pqnode
= bgp_processq_alloc(bgp
);
2531 /* all unlocked in bgp_process_wq */
2532 bgp_table_lock(bgp_node_table(rn
));
2534 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2537 /* can't be enqueued twice */
2538 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2539 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2543 work_queue_add(wq
, pqnode
);
2548 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2550 struct bgp_process_queue
*pqnode
;
2552 if (bm
->process_main_queue
== NULL
)
2555 pqnode
= bgp_processq_alloc(bgp
);
2557 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2558 work_queue_add(bm
->process_main_queue
, pqnode
);
2561 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2565 peer
= THREAD_ARG(thread
);
2566 peer
->t_pmax_restart
= NULL
;
2568 if (bgp_debug_neighbor_events(peer
))
2570 "%s Maximum-prefix restart timer expired, restore peering",
2573 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2574 zlog_debug("%s: %s peer_clear failed",
2575 __PRETTY_FUNCTION__
, peer
->host
);
2580 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2584 iana_safi_t pkt_safi
;
2586 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2589 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2590 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2591 PEER_STATUS_PREFIX_LIMIT
)
2596 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2598 afi_safi_print(afi
, safi
), peer
->host
,
2599 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2600 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2602 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2603 PEER_FLAG_MAX_PREFIX_WARNING
))
2606 /* Convert AFI, SAFI to values for packet. */
2607 pkt_afi
= afi_int2iana(afi
);
2608 pkt_safi
= safi_int2iana(safi
);
2612 ndata
[0] = (pkt_afi
>> 8);
2614 ndata
[2] = pkt_safi
;
2615 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2616 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2617 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2618 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2620 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2621 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2622 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2626 /* Dynamic peers will just close their connection. */
2627 if (peer_dynamic_neighbor(peer
))
2630 /* restart timer start */
2631 if (peer
->pmax_restart
[afi
][safi
]) {
2632 peer
->v_pmax_restart
=
2633 peer
->pmax_restart
[afi
][safi
] * 60;
2635 if (bgp_debug_neighbor_events(peer
))
2637 "%s Maximum-prefix restart timer started for %d secs",
2638 peer
->host
, peer
->v_pmax_restart
);
2640 BGP_TIMER_ON(peer
->t_pmax_restart
,
2641 bgp_maximum_prefix_restart_timer
,
2642 peer
->v_pmax_restart
);
2647 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2648 PEER_STATUS_PREFIX_LIMIT
);
2650 if (peer
->pcount
[afi
][safi
]
2651 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2652 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2653 PEER_STATUS_PREFIX_THRESHOLD
)
2658 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2659 afi_safi_print(afi
, safi
), peer
->host
,
2660 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2661 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2662 PEER_STATUS_PREFIX_THRESHOLD
);
2664 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2665 PEER_STATUS_PREFIX_THRESHOLD
);
2669 /* Unconditionally remove the route from the RIB, without taking
2670 * damping into consideration (eg, because the session went down)
2672 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2673 afi_t afi
, safi_t safi
)
2675 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2677 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2678 bgp_info_delete(rn
, ri
); /* keep historical info */
2680 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2683 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2684 struct peer
*peer
, afi_t afi
, safi_t safi
,
2685 struct prefix_rd
*prd
)
2687 /* apply dampening, if result is suppressed, we'll be retaining
2688 * the bgp_info in the RIB for historical reference.
2690 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2691 && peer
->sort
== BGP_PEER_EBGP
)
2692 if ((bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2693 == BGP_DAMP_SUPPRESSED
) {
2694 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2700 if (safi
== SAFI_MPLS_VPN
) {
2701 struct bgp_node
*prn
= NULL
;
2702 struct bgp_table
*table
= NULL
;
2704 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2705 (struct prefix
*)prd
);
2707 table
= (struct bgp_table
*)(prn
->info
);
2709 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2710 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2712 bgp_unlock_node(prn
);
2714 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2715 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2717 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2718 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2724 /* If this is an EVPN route, process for un-import. */
2725 if (safi
== SAFI_EVPN
)
2726 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2728 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2731 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2732 struct peer
*peer
, struct attr
*attr
,
2733 struct bgp_node
*rn
)
2735 struct bgp_info
*new;
2737 /* Make new BGP info. */
2738 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2740 new->instance
= instance
;
2741 new->sub_type
= sub_type
;
2744 new->uptime
= bgp_clock();
2746 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2750 static void overlay_index_update(struct attr
*attr
,
2751 struct eth_segment_id
*eth_s_id
,
2752 union gw_addr
*gw_ip
)
2757 if (eth_s_id
== NULL
) {
2758 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2759 sizeof(struct eth_segment_id
));
2761 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2762 sizeof(struct eth_segment_id
));
2764 if (gw_ip
== NULL
) {
2765 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2767 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2768 sizeof(union gw_addr
));
2772 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2773 struct eth_segment_id
*eth_s_id
,
2774 union gw_addr
*gw_ip
)
2776 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2777 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2779 struct eth_segment_id esi
;
2783 if (afi
!= AFI_L2VPN
)
2786 memset(&temp
, 0, sizeof(temp
));
2787 info_eth_s_id
= &temp
.esi
;
2788 info_gw_ip
= &temp
.ip
;
2790 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2793 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2794 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2797 if (gw_ip
== NULL
) {
2798 memset(&temp
, 0, sizeof(temp
));
2799 info_gw_ip_remote
= &temp
.ip
;
2801 info_gw_ip_remote
= gw_ip
;
2803 if (eth_s_id
== NULL
) {
2804 memset(&temp
, 0, sizeof(temp
));
2805 info_eth_s_id_remote
= &temp
.esi
;
2807 info_eth_s_id_remote
= eth_s_id
;
2809 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2812 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2813 sizeof(struct eth_segment_id
));
2816 /* Check if received nexthop is valid or not. */
2817 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2822 /* Only validated for unicast and multicast currently. */
2823 /* Also valid for EVPN where the nexthop is an IP address. */
2824 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2827 /* If NEXT_HOP is present, validate it. */
2828 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2829 if (attr
->nexthop
.s_addr
== 0
2830 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2831 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2835 /* If MP_NEXTHOP is present, validate it. */
2836 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2837 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2838 * it is not an IPv6 link-local address.
2840 if (attr
->mp_nexthop_len
) {
2841 switch (attr
->mp_nexthop_len
) {
2842 case BGP_ATTR_NHLEN_IPV4
:
2843 case BGP_ATTR_NHLEN_VPNV4
:
2844 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2845 || IPV4_CLASS_DE(ntohl(
2846 attr
->mp_nexthop_global_in
.s_addr
))
2847 || bgp_nexthop_self(bgp
,
2848 attr
->mp_nexthop_global_in
));
2851 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2852 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2853 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2854 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2855 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2856 || IN6_IS_ADDR_MULTICAST(
2857 &attr
->mp_nexthop_global
));
2869 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2870 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2871 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2872 uint32_t num_labels
, int soft_reconfig
,
2873 struct bgp_route_evpn
*evpn
)
2876 int aspath_loop_count
= 0;
2877 struct bgp_node
*rn
;
2879 struct attr new_attr
;
2880 struct attr
*attr_new
;
2881 struct bgp_info
*ri
;
2882 struct bgp_info
*new;
2883 struct bgp_info_extra
*extra
;
2885 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2887 int do_loop_check
= 1;
2888 int has_valid_label
= 0;
2890 int vnc_implicit_withdraw
= 0;
2894 memset(&new_attr
, 0, sizeof(struct attr
));
2895 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2896 new_attr
.label
= MPLS_INVALID_LABEL
;
2899 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2900 /* TODO: Check to see if we can get rid of "is_valid_label" */
2901 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2902 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2904 has_valid_label
= bgp_is_valid_label(label
);
2906 /* When peer's soft reconfiguration enabled. Record input packet in
2909 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2910 && peer
!= bgp
->peer_self
)
2911 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2913 /* Check previously received route. */
2914 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2915 if (ri
->peer
== peer
&& ri
->type
== type
2916 && ri
->sub_type
== sub_type
2917 && ri
->addpath_rx_id
== addpath_id
)
2920 /* AS path local-as loop check. */
2921 if (peer
->change_local_as
) {
2922 if (peer
->allowas_in
[afi
][safi
])
2923 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2924 else if (!CHECK_FLAG(peer
->flags
,
2925 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2926 aspath_loop_count
= 1;
2928 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2929 > aspath_loop_count
) {
2930 reason
= "as-path contains our own AS;";
2935 /* If the peer is configured for "allowas-in origin" and the last ASN in
2937 * as-path is our ASN then we do not need to call aspath_loop_check
2939 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2940 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2943 /* AS path loop check. */
2944 if (do_loop_check
) {
2945 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2946 > peer
->allowas_in
[afi
][safi
]
2947 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2948 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2949 > peer
->allowas_in
[afi
][safi
])) {
2950 reason
= "as-path contains our own AS;";
2955 /* Route reflector originator ID check. */
2956 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2957 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2958 reason
= "originator is us;";
2962 /* Route reflector cluster ID check. */
2963 if (bgp_cluster_filter(peer
, attr
)) {
2964 reason
= "reflected from the same cluster;";
2968 /* Apply incoming filter. */
2969 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2974 bgp_attr_dup(&new_attr
, attr
);
2976 /* Apply incoming route-map.
2977 * NB: new_attr may now contain newly allocated values from route-map
2979 * commands, so we need bgp_attr_flush in the error paths, until we
2981 * the attr (which takes over the memory references) */
2982 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2984 reason
= "route-map;";
2985 bgp_attr_flush(&new_attr
);
2989 if (peer
->sort
== BGP_PEER_EBGP
) {
2991 /* If we receive the graceful-shutdown community from an eBGP
2992 * peer we must lower local-preference */
2993 if (new_attr
.community
2994 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2995 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2996 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2998 /* If graceful-shutdown is configured then add the GSHUT
2999 * community to all paths received from eBGP peers */
3000 } else if (bgp_flag_check(peer
->bgp
,
3001 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3002 bgp_attr_add_gshut_community(&new_attr
);
3006 /* next hop check. */
3007 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3008 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3009 reason
= "martian or self next-hop;";
3010 bgp_attr_flush(&new_attr
);
3014 attr_new
= bgp_attr_intern(&new_attr
);
3016 /* If the update is implicit withdraw. */
3018 ri
->uptime
= bgp_clock();
3019 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
3021 /* Same attribute comes in. */
3022 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
3023 && attrhash_cmp(ri
->attr
, attr_new
)
3024 && (!has_valid_label
3025 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
3026 num_labels
* sizeof(mpls_label_t
))
3028 && (overlay_index_equal(
3029 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3030 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3031 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3032 BGP_CONFIG_DAMPENING
)
3033 && peer
->sort
== BGP_PEER_EBGP
3034 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3035 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3036 bgp_debug_rdpfxpath2str(
3037 afi
, safi
, prd
, p
, label
,
3038 num_labels
, addpath_id
? 1 : 0,
3039 addpath_id
, pfx_buf
,
3041 zlog_debug("%s rcvd %s", peer
->host
,
3045 if (bgp_damp_update(ri
, rn
, afi
, safi
)
3046 != BGP_DAMP_SUPPRESSED
) {
3047 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
3049 bgp_process(bgp
, rn
, afi
, safi
);
3051 } else /* Duplicate - odd */
3053 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3054 if (!peer
->rcvd_attr_printed
) {
3056 "%s rcvd UPDATE w/ attr: %s",
3058 peer
->rcvd_attr_str
);
3059 peer
->rcvd_attr_printed
= 1;
3062 bgp_debug_rdpfxpath2str(
3063 afi
, safi
, prd
, p
, label
,
3064 num_labels
, addpath_id
? 1 : 0,
3065 addpath_id
, pfx_buf
,
3068 "%s rcvd %s...duplicate ignored",
3069 peer
->host
, pfx_buf
);
3072 /* graceful restart STALE flag unset. */
3073 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3074 bgp_info_unset_flag(rn
, ri
,
3076 bgp_process(bgp
, rn
, afi
, safi
);
3080 bgp_unlock_node(rn
);
3081 bgp_attr_unintern(&attr_new
);
3086 /* Withdraw/Announce before we fully processed the withdraw */
3087 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3088 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3089 bgp_debug_rdpfxpath2str(
3090 afi
, safi
, prd
, p
, label
, num_labels
,
3091 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3094 "%s rcvd %s, flapped quicker than processing",
3095 peer
->host
, pfx_buf
);
3098 bgp_info_restore(rn
, ri
);
3101 /* Received Logging. */
3102 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3103 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3104 num_labels
, addpath_id
? 1 : 0,
3105 addpath_id
, pfx_buf
,
3107 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3110 /* graceful restart STALE flag unset. */
3111 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3112 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3114 /* The attribute is changed. */
3115 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3117 /* implicit withdraw, decrement aggregate and pcount here.
3118 * only if update is accepted, they'll increment below.
3120 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3122 /* Update bgp route dampening information. */
3123 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3124 && peer
->sort
== BGP_PEER_EBGP
) {
3125 /* This is implicit withdraw so we should update
3128 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3129 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3132 if (safi
== SAFI_MPLS_VPN
) {
3133 struct bgp_node
*prn
= NULL
;
3134 struct bgp_table
*table
= NULL
;
3136 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3137 (struct prefix
*)prd
);
3139 table
= (struct bgp_table
*)(prn
->info
);
3141 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3142 bgp
, prd
, table
, p
, ri
);
3144 bgp_unlock_node(prn
);
3146 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3147 && (safi
== SAFI_UNICAST
)) {
3148 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3150 * Implicit withdraw case.
3152 ++vnc_implicit_withdraw
;
3153 vnc_import_bgp_del_route(bgp
, p
, ri
);
3154 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3159 /* Special handling for EVPN update of an existing route. If the
3160 * extended community attribute has changed, we need to
3162 * the route using its existing extended community. It will be
3163 * subsequently processed for import with the new extended
3166 if (safi
== SAFI_EVPN
&& !same_attr
) {
3168 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3170 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3173 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3174 attr_new
->ecommunity
);
3176 if (bgp_debug_update(peer
, p
, NULL
, 1))
3178 "Change in EXT-COMM, existing %s new %s",
3180 ri
->attr
->ecommunity
),
3182 attr_new
->ecommunity
));
3183 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3189 /* Update to new attribute. */
3190 bgp_attr_unintern(&ri
->attr
);
3191 ri
->attr
= attr_new
;
3193 /* Update MPLS label */
3194 if (has_valid_label
) {
3195 extra
= bgp_info_extra_get(ri
);
3196 memcpy(&extra
->label
, label
,
3197 num_labels
* sizeof(mpls_label_t
));
3198 extra
->num_labels
= num_labels
;
3199 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3200 bgp_set_valid_label(&extra
->label
[0]);
3204 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3205 && (safi
== SAFI_UNICAST
)) {
3206 if (vnc_implicit_withdraw
) {
3208 * Add back the route with its new attributes
3210 * The route is still selected, until the route
3212 * queued by bgp_process actually runs. We have
3214 * update to the VNC side immediately to avoid
3216 * configuration changes (e.g., route-map
3218 * trigger re-importation of the entire RIB.
3220 vnc_import_bgp_add_route(bgp
, p
, ri
);
3221 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3225 /* Update Overlay Index */
3226 if (afi
== AFI_L2VPN
) {
3227 overlay_index_update(
3228 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3229 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3232 /* Update bgp route dampening information. */
3233 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3234 && peer
->sort
== BGP_PEER_EBGP
) {
3235 /* Now we do normal update dampening. */
3236 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3237 if (ret
== BGP_DAMP_SUPPRESSED
) {
3238 bgp_unlock_node(rn
);
3243 /* Nexthop reachability check - for unicast and
3244 * labeled-unicast.. */
3245 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3246 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3247 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3248 && !CHECK_FLAG(peer
->flags
,
3249 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3251 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3256 struct bgp
*bgp_nexthop
= bgp
;
3258 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3259 bgp_nexthop
= ri
->extra
->bgp_orig
;
3261 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3262 ri
, NULL
, connected
)
3263 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3264 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3266 if (BGP_DEBUG(nht
, NHT
)) {
3267 char buf1
[INET6_ADDRSTRLEN
];
3269 (const void *)&attr_new
3271 buf1
, INET6_ADDRSTRLEN
);
3272 zlog_debug("%s(%s): NH unresolved",
3273 __FUNCTION__
, buf1
);
3275 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3278 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3281 if (safi
== SAFI_MPLS_VPN
) {
3282 struct bgp_node
*prn
= NULL
;
3283 struct bgp_table
*table
= NULL
;
3285 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3286 (struct prefix
*)prd
);
3288 table
= (struct bgp_table
*)(prn
->info
);
3290 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3291 bgp
, prd
, table
, p
, ri
);
3293 bgp_unlock_node(prn
);
3297 /* If this is an EVPN route and some attribute has changed,
3299 * route for import. If the extended community has changed, we
3301 * have done the un-import earlier and the import would result
3303 * route getting injected into appropriate L2 VNIs. If it is
3305 * some other attribute change, the import will result in
3307 * the attributes for the route in the VNI(s).
3309 if (safi
== SAFI_EVPN
&& !same_attr
)
3310 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3312 /* Process change. */
3313 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3315 bgp_process(bgp
, rn
, afi
, safi
);
3316 bgp_unlock_node(rn
);
3318 if (SAFI_UNICAST
== safi
3319 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3320 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3322 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3324 if ((SAFI_MPLS_VPN
== safi
)
3325 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3327 vpn_leak_to_vrf_update(bgp
, ri
);
3331 if (SAFI_MPLS_VPN
== safi
) {
3332 mpls_label_t label_decoded
= decode_label(label
);
3334 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3335 type
, sub_type
, &label_decoded
);
3337 if (SAFI_ENCAP
== safi
) {
3338 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3339 type
, sub_type
, NULL
);
3344 } // End of implicit withdraw
3346 /* Received Logging. */
3347 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3348 if (!peer
->rcvd_attr_printed
) {
3349 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3350 peer
->rcvd_attr_str
);
3351 peer
->rcvd_attr_printed
= 1;
3354 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3355 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3357 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3360 /* Make new BGP info. */
3361 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3363 /* Update MPLS label */
3364 if (has_valid_label
) {
3365 extra
= bgp_info_extra_get(new);
3366 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3367 extra
->num_labels
= num_labels
;
3368 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3369 bgp_set_valid_label(&extra
->label
[0]);
3372 /* Update Overlay Index */
3373 if (afi
== AFI_L2VPN
) {
3374 overlay_index_update(new->attr
,
3375 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3376 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3378 /* Nexthop reachability check. */
3379 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3380 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3381 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3382 && !CHECK_FLAG(peer
->flags
,
3383 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3384 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3389 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3390 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3391 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3393 if (BGP_DEBUG(nht
, NHT
)) {
3394 char buf1
[INET6_ADDRSTRLEN
];
3396 (const void *)&attr_new
->nexthop
,
3397 buf1
, INET6_ADDRSTRLEN
);
3398 zlog_debug("%s(%s): NH unresolved",
3399 __FUNCTION__
, buf1
);
3401 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3404 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3407 new->addpath_rx_id
= addpath_id
;
3409 /* Increment prefix */
3410 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3412 /* Register new BGP information. */
3413 bgp_info_add(rn
, new);
3415 /* route_node_get lock */
3416 bgp_unlock_node(rn
);
3419 if (safi
== SAFI_MPLS_VPN
) {
3420 struct bgp_node
*prn
= NULL
;
3421 struct bgp_table
*table
= NULL
;
3423 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3425 table
= (struct bgp_table
*)(prn
->info
);
3427 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3428 bgp
, prd
, table
, p
, new);
3430 bgp_unlock_node(prn
);
3434 /* If maximum prefix count is configured and current prefix
3436 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3439 /* If this is an EVPN route, process for import. */
3440 if (safi
== SAFI_EVPN
)
3441 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3443 /* Process change. */
3444 bgp_process(bgp
, rn
, afi
, safi
);
3446 if (SAFI_UNICAST
== safi
3447 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3448 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3449 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3451 if ((SAFI_MPLS_VPN
== safi
)
3452 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3454 vpn_leak_to_vrf_update(bgp
, new);
3457 if (SAFI_MPLS_VPN
== safi
) {
3458 mpls_label_t label_decoded
= decode_label(label
);
3460 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3461 sub_type
, &label_decoded
);
3463 if (SAFI_ENCAP
== safi
) {
3464 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3471 /* This BGP update is filtered. Log the reason then update BGP
3474 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3475 if (!peer
->rcvd_attr_printed
) {
3476 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3477 peer
->rcvd_attr_str
);
3478 peer
->rcvd_attr_printed
= 1;
3481 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3482 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3484 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3485 peer
->host
, pfx_buf
, reason
);
3489 /* If this is an EVPN route, un-import it as it is now filtered.
3491 if (safi
== SAFI_EVPN
)
3492 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3494 if (SAFI_UNICAST
== safi
3495 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3496 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3498 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3500 if ((SAFI_MPLS_VPN
== safi
)
3501 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3503 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3506 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3509 bgp_unlock_node(rn
);
3513 * Filtered update is treated as an implicit withdrawal (see
3515 * a few lines above)
3517 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3518 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3526 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3527 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3528 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3529 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3532 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3533 struct bgp_node
*rn
;
3534 struct bgp_info
*ri
;
3537 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3538 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3546 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3548 /* If peer is soft reconfiguration enabled. Record input packet for
3549 * further calculation.
3551 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3552 * routes that are filtered. This tanks out Quagga RS pretty badly due
3554 * the iteration over all RS clients.
3555 * Since we need to remove the entry from adj_in anyway, do that first
3557 * if there was no entry, we don't need to do anything more.
3559 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3560 && peer
!= bgp
->peer_self
)
3561 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3562 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3563 bgp_debug_rdpfxpath2str(
3564 afi
, safi
, prd
, p
, label
, num_labels
,
3565 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3568 "%s withdrawing route %s not in adj-in",
3569 peer
->host
, pfx_buf
);
3571 bgp_unlock_node(rn
);
3575 /* Lookup withdrawn route. */
3576 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3577 if (ri
->peer
== peer
&& ri
->type
== type
3578 && ri
->sub_type
== sub_type
3579 && ri
->addpath_rx_id
== addpath_id
)
3583 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3584 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3585 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3587 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3591 /* Withdraw specified route from routing table. */
3592 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3593 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3594 if (SAFI_UNICAST
== safi
3595 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3596 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3597 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3599 if ((SAFI_MPLS_VPN
== safi
)
3600 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3602 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3604 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3605 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3606 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3608 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3611 /* Unlock bgp_node_get() lock. */
3612 bgp_unlock_node(rn
);
3617 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3620 struct update_subgroup
*subgrp
;
3621 subgrp
= peer_subgroup(peer
, afi
, safi
);
3622 subgroup_default_originate(subgrp
, withdraw
);
3627 * bgp_stop_announce_route_timer
3629 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3631 if (!paf
->t_announce_route
)
3634 THREAD_TIMER_OFF(paf
->t_announce_route
);
3638 * bgp_announce_route_timer_expired
3640 * Callback that is invoked when the route announcement timer for a
3643 static int bgp_announce_route_timer_expired(struct thread
*t
)
3645 struct peer_af
*paf
;
3648 paf
= THREAD_ARG(t
);
3651 if (peer
->status
!= Established
)
3654 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3657 peer_af_announce_route(paf
, 1);
3662 * bgp_announce_route
3664 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3666 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3668 struct peer_af
*paf
;
3669 struct update_subgroup
*subgrp
;
3671 paf
= peer_af_find(peer
, afi
, safi
);
3674 subgrp
= PAF_SUBGRP(paf
);
3677 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3678 * or a refresh has already been triggered.
3680 if (!subgrp
|| paf
->t_announce_route
)
3684 * Start a timer to stagger/delay the announce. This serves
3685 * two purposes - announcement can potentially be combined for
3686 * multiple peers and the announcement doesn't happen in the
3689 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3690 (subgrp
->peer_count
== 1)
3691 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3692 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3693 &paf
->t_announce_route
);
3697 * Announce routes from all AF tables to a peer.
3699 * This should ONLY be called when there is a need to refresh the
3700 * routes to the peer based on a policy change for this peer alone
3701 * or a route refresh request received from the peer.
3702 * The operation will result in splitting the peer from its existing
3703 * subgroups and putting it in new subgroups.
3705 void bgp_announce_route_all(struct peer
*peer
)
3710 FOREACH_AFI_SAFI (afi
, safi
)
3711 bgp_announce_route(peer
, afi
, safi
);
3714 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3715 struct bgp_table
*table
,
3716 struct prefix_rd
*prd
)
3719 struct bgp_node
*rn
;
3720 struct bgp_adj_in
*ain
;
3723 table
= peer
->bgp
->rib
[afi
][safi
];
3725 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3726 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3727 if (ain
->peer
!= peer
)
3730 struct bgp_info
*ri
= rn
->info
;
3731 uint32_t num_labels
= 0;
3732 mpls_label_t
*label_pnt
= NULL
;
3734 if (ri
&& ri
->extra
)
3735 num_labels
= ri
->extra
->num_labels
;
3737 label_pnt
= &ri
->extra
->label
[0];
3739 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3740 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3741 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3742 num_labels
, 1, NULL
);
3745 bgp_unlock_node(rn
);
3751 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3753 struct bgp_node
*rn
;
3754 struct bgp_table
*table
;
3756 if (peer
->status
!= Established
)
3759 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3760 && (safi
!= SAFI_EVPN
))
3761 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3763 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3764 rn
= bgp_route_next(rn
))
3765 if ((table
= rn
->info
) != NULL
) {
3766 struct prefix_rd prd
;
3767 prd
.family
= AF_UNSPEC
;
3769 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3771 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3777 struct bgp_clear_node_queue
{
3778 struct bgp_node
*rn
;
3781 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3783 struct bgp_clear_node_queue
*cnq
= data
;
3784 struct bgp_node
*rn
= cnq
->rn
;
3785 struct peer
*peer
= wq
->spec
.data
;
3786 struct bgp_info
*ri
;
3788 afi_t afi
= bgp_node_table(rn
)->afi
;
3789 safi_t safi
= bgp_node_table(rn
)->safi
;
3794 /* It is possible that we have multiple paths for a prefix from a peer
3795 * if that peer is using AddPath.
3797 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3798 if (ri
->peer
!= peer
)
3801 /* graceful restart STALE flag set. */
3802 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3803 && peer
->nsf
[afi
][safi
]
3804 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3805 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3806 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3808 /* If this is an EVPN route, process for
3810 if (safi
== SAFI_EVPN
)
3811 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3813 /* Handle withdraw for VRF route-leaking and L3VPN */
3814 if (SAFI_UNICAST
== safi
3815 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3816 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3817 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3820 if (SAFI_MPLS_VPN
== safi
&&
3821 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3822 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3825 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3831 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3833 struct bgp_clear_node_queue
*cnq
= data
;
3834 struct bgp_node
*rn
= cnq
->rn
;
3835 struct bgp_table
*table
= bgp_node_table(rn
);
3837 bgp_unlock_node(rn
);
3838 bgp_table_unlock(table
);
3839 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3842 static void bgp_clear_node_complete(struct work_queue
*wq
)
3844 struct peer
*peer
= wq
->spec
.data
;
3846 /* Tickle FSM to start moving again */
3847 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3849 peer_unlock(peer
); /* bgp_clear_route */
3852 static void bgp_clear_node_queue_init(struct peer
*peer
)
3854 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3856 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3857 #undef CLEAR_QUEUE_NAME_LEN
3859 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3860 peer
->clear_node_queue
->spec
.hold
= 10;
3861 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3862 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3863 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3864 peer
->clear_node_queue
->spec
.max_retries
= 0;
3866 /* we only 'lock' this peer reference when the queue is actually active
3868 peer
->clear_node_queue
->spec
.data
= peer
;
3871 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3872 struct bgp_table
*table
)
3874 struct bgp_node
*rn
;
3875 int force
= bm
->process_main_queue
? 0 : 1;
3878 table
= peer
->bgp
->rib
[afi
][safi
];
3880 /* If still no table => afi/safi isn't configured at all or smth. */
3884 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3885 struct bgp_info
*ri
, *next
;
3886 struct bgp_adj_in
*ain
;
3887 struct bgp_adj_in
*ain_next
;
3889 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3890 * queued for every clearing peer, regardless of whether it is
3891 * relevant to the peer at hand.
3893 * Overview: There are 3 different indices which need to be
3894 * scrubbed, potentially, when a peer is removed:
3896 * 1 peer's routes visible via the RIB (ie accepted routes)
3897 * 2 peer's routes visible by the (optional) peer's adj-in index
3898 * 3 other routes visible by the peer's adj-out index
3900 * 3 there is no hurry in scrubbing, once the struct peer is
3901 * removed from bgp->peer, we could just GC such deleted peer's
3902 * adj-outs at our leisure.
3904 * 1 and 2 must be 'scrubbed' in some way, at least made
3905 * invisible via RIB index before peer session is allowed to be
3906 * brought back up. So one needs to know when such a 'search' is
3911 * - there'd be a single global queue or a single RIB walker
3912 * - rather than tracking which route_nodes still need to be
3913 * examined on a peer basis, we'd track which peers still
3916 * Given that our per-peer prefix-counts now should be reliable,
3917 * this may actually be achievable. It doesn't seem to be a huge
3918 * problem at this time,
3920 * It is possible that we have multiple paths for a prefix from
3922 * if that peer is using AddPath.
3926 ain_next
= ain
->next
;
3928 if (ain
->peer
== peer
) {
3929 bgp_adj_in_remove(rn
, ain
);
3930 bgp_unlock_node(rn
);
3936 for (ri
= rn
->info
; ri
; ri
= next
) {
3938 if (ri
->peer
!= peer
)
3942 bgp_info_reap(rn
, ri
);
3944 struct bgp_clear_node_queue
*cnq
;
3946 /* both unlocked in bgp_clear_node_queue_del */
3947 bgp_table_lock(bgp_node_table(rn
));
3950 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3951 sizeof(struct bgp_clear_node_queue
));
3953 work_queue_add(peer
->clear_node_queue
, cnq
);
3961 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3963 struct bgp_node
*rn
;
3964 struct bgp_table
*table
;
3966 if (peer
->clear_node_queue
== NULL
)
3967 bgp_clear_node_queue_init(peer
);
3969 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3970 * Idle until it receives a Clearing_Completed event. This protects
3971 * against peers which flap faster than we can we clear, which could
3974 * a) race with routes from the new session being installed before
3975 * clear_route_node visits the node (to delete the route of that
3977 * b) resource exhaustion, clear_route_node likely leads to an entry
3978 * on the process_main queue. Fast-flapping could cause that queue
3982 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3983 * the unlock will happen upon work-queue completion; other wise, the
3984 * unlock happens at the end of this function.
3986 if (!peer
->clear_node_queue
->thread
)
3989 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3990 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3992 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3993 rn
= bgp_route_next(rn
))
3994 if ((table
= rn
->info
) != NULL
)
3995 bgp_clear_route_table(peer
, afi
, safi
, table
);
3997 /* unlock if no nodes got added to the clear-node-queue. */
3998 if (!peer
->clear_node_queue
->thread
)
4002 void bgp_clear_route_all(struct peer
*peer
)
4007 FOREACH_AFI_SAFI (afi
, safi
)
4008 bgp_clear_route(peer
, afi
, safi
);
4011 rfapiProcessPeerDown(peer
);
4015 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4017 struct bgp_table
*table
;
4018 struct bgp_node
*rn
;
4019 struct bgp_adj_in
*ain
;
4020 struct bgp_adj_in
*ain_next
;
4022 table
= peer
->bgp
->rib
[afi
][safi
];
4024 /* It is possible that we have multiple paths for a prefix from a peer
4025 * if that peer is using AddPath.
4027 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4031 ain_next
= ain
->next
;
4033 if (ain
->peer
== peer
) {
4034 bgp_adj_in_remove(rn
, ain
);
4035 bgp_unlock_node(rn
);
4043 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4045 struct bgp_node
*rn
;
4046 struct bgp_info
*ri
;
4047 struct bgp_table
*table
;
4049 if (safi
== SAFI_MPLS_VPN
) {
4050 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4051 rn
= bgp_route_next(rn
)) {
4052 struct bgp_node
*rm
;
4054 /* look for neighbor in tables */
4055 if ((table
= rn
->info
) == NULL
)
4058 for (rm
= bgp_table_top(table
); rm
;
4059 rm
= bgp_route_next(rm
))
4060 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4061 if (ri
->peer
!= peer
)
4063 if (!CHECK_FLAG(ri
->flags
,
4067 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4072 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4073 rn
= bgp_route_next(rn
))
4074 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4075 if (ri
->peer
!= peer
)
4077 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4079 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4085 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4088 struct bgp_node
*rn
;
4089 struct bgp_info
*ri
;
4090 struct bgp_info
*next
;
4092 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4093 for (ri
= rn
->info
; ri
; ri
= next
) {
4095 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4096 && ri
->type
== ZEBRA_ROUTE_BGP
4097 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4098 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4099 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4101 if (bgp_fibupd_safi(safi
))
4102 bgp_zebra_withdraw(&rn
->p
, ri
,
4104 bgp_info_reap(rn
, ri
);
4109 /* Delete all kernel routes. */
4110 void bgp_cleanup_routes(struct bgp
*bgp
)
4113 struct bgp_node
*rn
;
4115 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4116 if (afi
== AFI_L2VPN
)
4118 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4121 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4123 if (afi
!= AFI_L2VPN
) {
4125 safi
= SAFI_MPLS_VPN
;
4126 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4127 rn
= bgp_route_next(rn
)) {
4129 bgp_cleanup_table(bgp
,
4130 (struct bgp_table
*)(rn
->info
),
4132 bgp_table_finish((struct bgp_table
**)&(
4135 bgp_unlock_node(rn
);
4139 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4140 rn
= bgp_route_next(rn
)) {
4142 bgp_cleanup_table(bgp
,
4143 (struct bgp_table
*)(rn
->info
),
4145 bgp_table_finish((struct bgp_table
**)&(
4148 bgp_unlock_node(rn
);
4153 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4154 rn
= bgp_route_next(rn
)) {
4156 bgp_cleanup_table(bgp
,
4157 (struct bgp_table
*)(rn
->info
),
4159 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4161 bgp_unlock_node(rn
);
4166 void bgp_reset(void)
4169 bgp_zclient_reset();
4170 access_list_reset();
4171 prefix_list_reset();
4174 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4176 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4177 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4178 PEER_CAP_ADDPATH_AF_TX_RCV
));
4181 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4183 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4184 struct bgp_nlri
*packet
)
4193 int addpath_encoded
;
4194 uint32_t addpath_id
;
4197 lim
= pnt
+ packet
->length
;
4199 safi
= packet
->safi
;
4201 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4203 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4204 syntactic validity. If the field is syntactically incorrect,
4205 then the Error Subcode is set to Invalid Network Field. */
4206 for (; pnt
< lim
; pnt
+= psize
) {
4207 /* Clear prefix structure. */
4208 memset(&p
, 0, sizeof(struct prefix
));
4210 if (addpath_encoded
) {
4212 /* When packet overflow occurs return immediately. */
4213 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4216 addpath_id
= ntohl(*((uint32_t *)pnt
));
4217 pnt
+= BGP_ADDPATH_ID_LEN
;
4220 /* Fetch prefix length. */
4221 p
.prefixlen
= *pnt
++;
4222 /* afi/safi validity already verified by caller,
4223 * bgp_update_receive */
4224 p
.family
= afi2family(afi
);
4226 /* Prefix length check. */
4227 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4230 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4231 peer
->host
, p
.prefixlen
, packet
->afi
);
4235 /* Packet size overflow check. */
4236 psize
= PSIZE(p
.prefixlen
);
4238 /* When packet overflow occur return immediately. */
4239 if (pnt
+ psize
> lim
) {
4242 "%s [Error] Update packet error (prefix length %d overflows packet)",
4243 peer
->host
, p
.prefixlen
);
4247 /* Defensive coding, double-check the psize fits in a struct
4249 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4252 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4253 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4257 /* Fetch prefix from NLRI packet. */
4258 memcpy(p
.u
.val
, pnt
, psize
);
4260 /* Check address. */
4261 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4262 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4263 /* From RFC4271 Section 6.3:
4265 * If a prefix in the NLRI field is semantically
4267 * (e.g., an unexpected multicast IP address),
4269 * be logged locally, and the prefix SHOULD be
4274 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4275 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4280 /* Check address. */
4281 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4282 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4287 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4289 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4294 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4299 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4301 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4308 /* Normal process. */
4310 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4311 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4312 NULL
, NULL
, 0, 0, NULL
);
4314 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4315 safi
, ZEBRA_ROUTE_BGP
,
4316 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4319 /* Address family configuration mismatch or maximum-prefix count
4325 /* Packet length consistency check. */
4329 "%s [Error] Update packet error (prefix length mismatch with total length)",
4337 static struct bgp_static
*bgp_static_new(void)
4339 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4342 static void bgp_static_free(struct bgp_static
*bgp_static
)
4344 if (bgp_static
->rmap
.name
)
4345 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4346 if (bgp_static
->eth_s_id
)
4347 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4348 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4351 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4352 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4354 struct bgp_node
*rn
;
4355 struct bgp_info
*ri
;
4356 struct bgp_info
*new;
4357 struct bgp_info info
;
4359 struct attr
*attr_new
;
4362 int vnc_implicit_withdraw
= 0;
4369 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4371 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4373 attr
.nexthop
= bgp_static
->igpnexthop
;
4374 attr
.med
= bgp_static
->igpmetric
;
4375 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4377 if (bgp_static
->atomic
)
4378 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4380 /* Store label index, if required. */
4381 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4382 attr
.label_index
= bgp_static
->label_index
;
4383 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4386 /* Apply route-map. */
4387 if (bgp_static
->rmap
.name
) {
4388 struct attr attr_tmp
= attr
;
4390 memset(&info
, 0, sizeof(struct bgp_info
));
4391 info
.peer
= bgp
->peer_self
;
4392 info
.attr
= &attr_tmp
;
4394 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4396 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4398 bgp
->peer_self
->rmap_type
= 0;
4400 if (ret
== RMAP_DENYMATCH
) {
4401 /* Free uninterned attribute. */
4402 bgp_attr_flush(&attr_tmp
);
4404 /* Unintern original. */
4405 aspath_unintern(&attr
.aspath
);
4406 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4410 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4411 bgp_attr_add_gshut_community(&attr_tmp
);
4413 attr_new
= bgp_attr_intern(&attr_tmp
);
4416 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4417 bgp_attr_add_gshut_community(&attr
);
4419 attr_new
= bgp_attr_intern(&attr
);
4422 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4423 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4424 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4428 if (attrhash_cmp(ri
->attr
, attr_new
)
4429 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4430 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4431 bgp_unlock_node(rn
);
4432 bgp_attr_unintern(&attr_new
);
4433 aspath_unintern(&attr
.aspath
);
4436 /* The attribute is changed. */
4437 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4439 /* Rewrite BGP route information. */
4440 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4441 bgp_info_restore(rn
, ri
);
4443 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4445 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4446 && (safi
== SAFI_UNICAST
)) {
4447 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4449 * Implicit withdraw case.
4450 * We have to do this before ri is
4453 ++vnc_implicit_withdraw
;
4454 vnc_import_bgp_del_route(bgp
, p
, ri
);
4455 vnc_import_bgp_exterior_del_route(
4460 bgp_attr_unintern(&ri
->attr
);
4461 ri
->attr
= attr_new
;
4462 ri
->uptime
= bgp_clock();
4464 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4465 && (safi
== SAFI_UNICAST
)) {
4466 if (vnc_implicit_withdraw
) {
4467 vnc_import_bgp_add_route(bgp
, p
, ri
);
4468 vnc_import_bgp_exterior_add_route(
4474 /* Nexthop reachability check. */
4475 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4476 && (safi
== SAFI_UNICAST
4477 || safi
== SAFI_LABELED_UNICAST
)) {
4479 struct bgp
*bgp_nexthop
= bgp
;
4481 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4482 bgp_nexthop
= ri
->extra
->bgp_orig
;
4484 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4486 bgp_info_set_flag(rn
, ri
,
4489 if (BGP_DEBUG(nht
, NHT
)) {
4490 char buf1
[INET6_ADDRSTRLEN
];
4491 inet_ntop(p
->family
,
4495 "%s(%s): Route not in table, not advertising",
4496 __FUNCTION__
, buf1
);
4498 bgp_info_unset_flag(rn
, ri
,
4502 /* Delete the NHT structure if any, if we're
4504 * enabling/disabling import check. We
4505 * deregister the route
4506 * from NHT to avoid overloading NHT and the
4507 * process interaction
4509 bgp_unlink_nexthop(ri
);
4510 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4512 /* Process change. */
4513 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4514 bgp_process(bgp
, rn
, afi
, safi
);
4516 if (SAFI_UNICAST
== safi
4517 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4519 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4520 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4524 bgp_unlock_node(rn
);
4525 aspath_unintern(&attr
.aspath
);
4530 /* Make new BGP info. */
4531 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4533 /* Nexthop reachability check. */
4534 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4535 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4536 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4537 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4539 if (BGP_DEBUG(nht
, NHT
)) {
4540 char buf1
[INET6_ADDRSTRLEN
];
4541 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4544 "%s(%s): Route not in table, not advertising",
4545 __FUNCTION__
, buf1
);
4547 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4550 /* Delete the NHT structure if any, if we're toggling between
4551 * enabling/disabling import check. We deregister the route
4552 * from NHT to avoid overloading NHT and the process interaction
4554 bgp_unlink_nexthop(new);
4556 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4559 /* Aggregate address increment. */
4560 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4562 /* Register new BGP information. */
4563 bgp_info_add(rn
, new);
4565 /* route_node_get lock */
4566 bgp_unlock_node(rn
);
4568 /* Process change. */
4569 bgp_process(bgp
, rn
, afi
, safi
);
4571 if (SAFI_UNICAST
== safi
4572 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4573 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4574 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4577 /* Unintern original. */
4578 aspath_unintern(&attr
.aspath
);
4581 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4584 struct bgp_node
*rn
;
4585 struct bgp_info
*ri
;
4587 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4589 /* Check selected route and self inserted route. */
4590 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4591 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4592 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4595 /* Withdraw static BGP route from routing table. */
4597 if (SAFI_UNICAST
== safi
4598 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4599 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4600 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4602 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4603 bgp_unlink_nexthop(ri
);
4604 bgp_info_delete(rn
, ri
);
4605 bgp_process(bgp
, rn
, afi
, safi
);
4608 /* Unlock bgp_node_lookup. */
4609 bgp_unlock_node(rn
);
4613 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4615 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4616 afi_t afi
, safi_t safi
,
4617 struct prefix_rd
*prd
)
4619 struct bgp_node
*rn
;
4620 struct bgp_info
*ri
;
4622 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4624 /* Check selected route and self inserted route. */
4625 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4626 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4627 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4630 /* Withdraw static BGP route from routing table. */
4633 rfapiProcessWithdraw(
4634 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4635 1); /* Kill, since it is an administrative change */
4637 if (SAFI_MPLS_VPN
== safi
4638 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4639 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4641 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4642 bgp_info_delete(rn
, ri
);
4643 bgp_process(bgp
, rn
, afi
, safi
);
4646 /* Unlock bgp_node_lookup. */
4647 bgp_unlock_node(rn
);
4650 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4651 struct bgp_static
*bgp_static
, afi_t afi
,
4654 struct bgp_node
*rn
;
4655 struct bgp_info
*new;
4656 struct attr
*attr_new
;
4657 struct attr attr
= {0};
4658 struct bgp_info
*ri
;
4660 mpls_label_t label
= 0;
4662 uint32_t num_labels
= 0;
4667 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4669 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4672 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4674 attr
.nexthop
= bgp_static
->igpnexthop
;
4675 attr
.med
= bgp_static
->igpmetric
;
4676 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4678 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4679 || (safi
== SAFI_ENCAP
)) {
4680 if (afi
== AFI_IP
) {
4681 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4682 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4685 if (afi
== AFI_L2VPN
) {
4686 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4688 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4689 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4690 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4691 sizeof(struct in6_addr
));
4692 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4693 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4694 struct bgp_encap_type_vxlan bet
;
4695 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4696 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4697 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4699 if (bgp_static
->router_mac
) {
4700 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4703 /* Apply route-map. */
4704 if (bgp_static
->rmap
.name
) {
4705 struct attr attr_tmp
= attr
;
4706 struct bgp_info info
;
4709 info
.peer
= bgp
->peer_self
;
4710 info
.attr
= &attr_tmp
;
4712 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4714 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4716 bgp
->peer_self
->rmap_type
= 0;
4718 if (ret
== RMAP_DENYMATCH
) {
4719 /* Free uninterned attribute. */
4720 bgp_attr_flush(&attr_tmp
);
4722 /* Unintern original. */
4723 aspath_unintern(&attr
.aspath
);
4724 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4729 attr_new
= bgp_attr_intern(&attr_tmp
);
4731 attr_new
= bgp_attr_intern(&attr
);
4734 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4735 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4736 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4740 memset(&add
, 0, sizeof(union gw_addr
));
4741 if (attrhash_cmp(ri
->attr
, attr_new
)
4742 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4743 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4744 bgp_unlock_node(rn
);
4745 bgp_attr_unintern(&attr_new
);
4746 aspath_unintern(&attr
.aspath
);
4749 /* The attribute is changed. */
4750 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4752 /* Rewrite BGP route information. */
4753 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4754 bgp_info_restore(rn
, ri
);
4756 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4757 bgp_attr_unintern(&ri
->attr
);
4758 ri
->attr
= attr_new
;
4759 ri
->uptime
= bgp_clock();
4762 label
= decode_label(&ri
->extra
->label
[0]);
4765 /* Process change. */
4766 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4767 bgp_process(bgp
, rn
, afi
, safi
);
4769 if (SAFI_MPLS_VPN
== safi
4770 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4771 vpn_leak_to_vrf_update(bgp
, ri
);
4774 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4775 ri
->attr
, afi
, safi
, ri
->type
,
4776 ri
->sub_type
, &label
);
4778 bgp_unlock_node(rn
);
4779 aspath_unintern(&attr
.aspath
);
4785 /* Make new BGP info. */
4786 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4788 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4789 new->extra
= bgp_info_extra_new();
4791 new->extra
->label
[0] = bgp_static
->label
;
4792 new->extra
->num_labels
= num_labels
;
4795 label
= decode_label(&bgp_static
->label
);
4798 /* Aggregate address increment. */
4799 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4801 /* Register new BGP information. */
4802 bgp_info_add(rn
, new);
4803 /* route_node_get lock */
4804 bgp_unlock_node(rn
);
4806 /* Process change. */
4807 bgp_process(bgp
, rn
, afi
, safi
);
4809 if (SAFI_MPLS_VPN
== safi
4810 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4811 vpn_leak_to_vrf_update(bgp
, new);
4814 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4815 safi
, new->type
, new->sub_type
, &label
);
4818 /* Unintern original. */
4819 aspath_unintern(&attr
.aspath
);
4822 /* Configure static BGP network. When user don't run zebra, static
4823 route should be installed as valid. */
4824 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4825 const char *ip_str
, afi_t afi
, safi_t safi
,
4826 const char *rmap
, int backdoor
, uint32_t label_index
)
4828 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4831 struct bgp_static
*bgp_static
;
4832 struct bgp_node
*rn
;
4833 uint8_t need_update
= 0;
4835 /* Convert IP prefix string to struct prefix. */
4836 ret
= str2prefix(ip_str
, &p
);
4838 vty_out(vty
, "%% Malformed prefix\n");
4839 return CMD_WARNING_CONFIG_FAILED
;
4841 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4842 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4843 return CMD_WARNING_CONFIG_FAILED
;
4850 /* Set BGP static route configuration. */
4851 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4854 vty_out(vty
, "%% Can't find static route specified\n");
4855 return CMD_WARNING_CONFIG_FAILED
;
4858 bgp_static
= bgp_static_get_node_info(rn
);
4860 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4861 && (label_index
!= bgp_static
->label_index
)) {
4863 "%% label-index doesn't match static route\n");
4864 return CMD_WARNING_CONFIG_FAILED
;
4867 if ((rmap
&& bgp_static
->rmap
.name
)
4868 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4870 "%% route-map name doesn't match static route\n");
4871 return CMD_WARNING_CONFIG_FAILED
;
4874 /* Update BGP RIB. */
4875 if (!bgp_static
->backdoor
)
4876 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4878 /* Clear configuration. */
4879 bgp_static_free(bgp_static
);
4880 bgp_static_set_node_info(rn
, NULL
);
4881 bgp_unlock_node(rn
);
4882 bgp_unlock_node(rn
);
4885 /* Set BGP static route configuration. */
4886 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4888 bgp_static
= bgp_static_get_node_info(rn
);
4890 /* Configuration change. */
4891 /* Label index cannot be changed. */
4892 if (bgp_static
->label_index
!= label_index
) {
4893 vty_out(vty
, "%% cannot change label-index\n");
4894 return CMD_WARNING_CONFIG_FAILED
;
4897 /* Check previous routes are installed into BGP. */
4898 if (bgp_static
->valid
4899 && bgp_static
->backdoor
!= backdoor
)
4902 bgp_static
->backdoor
= backdoor
;
4905 if (bgp_static
->rmap
.name
)
4906 XFREE(MTYPE_ROUTE_MAP_NAME
,
4907 bgp_static
->rmap
.name
);
4908 bgp_static
->rmap
.name
=
4909 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4910 bgp_static
->rmap
.map
=
4911 route_map_lookup_by_name(rmap
);
4913 if (bgp_static
->rmap
.name
)
4914 XFREE(MTYPE_ROUTE_MAP_NAME
,
4915 bgp_static
->rmap
.name
);
4916 bgp_static
->rmap
.name
= NULL
;
4917 bgp_static
->rmap
.map
= NULL
;
4918 bgp_static
->valid
= 0;
4920 bgp_unlock_node(rn
);
4922 /* New configuration. */
4923 bgp_static
= bgp_static_new();
4924 bgp_static
->backdoor
= backdoor
;
4925 bgp_static
->valid
= 0;
4926 bgp_static
->igpmetric
= 0;
4927 bgp_static
->igpnexthop
.s_addr
= 0;
4928 bgp_static
->label_index
= label_index
;
4931 if (bgp_static
->rmap
.name
)
4932 XFREE(MTYPE_ROUTE_MAP_NAME
,
4933 bgp_static
->rmap
.name
);
4934 bgp_static
->rmap
.name
=
4935 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4936 bgp_static
->rmap
.map
=
4937 route_map_lookup_by_name(rmap
);
4939 bgp_static_set_node_info(rn
, bgp_static
);
4942 bgp_static
->valid
= 1;
4944 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4946 if (!bgp_static
->backdoor
)
4947 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4953 void bgp_static_add(struct bgp
*bgp
)
4957 struct bgp_node
*rn
;
4958 struct bgp_node
*rm
;
4959 struct bgp_table
*table
;
4960 struct bgp_static
*bgp_static
;
4962 FOREACH_AFI_SAFI (afi
, safi
)
4963 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4964 rn
= bgp_route_next(rn
)) {
4965 if (rn
->info
== NULL
)
4968 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4969 || (safi
== SAFI_EVPN
)) {
4972 for (rm
= bgp_table_top(table
); rm
;
4973 rm
= bgp_route_next(rm
)) {
4975 bgp_static_get_node_info(rm
);
4976 bgp_static_update_safi(bgp
, &rm
->p
,
4981 bgp_static_update(bgp
, &rn
->p
,
4982 bgp_static_get_node_info(rn
),
4988 /* Called from bgp_delete(). Delete all static routes from the BGP
4990 void bgp_static_delete(struct bgp
*bgp
)
4994 struct bgp_node
*rn
;
4995 struct bgp_node
*rm
;
4996 struct bgp_table
*table
;
4997 struct bgp_static
*bgp_static
;
4999 FOREACH_AFI_SAFI (afi
, safi
)
5000 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5001 rn
= bgp_route_next(rn
)) {
5002 if (rn
->info
== NULL
)
5005 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5006 || (safi
== SAFI_EVPN
)) {
5009 for (rm
= bgp_table_top(table
); rm
;
5010 rm
= bgp_route_next(rm
)) {
5012 bgp_static_get_node_info(rm
);
5013 bgp_static_withdraw_safi(
5014 bgp
, &rm
->p
, AFI_IP
, safi
,
5015 (struct prefix_rd
*)&rn
->p
);
5016 bgp_static_free(bgp_static
);
5017 bgp_static_set_node_info(rn
, NULL
);
5018 bgp_unlock_node(rn
);
5021 bgp_static
= bgp_static_get_node_info(rn
);
5022 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5023 bgp_static_free(bgp_static
);
5024 bgp_static_set_node_info(rn
, NULL
);
5025 bgp_unlock_node(rn
);
5030 void bgp_static_redo_import_check(struct bgp
*bgp
)
5034 struct bgp_node
*rn
;
5035 struct bgp_node
*rm
;
5036 struct bgp_table
*table
;
5037 struct bgp_static
*bgp_static
;
5039 /* Use this flag to force reprocessing of the route */
5040 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5041 FOREACH_AFI_SAFI (afi
, safi
) {
5042 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5043 rn
= bgp_route_next(rn
)) {
5044 if (rn
->info
== NULL
)
5047 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5048 || (safi
== SAFI_EVPN
)) {
5051 for (rm
= bgp_table_top(table
); rm
;
5052 rm
= bgp_route_next(rm
)) {
5054 bgp_static_get_node_info(rm
);
5055 bgp_static_update_safi(bgp
, &rm
->p
,
5060 bgp_static
= bgp_static_get_node_info(rn
);
5061 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5066 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5069 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5072 struct bgp_table
*table
;
5073 struct bgp_node
*rn
;
5074 struct bgp_info
*ri
;
5076 table
= bgp
->rib
[afi
][safi
];
5077 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5078 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5079 if (ri
->peer
== bgp
->peer_self
5080 && ((ri
->type
== ZEBRA_ROUTE_BGP
5081 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5082 || (ri
->type
!= ZEBRA_ROUTE_BGP
5084 == BGP_ROUTE_REDISTRIBUTE
))) {
5085 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5087 bgp_unlink_nexthop(ri
);
5088 bgp_info_delete(rn
, ri
);
5089 bgp_process(bgp
, rn
, afi
, safi
);
5096 * Purge all networks and redistributed routes from routing table.
5097 * Invoked upon the instance going down.
5099 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5104 FOREACH_AFI_SAFI (afi
, safi
)
5105 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5110 * Currently this is used to set static routes for VPN and ENCAP.
5111 * I think it can probably be factored with bgp_static_set.
5113 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5114 const char *ip_str
, const char *rd_str
,
5115 const char *label_str
, const char *rmap_str
,
5116 int evpn_type
, const char *esi
, const char *gwip
,
5117 const char *ethtag
, const char *routermac
)
5119 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5122 struct prefix_rd prd
;
5123 struct bgp_node
*prn
;
5124 struct bgp_node
*rn
;
5125 struct bgp_table
*table
;
5126 struct bgp_static
*bgp_static
;
5127 mpls_label_t label
= MPLS_INVALID_LABEL
;
5128 struct prefix gw_ip
;
5130 /* validate ip prefix */
5131 ret
= str2prefix(ip_str
, &p
);
5133 vty_out(vty
, "%% Malformed prefix\n");
5134 return CMD_WARNING_CONFIG_FAILED
;
5137 if ((afi
== AFI_L2VPN
)
5138 && (bgp_build_evpn_prefix(evpn_type
,
5139 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5140 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5141 return CMD_WARNING_CONFIG_FAILED
;
5144 ret
= str2prefix_rd(rd_str
, &prd
);
5146 vty_out(vty
, "%% Malformed rd\n");
5147 return CMD_WARNING_CONFIG_FAILED
;
5151 unsigned long label_val
;
5152 label_val
= strtoul(label_str
, NULL
, 10);
5153 encode_label(label_val
, &label
);
5156 if (safi
== SAFI_EVPN
) {
5157 if (esi
&& str2esi(esi
, NULL
) == 0) {
5158 vty_out(vty
, "%% Malformed ESI\n");
5159 return CMD_WARNING_CONFIG_FAILED
;
5161 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5162 vty_out(vty
, "%% Malformed Router MAC\n");
5163 return CMD_WARNING_CONFIG_FAILED
;
5166 memset(&gw_ip
, 0, sizeof(struct prefix
));
5167 ret
= str2prefix(gwip
, &gw_ip
);
5169 vty_out(vty
, "%% Malformed GatewayIp\n");
5170 return CMD_WARNING_CONFIG_FAILED
;
5172 if ((gw_ip
.family
== AF_INET
5173 && is_evpn_prefix_ipaddr_v6(
5174 (struct prefix_evpn
*)&p
))
5175 || (gw_ip
.family
== AF_INET6
5176 && is_evpn_prefix_ipaddr_v4(
5177 (struct prefix_evpn
*)&p
))) {
5179 "%% GatewayIp family differs with IP prefix\n");
5180 return CMD_WARNING_CONFIG_FAILED
;
5184 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5185 if (prn
->info
== NULL
)
5186 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5188 bgp_unlock_node(prn
);
5191 rn
= bgp_node_get(table
, &p
);
5194 vty_out(vty
, "%% Same network configuration exists\n");
5195 bgp_unlock_node(rn
);
5197 /* New configuration. */
5198 bgp_static
= bgp_static_new();
5199 bgp_static
->backdoor
= 0;
5200 bgp_static
->valid
= 0;
5201 bgp_static
->igpmetric
= 0;
5202 bgp_static
->igpnexthop
.s_addr
= 0;
5203 bgp_static
->label
= label
;
5204 bgp_static
->prd
= prd
;
5207 if (bgp_static
->rmap
.name
)
5208 XFREE(MTYPE_ROUTE_MAP_NAME
,
5209 bgp_static
->rmap
.name
);
5210 bgp_static
->rmap
.name
=
5211 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5212 bgp_static
->rmap
.map
=
5213 route_map_lookup_by_name(rmap_str
);
5216 if (safi
== SAFI_EVPN
) {
5218 bgp_static
->eth_s_id
=
5220 sizeof(struct eth_segment_id
));
5221 str2esi(esi
, bgp_static
->eth_s_id
);
5224 bgp_static
->router_mac
=
5225 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5226 (void)prefix_str2mac(routermac
,
5227 bgp_static
->router_mac
);
5230 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5232 bgp_static_set_node_info(rn
, bgp_static
);
5234 bgp_static
->valid
= 1;
5235 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5241 /* Configure static BGP network. */
5242 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5243 const char *ip_str
, const char *rd_str
,
5244 const char *label_str
, int evpn_type
, const char *esi
,
5245 const char *gwip
, const char *ethtag
)
5247 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5250 struct prefix_rd prd
;
5251 struct bgp_node
*prn
;
5252 struct bgp_node
*rn
;
5253 struct bgp_table
*table
;
5254 struct bgp_static
*bgp_static
;
5255 mpls_label_t label
= MPLS_INVALID_LABEL
;
5257 /* Convert IP prefix string to struct prefix. */
5258 ret
= str2prefix(ip_str
, &p
);
5260 vty_out(vty
, "%% Malformed prefix\n");
5261 return CMD_WARNING_CONFIG_FAILED
;
5264 if ((afi
== AFI_L2VPN
)
5265 && (bgp_build_evpn_prefix(evpn_type
,
5266 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5267 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5268 return CMD_WARNING_CONFIG_FAILED
;
5270 ret
= str2prefix_rd(rd_str
, &prd
);
5272 vty_out(vty
, "%% Malformed rd\n");
5273 return CMD_WARNING_CONFIG_FAILED
;
5277 unsigned long label_val
;
5278 label_val
= strtoul(label_str
, NULL
, 10);
5279 encode_label(label_val
, &label
);
5282 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5283 if (prn
->info
== NULL
)
5284 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5286 bgp_unlock_node(prn
);
5289 rn
= bgp_node_lookup(table
, &p
);
5292 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5294 bgp_static
= bgp_static_get_node_info(rn
);
5295 bgp_static_free(bgp_static
);
5296 bgp_static_set_node_info(rn
, NULL
);
5297 bgp_unlock_node(rn
);
5298 bgp_unlock_node(rn
);
5300 vty_out(vty
, "%% Can't find the route\n");
5305 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5306 const char *rmap_name
)
5308 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5309 struct bgp_rmap
*rmap
;
5311 rmap
= &bgp
->table_map
[afi
][safi
];
5314 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5315 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5316 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5319 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5324 if (bgp_fibupd_safi(safi
))
5325 bgp_zebra_announce_table(bgp
, afi
, safi
);
5330 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5331 const char *rmap_name
)
5333 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5334 struct bgp_rmap
*rmap
;
5336 rmap
= &bgp
->table_map
[afi
][safi
];
5338 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5342 if (bgp_fibupd_safi(safi
))
5343 bgp_zebra_announce_table(bgp
, afi
, safi
);
5348 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5351 if (bgp
->table_map
[afi
][safi
].name
) {
5352 vty_out(vty
, " table-map %s\n",
5353 bgp
->table_map
[afi
][safi
].name
);
5357 DEFUN (bgp_table_map
,
5360 "BGP table to RIB route download filter\n"
5361 "Name of the route map\n")
5364 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5365 argv
[idx_word
]->arg
);
5367 DEFUN (no_bgp_table_map
,
5368 no_bgp_table_map_cmd
,
5369 "no table-map WORD",
5371 "BGP table to RIB route download filter\n"
5372 "Name of the route map\n")
5375 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5376 argv
[idx_word
]->arg
);
5382 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5383 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5384 backdoor$backdoor}]",
5386 "Specify a network to announce via BGP\n"
5391 "Route-map to modify the attributes\n"
5392 "Name of the route map\n"
5393 "Label index to associate with the prefix\n"
5394 "Label index value\n"
5395 "Specify a BGP backdoor route\n")
5397 char addr_prefix_str
[BUFSIZ
];
5402 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5405 vty_out(vty
, "%% Inconsistent address and mask\n");
5406 return CMD_WARNING_CONFIG_FAILED
;
5410 return bgp_static_set(
5411 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5412 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5413 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5416 DEFPY(ipv6_bgp_network
,
5417 ipv6_bgp_network_cmd
,
5418 "[no] network X:X::X:X/M$prefix \
5419 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5421 "Specify a network to announce via BGP\n"
5423 "Route-map to modify the attributes\n"
5424 "Name of the route map\n"
5425 "Label index to associate with the prefix\n"
5426 "Label index value\n")
5428 return bgp_static_set(
5429 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5430 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5433 /* Aggreagete address:
5435 advertise-map Set condition to advertise attribute
5436 as-set Generate AS set path information
5437 attribute-map Set attributes of aggregate
5438 route-map Set parameters of aggregate
5439 summary-only Filter more specific routes from updates
5440 suppress-map Conditionally filter more specific routes from updates
5443 struct bgp_aggregate
{
5444 /* Summary-only flag. */
5445 uint8_t summary_only
;
5447 /* AS set generation. */
5450 /* Route-map for aggregated route. */
5451 struct route_map
*map
;
5453 /* Suppress-count. */
5454 unsigned long count
;
5456 /* SAFI configuration. */
5460 static struct bgp_aggregate
*bgp_aggregate_new(void)
5462 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5465 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5467 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5470 static int bgp_aggregate_info_same(struct bgp_info
*ri
, uint8_t origin
,
5471 struct aspath
*aspath
,
5472 struct community
*comm
)
5474 static struct aspath
*ae
= NULL
;
5477 ae
= aspath_empty();
5482 if (origin
!= ri
->attr
->origin
)
5485 if (!aspath_cmp(ri
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5488 if (!community_cmp(ri
->attr
->community
, comm
))
5491 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
5497 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5498 struct prefix
*p
, uint8_t origin
,
5499 struct aspath
*aspath
,
5500 struct community
*community
,
5501 uint8_t atomic_aggregate
,
5502 struct bgp_aggregate
*aggregate
)
5504 struct bgp_node
*rn
;
5505 struct bgp_table
*table
;
5506 struct bgp_info
*ri
, *new;
5508 table
= bgp
->rib
[afi
][safi
];
5510 rn
= bgp_node_get(table
, p
);
5512 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5513 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5514 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5517 if (aggregate
->count
> 0) {
5519 * If the aggregate information has not changed
5520 * no need to re-install it again.
5522 if (bgp_aggregate_info_same(rn
->info
, origin
, aspath
,
5524 bgp_unlock_node(rn
);
5527 aspath_free(aspath
);
5529 community_free(community
);
5535 * Mark the old as unusable
5538 bgp_info_delete(rn
, ri
);
5541 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5542 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5543 community
, aggregate
->as_set
,
5546 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5548 bgp_info_add(rn
, new);
5549 bgp_process(bgp
, rn
, afi
, safi
);
5551 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5552 if (ri
->peer
== bgp
->peer_self
5553 && ri
->type
== ZEBRA_ROUTE_BGP
5554 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5557 /* Withdraw static BGP route from routing table. */
5559 bgp_info_delete(rn
, ri
);
5560 bgp_process(bgp
, rn
, afi
, safi
);
5564 bgp_unlock_node(rn
);
5567 /* Update an aggregate as routes are added/removed from the BGP table */
5568 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5569 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5570 struct bgp_info
*del
,
5571 struct bgp_aggregate
*aggregate
)
5573 struct bgp_table
*table
;
5574 struct bgp_node
*top
;
5575 struct bgp_node
*rn
;
5577 struct aspath
*aspath
= NULL
;
5578 struct aspath
*asmerge
= NULL
;
5579 struct community
*community
= NULL
;
5580 struct community
*commerge
= NULL
;
5581 struct bgp_info
*ri
;
5582 unsigned long match
= 0;
5583 uint8_t atomic_aggregate
= 0;
5585 /* ORIGIN attribute: If at least one route among routes that are
5586 aggregated has ORIGIN with the value INCOMPLETE, then the
5587 aggregated route must have the ORIGIN attribute with the value
5588 INCOMPLETE. Otherwise, if at least one route among routes that
5589 are aggregated has ORIGIN with the value EGP, then the aggregated
5590 route must have the origin attribute with the value EGP. In all
5591 other case the value of the ORIGIN attribute of the aggregated
5592 route is INTERNAL. */
5593 origin
= BGP_ORIGIN_IGP
;
5595 table
= bgp
->rib
[afi
][safi
];
5597 top
= bgp_node_get(table
, p
);
5598 for (rn
= bgp_node_get(table
, p
); rn
;
5599 rn
= bgp_route_next_until(rn
, top
)) {
5600 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5605 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5606 if (BGP_INFO_HOLDDOWN(ri
))
5609 if (del
&& ri
== del
)
5613 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5614 atomic_aggregate
= 1;
5616 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5620 * summary-only aggregate route suppress
5621 * aggregated route announcements.
5623 if (aggregate
->summary_only
) {
5624 (bgp_info_extra_get(ri
))->suppress
++;
5625 bgp_info_set_flag(rn
, ri
,
5626 BGP_INFO_ATTR_CHANGED
);
5633 * If at least one route among routes that are
5634 * aggregated has ORIGIN with the value INCOMPLETE,
5635 * then the aggregated route MUST have the ORIGIN
5636 * attribute with the value INCOMPLETE. Otherwise, if
5637 * at least one route among routes that are aggregated
5638 * has ORIGIN with the value EGP, then the aggregated
5639 * route MUST have the ORIGIN attribute with the value
5642 if (origin
< ri
->attr
->origin
)
5643 origin
= ri
->attr
->origin
;
5645 if (!aggregate
->as_set
)
5649 * as-set aggregate route generate origin, as path,
5650 * and community aggregation.
5653 asmerge
= aspath_aggregate(aspath
,
5655 aspath_free(aspath
);
5658 aspath
= aspath_dup(ri
->attr
->aspath
);
5660 if (!ri
->attr
->community
)
5664 commerge
= community_merge(community
,
5665 ri
->attr
->community
);
5666 community
= community_uniq_sort(commerge
);
5667 community_free(commerge
);
5669 community
= community_dup(ri
->attr
->community
);
5672 bgp_process(bgp
, rn
, afi
, safi
);
5674 bgp_unlock_node(top
);
5679 if (aggregate
->summary_only
)
5680 (bgp_info_extra_get(rinew
))->suppress
++;
5682 if (origin
< rinew
->attr
->origin
)
5683 origin
= rinew
->attr
->origin
;
5685 if (aggregate
->as_set
) {
5687 asmerge
= aspath_aggregate(aspath
,
5688 rinew
->attr
->aspath
);
5689 aspath_free(aspath
);
5692 aspath
= aspath_dup(rinew
->attr
->aspath
);
5694 if (rinew
->attr
->community
) {
5696 commerge
= community_merge(
5698 rinew
->attr
->community
);
5700 community_uniq_sort(commerge
);
5701 community_free(commerge
);
5703 community
= community_dup(
5704 rinew
->attr
->community
);
5709 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5710 atomic_aggregate
, aggregate
);
5712 if (aggregate
->count
== 0) {
5714 aspath_free(aspath
);
5716 community_free(community
);
5720 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5721 safi_t safi
, struct bgp_aggregate
*aggregate
)
5723 struct bgp_table
*table
;
5724 struct bgp_node
*top
;
5725 struct bgp_node
*rn
;
5726 struct bgp_info
*ri
;
5727 unsigned long match
;
5729 table
= bgp
->rib
[afi
][safi
];
5731 /* If routes exists below this node, generate aggregate routes. */
5732 top
= bgp_node_get(table
, p
);
5733 for (rn
= bgp_node_get(table
, p
); rn
;
5734 rn
= bgp_route_next_until(rn
, top
)) {
5735 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5739 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5740 if (BGP_INFO_HOLDDOWN(ri
))
5743 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5746 if (aggregate
->summary_only
&& ri
->extra
) {
5747 ri
->extra
->suppress
--;
5749 if (ri
->extra
->suppress
== 0) {
5751 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5758 /* If this node was suppressed, process the change. */
5760 bgp_process(bgp
, rn
, afi
, safi
);
5762 bgp_unlock_node(top
);
5765 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5766 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5768 struct bgp_node
*child
;
5769 struct bgp_node
*rn
;
5770 struct bgp_aggregate
*aggregate
;
5771 struct bgp_table
*table
;
5773 table
= bgp
->aggregate
[afi
][safi
];
5775 /* No aggregates configured. */
5776 if (bgp_table_top_nolock(table
) == NULL
)
5779 if (p
->prefixlen
== 0)
5782 if (BGP_INFO_HOLDDOWN(ri
))
5785 child
= bgp_node_get(table
, p
);
5787 /* Aggregate address configuration check. */
5788 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5789 aggregate
= bgp_aggregate_get_node_info(rn
);
5790 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5791 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5792 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5796 bgp_unlock_node(child
);
5799 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5800 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5802 struct bgp_node
*child
;
5803 struct bgp_node
*rn
;
5804 struct bgp_aggregate
*aggregate
;
5805 struct bgp_table
*table
;
5807 table
= bgp
->aggregate
[afi
][safi
];
5809 /* No aggregates configured. */
5810 if (bgp_table_top_nolock(table
) == NULL
)
5813 if (p
->prefixlen
== 0)
5816 child
= bgp_node_get(table
, p
);
5818 /* Aggregate address configuration check. */
5819 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5820 aggregate
= bgp_aggregate_get_node_info(rn
);
5821 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5822 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5823 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5827 bgp_unlock_node(child
);
5830 /* Aggregate route attribute. */
5831 #define AGGREGATE_SUMMARY_ONLY 1
5832 #define AGGREGATE_AS_SET 1
5834 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5835 afi_t afi
, safi_t safi
)
5837 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5840 struct bgp_node
*rn
;
5841 struct bgp_aggregate
*aggregate
;
5843 /* Convert string to prefix structure. */
5844 ret
= str2prefix(prefix_str
, &p
);
5846 vty_out(vty
, "Malformed prefix\n");
5847 return CMD_WARNING_CONFIG_FAILED
;
5851 /* Old configuration check. */
5852 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5855 "%% There is no aggregate-address configuration.\n");
5856 return CMD_WARNING_CONFIG_FAILED
;
5859 aggregate
= bgp_aggregate_get_node_info(rn
);
5860 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5861 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
, 0, aggregate
);
5863 /* Unlock aggregate address configuration. */
5864 bgp_aggregate_set_node_info(rn
, NULL
);
5865 bgp_aggregate_free(aggregate
);
5866 bgp_unlock_node(rn
);
5867 bgp_unlock_node(rn
);
5872 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5873 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5875 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5878 struct bgp_node
*rn
;
5879 struct bgp_aggregate
*aggregate
;
5881 /* Convert string to prefix structure. */
5882 ret
= str2prefix(prefix_str
, &p
);
5884 vty_out(vty
, "Malformed prefix\n");
5885 return CMD_WARNING_CONFIG_FAILED
;
5889 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5890 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5891 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5893 return CMD_WARNING_CONFIG_FAILED
;
5896 /* Old configuration check. */
5897 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5900 vty_out(vty
, "There is already same aggregate network.\n");
5901 /* try to remove the old entry */
5902 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5904 vty_out(vty
, "Error deleting aggregate.\n");
5905 bgp_unlock_node(rn
);
5906 return CMD_WARNING_CONFIG_FAILED
;
5910 /* Make aggregate address structure. */
5911 aggregate
= bgp_aggregate_new();
5912 aggregate
->summary_only
= summary_only
;
5913 aggregate
->as_set
= as_set
;
5914 aggregate
->safi
= safi
;
5915 bgp_aggregate_set_node_info(rn
, aggregate
);
5917 /* Aggregate address insert into BGP routing table. */
5918 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
5923 DEFUN (aggregate_address
,
5924 aggregate_address_cmd
,
5925 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5926 "Configure BGP aggregate entries\n"
5927 "Aggregate prefix\n"
5928 "Generate AS set path information\n"
5929 "Filter more specific routes from updates\n"
5930 "Filter more specific routes from updates\n"
5931 "Generate AS set path information\n")
5934 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5935 char *prefix
= argv
[idx
]->arg
;
5937 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5939 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5940 ? AGGREGATE_SUMMARY_ONLY
5943 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5944 summary_only
, as_set
);
5947 DEFUN (aggregate_address_mask
,
5948 aggregate_address_mask_cmd
,
5949 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5950 "Configure BGP aggregate entries\n"
5951 "Aggregate address\n"
5953 "Generate AS set path information\n"
5954 "Filter more specific routes from updates\n"
5955 "Filter more specific routes from updates\n"
5956 "Generate AS set path information\n")
5959 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5960 char *prefix
= argv
[idx
]->arg
;
5961 char *mask
= argv
[idx
+ 1]->arg
;
5963 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5965 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5966 ? AGGREGATE_SUMMARY_ONLY
5969 char prefix_str
[BUFSIZ
];
5970 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5973 vty_out(vty
, "%% Inconsistent address and mask\n");
5974 return CMD_WARNING_CONFIG_FAILED
;
5977 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5978 summary_only
, as_set
);
5981 DEFUN (no_aggregate_address
,
5982 no_aggregate_address_cmd
,
5983 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5985 "Configure BGP aggregate entries\n"
5986 "Aggregate prefix\n"
5987 "Generate AS set path information\n"
5988 "Filter more specific routes from updates\n"
5989 "Filter more specific routes from updates\n"
5990 "Generate AS set path information\n")
5993 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5994 char *prefix
= argv
[idx
]->arg
;
5995 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5998 DEFUN (no_aggregate_address_mask
,
5999 no_aggregate_address_mask_cmd
,
6000 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6002 "Configure BGP aggregate entries\n"
6003 "Aggregate address\n"
6005 "Generate AS set path information\n"
6006 "Filter more specific routes from updates\n"
6007 "Filter more specific routes from updates\n"
6008 "Generate AS set path information\n")
6011 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6012 char *prefix
= argv
[idx
]->arg
;
6013 char *mask
= argv
[idx
+ 1]->arg
;
6015 char prefix_str
[BUFSIZ
];
6016 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6019 vty_out(vty
, "%% Inconsistent address and mask\n");
6020 return CMD_WARNING_CONFIG_FAILED
;
6023 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6026 DEFUN (ipv6_aggregate_address
,
6027 ipv6_aggregate_address_cmd
,
6028 "aggregate-address X:X::X:X/M [summary-only]",
6029 "Configure BGP aggregate entries\n"
6030 "Aggregate prefix\n"
6031 "Filter more specific routes from updates\n")
6034 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6035 char *prefix
= argv
[idx
]->arg
;
6036 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6037 ? AGGREGATE_SUMMARY_ONLY
6039 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6043 DEFUN (no_ipv6_aggregate_address
,
6044 no_ipv6_aggregate_address_cmd
,
6045 "no aggregate-address X:X::X:X/M [summary-only]",
6047 "Configure BGP aggregate entries\n"
6048 "Aggregate prefix\n"
6049 "Filter more specific routes from updates\n")
6052 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6053 char *prefix
= argv
[idx
]->arg
;
6054 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6057 /* Redistribute route treatment. */
6058 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6059 const union g_addr
*nexthop
, ifindex_t ifindex
,
6060 enum nexthop_types_t nhtype
, uint32_t metric
,
6061 uint8_t type
, unsigned short instance
,
6064 struct bgp_info
*new;
6065 struct bgp_info
*bi
;
6066 struct bgp_info info
;
6067 struct bgp_node
*bn
;
6069 struct attr
*new_attr
;
6072 struct bgp_redist
*red
;
6074 /* Make default attribute. */
6075 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6078 case NEXTHOP_TYPE_IFINDEX
:
6080 case NEXTHOP_TYPE_IPV4
:
6081 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6082 attr
.nexthop
= nexthop
->ipv4
;
6084 case NEXTHOP_TYPE_IPV6
:
6085 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6086 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6087 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6089 case NEXTHOP_TYPE_BLACKHOLE
:
6090 switch (p
->family
) {
6092 attr
.nexthop
.s_addr
= INADDR_ANY
;
6095 memset(&attr
.mp_nexthop_global
, 0,
6096 sizeof(attr
.mp_nexthop_global
));
6097 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6102 attr
.nh_ifindex
= ifindex
;
6105 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6108 afi
= family2afi(p
->family
);
6110 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6112 struct attr attr_new
;
6114 /* Copy attribute for modification. */
6115 bgp_attr_dup(&attr_new
, &attr
);
6117 if (red
->redist_metric_flag
)
6118 attr_new
.med
= red
->redist_metric
;
6120 /* Apply route-map. */
6121 if (red
->rmap
.name
) {
6122 memset(&info
, 0, sizeof(struct bgp_info
));
6123 info
.peer
= bgp
->peer_self
;
6124 info
.attr
= &attr_new
;
6126 SET_FLAG(bgp
->peer_self
->rmap_type
,
6127 PEER_RMAP_TYPE_REDISTRIBUTE
);
6129 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6132 bgp
->peer_self
->rmap_type
= 0;
6134 if (ret
== RMAP_DENYMATCH
) {
6135 /* Free uninterned attribute. */
6136 bgp_attr_flush(&attr_new
);
6138 /* Unintern original. */
6139 aspath_unintern(&attr
.aspath
);
6140 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6145 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6146 bgp_attr_add_gshut_community(&attr_new
);
6148 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6149 SAFI_UNICAST
, p
, NULL
);
6151 new_attr
= bgp_attr_intern(&attr_new
);
6153 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6154 if (bi
->peer
== bgp
->peer_self
6155 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6159 /* Ensure the (source route) type is updated. */
6161 if (attrhash_cmp(bi
->attr
, new_attr
)
6162 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6163 bgp_attr_unintern(&new_attr
);
6164 aspath_unintern(&attr
.aspath
);
6165 bgp_unlock_node(bn
);
6168 /* The attribute is changed. */
6169 bgp_info_set_flag(bn
, bi
,
6170 BGP_INFO_ATTR_CHANGED
);
6172 /* Rewrite BGP route information. */
6173 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6174 bgp_info_restore(bn
, bi
);
6176 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6178 bgp_attr_unintern(&bi
->attr
);
6179 bi
->attr
= new_attr
;
6180 bi
->uptime
= bgp_clock();
6182 /* Process change. */
6183 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6185 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6186 bgp_unlock_node(bn
);
6187 aspath_unintern(&attr
.aspath
);
6189 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6191 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6193 vpn_leak_from_vrf_update(
6194 bgp_get_default(), bgp
, bi
);
6200 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6201 bgp
->peer_self
, new_attr
, bn
);
6202 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6204 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6205 bgp_info_add(bn
, new);
6206 bgp_unlock_node(bn
);
6207 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6209 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6210 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6212 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6216 /* Unintern original. */
6217 aspath_unintern(&attr
.aspath
);
6220 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6221 unsigned short instance
)
6224 struct bgp_node
*rn
;
6225 struct bgp_info
*ri
;
6226 struct bgp_redist
*red
;
6228 afi
= family2afi(p
->family
);
6230 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6232 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6233 SAFI_UNICAST
, p
, NULL
);
6235 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6236 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6240 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6241 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6243 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6246 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6247 bgp_info_delete(rn
, ri
);
6248 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6250 bgp_unlock_node(rn
);
6254 /* Withdraw specified route type's route. */
6255 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6256 unsigned short instance
)
6258 struct bgp_node
*rn
;
6259 struct bgp_info
*ri
;
6260 struct bgp_table
*table
;
6262 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6264 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6265 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6266 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6267 && ri
->instance
== instance
)
6271 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6272 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6274 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6277 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6279 bgp_info_delete(rn
, ri
);
6280 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6285 /* Static function to display route. */
6286 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6292 if (p
->family
== AF_INET
) {
6296 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6299 json_object_string_add(json
, "prefix",
6300 inet_ntop(p
->family
,
6303 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6305 } else if (p
->family
== AF_ETHERNET
) {
6306 prefix2str(p
, buf
, PREFIX_STRLEN
);
6307 len
= vty_out(vty
, "%s", buf
);
6308 } else if (p
->family
== AF_EVPN
) {
6312 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6315 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6316 } else if (p
->family
== AF_FLOWSPEC
) {
6317 route_vty_out_flowspec(vty
, p
, NULL
,
6319 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6320 NLRI_STRING_FORMAT_MIN
, json
);
6325 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6332 vty_out(vty
, "\n%*s", 20, " ");
6334 vty_out(vty
, "%*s", len
, " ");
6338 enum bgp_display_type
{
6342 /* Print the short form route status for a bgp_info */
6343 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6344 json_object
*json_path
)
6348 /* Route status display. */
6349 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6350 json_object_boolean_true_add(json_path
, "removed");
6352 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6353 json_object_boolean_true_add(json_path
, "stale");
6355 if (binfo
->extra
&& binfo
->extra
->suppress
)
6356 json_object_boolean_true_add(json_path
, "suppressed");
6358 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6359 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6360 json_object_boolean_true_add(json_path
, "valid");
6363 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6364 json_object_boolean_true_add(json_path
, "history");
6366 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6367 json_object_boolean_true_add(json_path
, "damped");
6369 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6370 json_object_boolean_true_add(json_path
, "bestpath");
6372 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6373 json_object_boolean_true_add(json_path
, "multipath");
6375 /* Internal route. */
6376 if ((binfo
->peer
->as
)
6377 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6378 json_object_string_add(json_path
, "pathFrom",
6381 json_object_string_add(json_path
, "pathFrom",
6387 /* Route status display. */
6388 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6390 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6392 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6394 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6395 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6401 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6403 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6405 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6407 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6412 /* Internal route. */
6413 if (binfo
->peer
&& (binfo
->peer
->as
)
6414 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6420 /* called from terminal list command */
6421 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6422 int display
, safi_t safi
, json_object
*json_paths
)
6425 json_object
*json_path
= NULL
;
6426 json_object
*json_nexthops
= NULL
;
6427 json_object
*json_nexthop_global
= NULL
;
6428 json_object
*json_nexthop_ll
= NULL
;
6429 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6430 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6433 bool nexthop_othervrf
= false;
6434 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6435 const char *nexthop_vrfname
= "Default";
6438 json_path
= json_object_new_object();
6440 /* short status lead text */
6441 route_vty_short_status_out(vty
, binfo
, json_path
);
6444 /* print prefix and mask */
6446 route_vty_out_route(p
, vty
, json_path
);
6448 vty_out(vty
, "%*s", 17, " ");
6450 route_vty_out_route(p
, vty
, json_path
);
6453 /* Print attribute */
6457 json_object_array_add(json_paths
, json_path
);
6465 * If vrf id of nexthop is different from that of prefix,
6466 * set up printable string to append
6468 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6469 const char *self
= "";
6474 nexthop_othervrf
= true;
6475 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6477 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6478 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6479 "@%s%s", VRFID_NONE_STR
, self
);
6481 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6482 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6484 if (binfo
->extra
->bgp_orig
->inst_type
!=
6485 BGP_INSTANCE_TYPE_DEFAULT
)
6487 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6489 const char *self
= "";
6494 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6498 * For ENCAP and EVPN routes, nexthop address family is not
6499 * neccessarily the same as the prefix address family.
6500 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6501 * EVPN routes are also exchanged with a MP nexthop. Currently,
6503 * is only IPv4, the value will be present in either
6505 * attr->mp_nexthop_global_in
6507 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6510 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6514 sprintf(nexthop
, "%s",
6515 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6519 sprintf(nexthop
, "%s",
6520 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6524 sprintf(nexthop
, "?");
6529 json_nexthop_global
= json_object_new_object();
6531 json_object_string_add(json_nexthop_global
, "afi",
6532 (af
== AF_INET
) ? "ip" : "ipv6");
6533 json_object_string_add(json_nexthop_global
,
6534 (af
== AF_INET
) ? "ip" : "ipv6",
6536 json_object_boolean_true_add(json_nexthop_global
,
6539 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6540 } else if (safi
== SAFI_EVPN
) {
6542 json_nexthop_global
= json_object_new_object();
6544 json_object_string_add(json_nexthop_global
, "ip",
6545 inet_ntoa(attr
->nexthop
));
6546 json_object_string_add(json_nexthop_global
, "afi",
6548 json_object_boolean_true_add(json_nexthop_global
,
6551 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6553 } else if (safi
== SAFI_FLOWSPEC
) {
6554 if (attr
->nexthop
.s_addr
!= 0) {
6556 json_nexthop_global
= json_object_new_object();
6557 json_object_string_add(
6558 json_nexthop_global
, "ip",
6559 inet_ntoa(attr
->nexthop
));
6560 json_object_string_add(json_nexthop_global
,
6562 json_object_boolean_true_add(json_nexthop_global
,
6565 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6568 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6570 json_nexthop_global
= json_object_new_object();
6572 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6573 json_object_string_add(
6574 json_nexthop_global
, "ip",
6575 inet_ntoa(attr
->mp_nexthop_global_in
));
6577 json_object_string_add(
6578 json_nexthop_global
, "ip",
6579 inet_ntoa(attr
->nexthop
));
6581 json_object_string_add(json_nexthop_global
, "afi",
6583 json_object_boolean_true_add(json_nexthop_global
,
6588 snprintf(buf
, sizeof(buf
), "%s%s",
6589 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6590 vty_out(vty
, "%-16s", buf
);
6595 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6600 json_nexthop_global
= json_object_new_object();
6601 json_object_string_add(
6602 json_nexthop_global
, "ip",
6603 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6605 json_object_string_add(json_nexthop_global
, "afi",
6607 json_object_string_add(json_nexthop_global
, "scope",
6610 /* We display both LL & GL if both have been
6612 if ((attr
->mp_nexthop_len
== 32)
6613 || (binfo
->peer
->conf_if
)) {
6614 json_nexthop_ll
= json_object_new_object();
6615 json_object_string_add(
6616 json_nexthop_ll
, "ip",
6618 &attr
->mp_nexthop_local
, buf
,
6620 json_object_string_add(json_nexthop_ll
, "afi",
6622 json_object_string_add(json_nexthop_ll
, "scope",
6625 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6626 &attr
->mp_nexthop_local
)
6628 && !attr
->mp_nexthop_prefer_global
)
6629 json_object_boolean_true_add(
6630 json_nexthop_ll
, "used");
6632 json_object_boolean_true_add(
6633 json_nexthop_global
, "used");
6635 json_object_boolean_true_add(
6636 json_nexthop_global
, "used");
6638 /* Display LL if LL/Global both in table unless
6639 * prefer-global is set */
6640 if (((attr
->mp_nexthop_len
== 32)
6641 && !attr
->mp_nexthop_prefer_global
)
6642 || (binfo
->peer
->conf_if
)) {
6643 if (binfo
->peer
->conf_if
) {
6644 len
= vty_out(vty
, "%s",
6645 binfo
->peer
->conf_if
);
6646 len
= 16 - len
; /* len of IPv6
6652 vty_out(vty
, "\n%*s", 36, " ");
6654 vty_out(vty
, "%*s", len
, " ");
6660 &attr
->mp_nexthop_local
,
6666 vty_out(vty
, "\n%*s", 36, " ");
6668 vty_out(vty
, "%*s", len
, " ");
6674 &attr
->mp_nexthop_global
, buf
,
6680 vty_out(vty
, "\n%*s", 36, " ");
6682 vty_out(vty
, "%*s", len
, " ");
6688 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6690 json_object_int_add(json_path
, "med", attr
->med
);
6692 vty_out(vty
, "%10u", attr
->med
);
6693 else if (!json_paths
)
6697 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6699 json_object_int_add(json_path
, "localpref",
6702 vty_out(vty
, "%7u", attr
->local_pref
);
6703 else if (!json_paths
)
6707 json_object_int_add(json_path
, "weight", attr
->weight
);
6709 vty_out(vty
, "%7u ", attr
->weight
);
6713 json_object_string_add(
6714 json_path
, "peerId",
6715 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6721 json_object_string_add(json_path
, "aspath",
6724 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6729 json_object_string_add(json_path
, "origin",
6730 bgp_origin_long_str
[attr
->origin
]);
6732 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6736 json_object_boolean_true_add(json_path
,
6737 "announceNexthopSelf");
6738 if (nexthop_othervrf
) {
6739 json_object_string_add(json_path
, "nhVrfName",
6742 json_object_int_add(json_path
, "nhVrfId",
6743 ((nexthop_vrfid
== VRF_UNKNOWN
)
6745 : (int)nexthop_vrfid
));
6750 if (json_nexthop_global
|| json_nexthop_ll
) {
6751 json_nexthops
= json_object_new_array();
6753 if (json_nexthop_global
)
6754 json_object_array_add(json_nexthops
,
6755 json_nexthop_global
);
6757 if (json_nexthop_ll
)
6758 json_object_array_add(json_nexthops
,
6761 json_object_object_add(json_path
, "nexthops",
6765 json_object_array_add(json_paths
, json_path
);
6769 /* prints an additional line, indented, with VNC info, if
6771 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6772 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6777 /* called from terminal list command */
6778 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6779 safi_t safi
, bool use_json
, json_object
*json_ar
)
6781 json_object
*json_status
= NULL
;
6782 json_object
*json_net
= NULL
;
6784 /* Route status display. */
6786 json_status
= json_object_new_object();
6787 json_net
= json_object_new_object();
6794 /* print prefix and mask */
6796 json_object_string_add(
6797 json_net
, "addrPrefix",
6798 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6800 route_vty_out_route(p
, vty
, NULL
);
6802 /* Print attribute */
6805 if (p
->family
== AF_INET
6806 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6807 || safi
== SAFI_EVPN
6808 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6809 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6810 || safi
== SAFI_EVPN
)
6811 json_object_string_add(
6812 json_net
, "nextHop",
6814 attr
->mp_nexthop_global_in
));
6816 json_object_string_add(
6817 json_net
, "nextHop",
6818 inet_ntoa(attr
->nexthop
));
6819 } else if (p
->family
== AF_INET6
6820 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6823 json_object_string_add(
6824 json_net
, "netHopGloabal",
6826 &attr
->mp_nexthop_global
, buf
,
6831 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6832 json_object_int_add(json_net
, "metric",
6835 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6836 json_object_int_add(json_net
, "localPref",
6839 json_object_int_add(json_net
, "weight", attr
->weight
);
6843 json_object_string_add(json_net
, "asPath",
6847 json_object_string_add(json_net
, "bgpOriginCode",
6848 bgp_origin_str
[attr
->origin
]);
6850 if (p
->family
== AF_INET
6851 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6852 || safi
== SAFI_EVPN
6853 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6854 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6855 || safi
== SAFI_EVPN
)
6856 vty_out(vty
, "%-16s",
6858 attr
->mp_nexthop_global_in
));
6860 vty_out(vty
, "%-16s",
6861 inet_ntoa(attr
->nexthop
));
6862 } else if (p
->family
== AF_INET6
6863 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6870 &attr
->mp_nexthop_global
, buf
,
6874 vty_out(vty
, "\n%*s", 36, " ");
6876 vty_out(vty
, "%*s", len
, " ");
6879 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6880 vty_out(vty
, "%10u", attr
->med
);
6884 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6885 vty_out(vty
, "%7u", attr
->local_pref
);
6889 vty_out(vty
, "%7u ", attr
->weight
);
6893 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6896 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6900 json_object_boolean_true_add(json_status
, "*");
6901 json_object_boolean_true_add(json_status
, ">");
6902 json_object_object_add(json_net
, "appliedStatusSymbols",
6904 char buf_cut
[BUFSIZ
];
6905 json_object_object_add(
6907 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6913 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6914 struct bgp_info
*binfo
, int display
, safi_t safi
,
6917 json_object
*json_out
= NULL
;
6919 mpls_label_t label
= MPLS_INVALID_LABEL
;
6925 json_out
= json_object_new_object();
6927 /* short status lead text */
6928 route_vty_short_status_out(vty
, binfo
, json_out
);
6930 /* print prefix and mask */
6933 route_vty_out_route(p
, vty
, NULL
);
6935 vty_out(vty
, "%*s", 17, " ");
6938 /* Print attribute */
6941 if (((p
->family
== AF_INET
)
6942 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6943 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6944 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6945 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6946 || safi
== SAFI_EVPN
) {
6948 json_object_string_add(
6949 json_out
, "mpNexthopGlobalIn",
6951 attr
->mp_nexthop_global_in
));
6953 vty_out(vty
, "%-16s",
6955 attr
->mp_nexthop_global_in
));
6958 json_object_string_add(
6959 json_out
, "nexthop",
6960 inet_ntoa(attr
->nexthop
));
6962 vty_out(vty
, "%-16s",
6963 inet_ntoa(attr
->nexthop
));
6965 } else if (((p
->family
== AF_INET6
)
6966 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6967 || (safi
== SAFI_EVPN
6968 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6969 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6973 if (attr
->mp_nexthop_len
6974 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6976 json_object_string_add(
6977 json_out
, "mpNexthopGlobalIn",
6980 &attr
->mp_nexthop_global
,
6981 buf_a
, sizeof(buf_a
)));
6986 &attr
->mp_nexthop_global
,
6987 buf_a
, sizeof(buf_a
)));
6988 } else if (attr
->mp_nexthop_len
6989 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6992 &attr
->mp_nexthop_global
,
6993 buf_a
, sizeof(buf_a
));
6995 &attr
->mp_nexthop_local
,
6996 buf_b
, sizeof(buf_b
));
6997 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6998 json_object_string_add(
7000 "mpNexthopGlobalLocal", buf_c
);
7002 vty_out(vty
, "%s(%s)",
7005 &attr
->mp_nexthop_global
,
7006 buf_a
, sizeof(buf_a
)),
7009 &attr
->mp_nexthop_local
,
7010 buf_b
, sizeof(buf_b
)));
7015 label
= decode_label(&binfo
->extra
->label
[0]);
7017 if (bgp_is_valid_label(&label
)) {
7019 json_object_int_add(json_out
, "notag", label
);
7020 json_object_array_add(json
, json_out
);
7022 vty_out(vty
, "notag/%d", label
);
7028 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7029 struct bgp_info
*binfo
, int display
,
7030 json_object
*json_paths
)
7034 json_object
*json_path
= NULL
;
7037 json_path
= json_object_new_object();
7042 /* short status lead text */
7043 route_vty_short_status_out(vty
, binfo
, json_path
);
7045 /* print prefix and mask */
7047 route_vty_out_route(p
, vty
, NULL
);
7049 vty_out(vty
, "%*s", 17, " ");
7051 /* Print attribute */
7055 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7059 vty_out(vty
, "%-16s",
7060 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7064 vty_out(vty
, "%s(%s)",
7065 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7067 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7074 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7076 vty_out(vty
, "%s", str
);
7077 XFREE(MTYPE_TMP
, str
);
7079 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7081 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7082 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7085 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7088 if (attr
->ecommunity
) {
7090 struct ecommunity_val
*routermac
= ecommunity_lookup(
7091 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7092 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7094 mac
= ecom_mac2str((char *)routermac
->val
);
7096 vty_out(vty
, "/%s", (char *)mac
);
7097 XFREE(MTYPE_TMP
, mac
);
7105 /* dampening route */
7106 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7107 struct bgp_info
*binfo
, int display
, safi_t safi
,
7108 bool use_json
, json_object
*json
)
7112 char timebuf
[BGP_UPTIME_LEN
];
7114 /* short status lead text */
7115 route_vty_short_status_out(vty
, binfo
, json
);
7117 /* print prefix and mask */
7120 route_vty_out_route(p
, vty
, NULL
);
7122 vty_out(vty
, "%*s", 17, " ");
7125 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7129 vty_out(vty
, "\n%*s", 34, " ");
7132 json_object_int_add(json
, "peerHost", len
);
7134 vty_out(vty
, "%*s", len
, " ");
7138 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7141 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7145 /* Print attribute */
7151 json_object_string_add(json
, "asPath",
7154 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7159 json_object_string_add(json
, "origin",
7160 bgp_origin_str
[attr
->origin
]);
7162 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7169 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7170 struct bgp_info
*binfo
, int display
, safi_t safi
,
7171 bool use_json
, json_object
*json
)
7174 struct bgp_damp_info
*bdi
;
7175 char timebuf
[BGP_UPTIME_LEN
];
7181 bdi
= binfo
->extra
->damp_info
;
7183 /* short status lead text */
7184 route_vty_short_status_out(vty
, binfo
, json
);
7186 /* print prefix and mask */
7189 route_vty_out_route(p
, vty
, NULL
);
7191 vty_out(vty
, "%*s", 17, " ");
7194 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7198 vty_out(vty
, "\n%*s", 33, " ");
7201 json_object_int_add(json
, "peerHost", len
);
7203 vty_out(vty
, "%*s", len
, " ");
7206 len
= vty_out(vty
, "%d", bdi
->flap
);
7213 json_object_int_add(json
, "bdiFlap", len
);
7215 vty_out(vty
, "%*s", len
, " ");
7219 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7222 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7223 BGP_UPTIME_LEN
, 0, NULL
));
7225 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7226 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7228 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7229 BGP_UPTIME_LEN
, use_json
, json
);
7232 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7237 vty_out(vty
, "%*s ", 8, " ");
7240 /* Print attribute */
7246 json_object_string_add(json
, "asPath",
7249 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7254 json_object_string_add(json
, "origin",
7255 bgp_origin_str
[attr
->origin
]);
7257 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7263 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7264 int *first
, const char *header
,
7265 json_object
*json_adv_to
)
7267 char buf1
[INET6_ADDRSTRLEN
];
7268 json_object
*json_peer
= NULL
;
7271 /* 'advertised-to' is a dictionary of peers we have advertised
7273 * prefix too. The key is the peer's IP or swpX, the value is
7275 * hostname if we know it and "" if not.
7277 json_peer
= json_object_new_object();
7280 json_object_string_add(json_peer
, "hostname",
7284 json_object_object_add(json_adv_to
, peer
->conf_if
,
7287 json_object_object_add(
7289 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7293 vty_out(vty
, "%s", header
);
7298 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7300 vty_out(vty
, " %s(%s)", peer
->hostname
,
7303 vty_out(vty
, " %s(%s)", peer
->hostname
,
7304 sockunion2str(&peer
->su
, buf1
,
7308 vty_out(vty
, " %s", peer
->conf_if
);
7311 sockunion2str(&peer
->su
, buf1
,
7317 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7318 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7319 json_object
*json_paths
)
7321 char buf
[INET6_ADDRSTRLEN
];
7323 char buf2
[EVPN_ROUTE_STRLEN
];
7325 int sockunion_vty_out(struct vty
*, union sockunion
*);
7327 json_object
*json_bestpath
= NULL
;
7328 json_object
*json_cluster_list
= NULL
;
7329 json_object
*json_cluster_list_list
= NULL
;
7330 json_object
*json_ext_community
= NULL
;
7331 json_object
*json_last_update
= NULL
;
7332 json_object
*json_pmsi
= NULL
;
7333 json_object
*json_nexthop_global
= NULL
;
7334 json_object
*json_nexthop_ll
= NULL
;
7335 json_object
*json_nexthops
= NULL
;
7336 json_object
*json_path
= NULL
;
7337 json_object
*json_peer
= NULL
;
7338 json_object
*json_string
= NULL
;
7339 json_object
*json_adv_to
= NULL
;
7341 struct listnode
*node
, *nnode
;
7343 int addpath_capable
;
7345 unsigned int first_as
;
7346 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7351 json_path
= json_object_new_object();
7352 json_peer
= json_object_new_object();
7353 json_nexthop_global
= json_object_new_object();
7356 if (!json_paths
&& safi
== SAFI_EVPN
) {
7359 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7360 vty_out(vty
, " Route %s", buf2
);
7362 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7363 bgp_evpn_label2str(binfo
->extra
->label
,
7364 binfo
->extra
->num_labels
, tag_buf
,
7366 vty_out(vty
, " VNI %s", tag_buf
);
7369 if (binfo
->extra
&& binfo
->extra
->parent
) {
7370 struct bgp_info
*parent_ri
;
7371 struct bgp_node
*rn
, *prn
;
7373 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7374 rn
= parent_ri
->net
;
7375 if (rn
&& rn
->prn
) {
7377 vty_out(vty
, " Imported from %s:%s\n",
7379 (struct prefix_rd
*)&prn
->p
,
7380 buf1
, sizeof(buf1
)),
7389 /* Line1 display AS-path, Aggregator */
7392 if (!attr
->aspath
->json
)
7393 aspath_str_update(attr
->aspath
, true);
7394 json_object_lock(attr
->aspath
->json
);
7395 json_object_object_add(json_path
, "aspath",
7396 attr
->aspath
->json
);
7398 if (attr
->aspath
->segments
)
7399 aspath_print_vty(vty
, " %s",
7402 vty_out(vty
, " Local");
7406 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7408 json_object_boolean_true_add(json_path
,
7411 vty_out(vty
, ", (removed)");
7414 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7416 json_object_boolean_true_add(json_path
,
7419 vty_out(vty
, ", (stale)");
7422 if (CHECK_FLAG(attr
->flag
,
7423 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7425 json_object_int_add(json_path
, "aggregatorAs",
7426 attr
->aggregator_as
);
7427 json_object_string_add(
7428 json_path
, "aggregatorId",
7429 inet_ntoa(attr
->aggregator_addr
));
7431 vty_out(vty
, ", (aggregated by %u %s)",
7432 attr
->aggregator_as
,
7433 inet_ntoa(attr
->aggregator_addr
));
7437 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7438 PEER_FLAG_REFLECTOR_CLIENT
)) {
7440 json_object_boolean_true_add(
7441 json_path
, "rxedFromRrClient");
7443 vty_out(vty
, ", (Received from a RR-client)");
7446 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7447 PEER_FLAG_RSERVER_CLIENT
)) {
7449 json_object_boolean_true_add(
7450 json_path
, "rxedFromRsClient");
7452 vty_out(vty
, ", (Received from a RS-client)");
7455 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7457 json_object_boolean_true_add(
7458 json_path
, "dampeningHistoryEntry");
7460 vty_out(vty
, ", (history entry)");
7461 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7463 json_object_boolean_true_add(
7464 json_path
, "dampeningSuppressed");
7466 vty_out(vty
, ", (suppressed due to dampening)");
7472 /* Line2 display Next-hop, Neighbor, Router-id */
7473 /* Display the nexthop */
7474 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7475 || p
->family
== AF_EVPN
)
7476 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7477 || safi
== SAFI_EVPN
7478 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7479 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7480 || safi
== SAFI_EVPN
) {
7482 json_object_string_add(
7483 json_nexthop_global
, "ip",
7485 attr
->mp_nexthop_global_in
));
7489 attr
->mp_nexthop_global_in
));
7492 json_object_string_add(
7493 json_nexthop_global
, "ip",
7494 inet_ntoa(attr
->nexthop
));
7497 inet_ntoa(attr
->nexthop
));
7501 json_object_string_add(json_nexthop_global
,
7505 json_object_string_add(
7506 json_nexthop_global
, "ip",
7508 &attr
->mp_nexthop_global
, buf
,
7510 json_object_string_add(json_nexthop_global
,
7512 json_object_string_add(json_nexthop_global
,
7517 &attr
->mp_nexthop_global
, buf
,
7522 /* Display the IGP cost or 'inaccessible' */
7523 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7525 json_object_boolean_false_add(
7526 json_nexthop_global
, "accessible");
7528 vty_out(vty
, " (inaccessible)");
7530 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7532 json_object_int_add(
7533 json_nexthop_global
, "metric",
7534 binfo
->extra
->igpmetric
);
7536 vty_out(vty
, " (metric %u)",
7537 binfo
->extra
->igpmetric
);
7540 /* IGP cost is 0, display this only for json */
7543 json_object_int_add(json_nexthop_global
,
7548 json_object_boolean_true_add(
7549 json_nexthop_global
, "accessible");
7552 /* Display peer "from" output */
7553 /* This path was originated locally */
7554 if (binfo
->peer
== bgp
->peer_self
) {
7556 if (safi
== SAFI_EVPN
7557 || (p
->family
== AF_INET
7558 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7560 json_object_string_add(
7561 json_peer
, "peerId", "0.0.0.0");
7563 vty_out(vty
, " from 0.0.0.0 ");
7566 json_object_string_add(json_peer
,
7569 vty_out(vty
, " from :: ");
7573 json_object_string_add(
7574 json_peer
, "routerId",
7575 inet_ntoa(bgp
->router_id
));
7577 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7580 /* We RXed this path from one of our peers */
7584 json_object_string_add(
7585 json_peer
, "peerId",
7586 sockunion2str(&binfo
->peer
->su
, buf
,
7588 json_object_string_add(
7589 json_peer
, "routerId",
7591 &binfo
->peer
->remote_id
, buf1
,
7594 if (binfo
->peer
->hostname
)
7595 json_object_string_add(
7596 json_peer
, "hostname",
7597 binfo
->peer
->hostname
);
7599 if (binfo
->peer
->domainname
)
7600 json_object_string_add(
7601 json_peer
, "domainname",
7602 binfo
->peer
->domainname
);
7604 if (binfo
->peer
->conf_if
)
7605 json_object_string_add(
7606 json_peer
, "interface",
7607 binfo
->peer
->conf_if
);
7609 if (binfo
->peer
->conf_if
) {
7610 if (binfo
->peer
->hostname
7613 BGP_FLAG_SHOW_HOSTNAME
))
7614 vty_out(vty
, " from %s(%s)",
7615 binfo
->peer
->hostname
,
7616 binfo
->peer
->conf_if
);
7618 vty_out(vty
, " from %s",
7619 binfo
->peer
->conf_if
);
7621 if (binfo
->peer
->hostname
7624 BGP_FLAG_SHOW_HOSTNAME
))
7625 vty_out(vty
, " from %s(%s)",
7626 binfo
->peer
->hostname
,
7629 vty_out(vty
, " from %s",
7638 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7639 vty_out(vty
, " (%s)",
7640 inet_ntoa(attr
->originator_id
));
7642 vty_out(vty
, " (%s)",
7645 &binfo
->peer
->remote_id
,
7646 buf1
, sizeof(buf1
)));
7651 * Note when vrfid of nexthop is different from that of prefix
7653 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7654 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7659 if (binfo
->extra
->bgp_orig
->inst_type
==
7660 BGP_INSTANCE_TYPE_DEFAULT
)
7664 vn
= binfo
->extra
->bgp_orig
->name
;
7666 json_object_string_add(json_path
, "nhVrfName",
7669 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7670 json_object_int_add(json_path
,
7673 json_object_int_add(json_path
,
7674 "nhVrfId", (int)nexthop_vrfid
);
7677 if (nexthop_vrfid
== VRF_UNKNOWN
)
7678 vty_out(vty
, " vrf ?");
7680 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7686 json_object_boolean_true_add(json_path
,
7687 "announceNexthopSelf");
7689 vty_out(vty
, " announce-nh-self");
7696 /* display the link-local nexthop */
7697 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7699 json_nexthop_ll
= json_object_new_object();
7700 json_object_string_add(
7701 json_nexthop_ll
, "ip",
7703 &attr
->mp_nexthop_local
, buf
,
7705 json_object_string_add(json_nexthop_ll
, "afi",
7707 json_object_string_add(json_nexthop_ll
, "scope",
7710 json_object_boolean_true_add(json_nexthop_ll
,
7713 if (!attr
->mp_nexthop_prefer_global
)
7714 json_object_boolean_true_add(
7715 json_nexthop_ll
, "used");
7717 json_object_boolean_true_add(
7718 json_nexthop_global
, "used");
7720 vty_out(vty
, " (%s) %s\n",
7722 &attr
->mp_nexthop_local
, buf
,
7724 attr
->mp_nexthop_prefer_global
7729 /* If we do not have a link-local nexthop then we must flag the
7733 json_object_boolean_true_add(
7734 json_nexthop_global
, "used");
7737 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7738 * Int/Ext/Local, Atomic, best */
7740 json_object_string_add(
7741 json_path
, "origin",
7742 bgp_origin_long_str
[attr
->origin
]);
7744 vty_out(vty
, " Origin %s",
7745 bgp_origin_long_str
[attr
->origin
]);
7747 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7749 json_object_int_add(json_path
, "med",
7752 vty_out(vty
, ", metric %u", attr
->med
);
7755 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7757 json_object_int_add(json_path
, "localpref",
7760 vty_out(vty
, ", localpref %u",
7764 if (attr
->weight
!= 0) {
7766 json_object_int_add(json_path
, "weight",
7769 vty_out(vty
, ", weight %u", attr
->weight
);
7772 if (attr
->tag
!= 0) {
7774 json_object_int_add(json_path
, "tag",
7777 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7781 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7783 json_object_boolean_false_add(json_path
,
7786 vty_out(vty
, ", invalid");
7787 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7789 json_object_boolean_true_add(json_path
,
7792 vty_out(vty
, ", valid");
7795 if (binfo
->peer
!= bgp
->peer_self
) {
7796 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7797 if (CHECK_FLAG(bgp
->config
,
7798 BGP_CONFIG_CONFEDERATION
)) {
7800 json_object_string_add(
7805 ", confed-internal");
7808 json_object_string_add(
7812 vty_out(vty
, ", internal");
7815 if (bgp_confederation_peers_check(
7816 bgp
, binfo
->peer
->as
)) {
7818 json_object_string_add(
7823 ", confed-external");
7826 json_object_string_add(
7830 vty_out(vty
, ", external");
7833 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7835 json_object_boolean_true_add(json_path
,
7837 json_object_boolean_true_add(json_path
,
7840 vty_out(vty
, ", aggregated, local");
7842 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7844 json_object_boolean_true_add(json_path
,
7847 vty_out(vty
, ", sourced");
7850 json_object_boolean_true_add(json_path
,
7852 json_object_boolean_true_add(json_path
,
7855 vty_out(vty
, ", sourced, local");
7859 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7861 json_object_boolean_true_add(json_path
,
7864 vty_out(vty
, ", atomic-aggregate");
7867 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7868 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7869 && bgp_info_mpath_count(binfo
))) {
7871 json_object_boolean_true_add(json_path
,
7874 vty_out(vty
, ", multipath");
7877 // Mark the bestpath(s)
7878 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7879 first_as
= aspath_get_first_as(attr
->aspath
);
7884 json_object_new_object();
7885 json_object_int_add(json_bestpath
,
7886 "bestpathFromAs", first_as
);
7889 vty_out(vty
, ", bestpath-from-AS %u",
7893 ", bestpath-from-AS Local");
7897 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7901 json_object_new_object();
7902 json_object_boolean_true_add(json_bestpath
,
7905 vty_out(vty
, ", best");
7909 json_object_object_add(json_path
, "bestpath",
7915 /* Line 4 display Community */
7916 if (attr
->community
) {
7918 if (!attr
->community
->json
)
7919 community_str(attr
->community
, true);
7920 json_object_lock(attr
->community
->json
);
7921 json_object_object_add(json_path
, "community",
7922 attr
->community
->json
);
7924 vty_out(vty
, " Community: %s\n",
7925 attr
->community
->str
);
7929 /* Line 5 display Extended-community */
7930 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7932 json_ext_community
= json_object_new_object();
7933 json_object_string_add(json_ext_community
,
7935 attr
->ecommunity
->str
);
7936 json_object_object_add(json_path
,
7937 "extendedCommunity",
7938 json_ext_community
);
7940 vty_out(vty
, " Extended Community: %s\n",
7941 attr
->ecommunity
->str
);
7945 /* Line 6 display Large community */
7946 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7948 if (!attr
->lcommunity
->json
)
7949 lcommunity_str(attr
->lcommunity
, true);
7950 json_object_lock(attr
->lcommunity
->json
);
7951 json_object_object_add(json_path
,
7953 attr
->lcommunity
->json
);
7955 vty_out(vty
, " Large Community: %s\n",
7956 attr
->lcommunity
->str
);
7960 /* Line 7 display Originator, Cluster-id */
7961 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7962 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7964 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7966 json_object_string_add(
7967 json_path
, "originatorId",
7968 inet_ntoa(attr
->originator_id
));
7970 vty_out(vty
, " Originator: %s",
7971 inet_ntoa(attr
->originator_id
));
7974 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7979 json_object_new_object();
7980 json_cluster_list_list
=
7981 json_object_new_array();
7984 i
< attr
->cluster
->length
/ 4;
7986 json_string
= json_object_new_string(
7990 json_object_array_add(
7991 json_cluster_list_list
,
7995 /* struct cluster_list does not have
7997 * aspath and community do. Add this
8000 json_object_string_add(json_cluster_list,
8001 "string", attr->cluster->str);
8003 json_object_object_add(
8004 json_cluster_list
, "list",
8005 json_cluster_list_list
);
8006 json_object_object_add(
8007 json_path
, "clusterList",
8010 vty_out(vty
, ", Cluster list: ");
8013 i
< attr
->cluster
->length
/ 4;
8027 if (binfo
->extra
&& binfo
->extra
->damp_info
)
8028 bgp_damp_info_vty(vty
, binfo
, json_path
);
8031 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8032 && safi
!= SAFI_EVPN
) {
8033 mpls_label_t label
=
8034 label_pton(&binfo
->extra
->label
[0]);
8036 json_object_int_add(json_path
, "remoteLabel",
8039 vty_out(vty
, " Remote label: %d\n", label
);
8043 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8045 json_object_int_add(json_path
, "labelIndex",
8048 vty_out(vty
, " Label Index: %d\n",
8052 /* Line 8 display Addpath IDs */
8053 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8055 json_object_int_add(json_path
, "addpathRxId",
8056 binfo
->addpath_rx_id
);
8057 json_object_int_add(json_path
, "addpathTxId",
8058 binfo
->addpath_tx_id
);
8060 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8061 binfo
->addpath_rx_id
,
8062 binfo
->addpath_tx_id
);
8066 /* If we used addpath to TX a non-bestpath we need to display
8067 * "Advertised to" on a path-by-path basis */
8068 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8071 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8073 bgp_addpath_encode_tx(peer
, afi
, safi
);
8074 has_adj
= bgp_adj_out_lookup(
8075 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8077 if ((addpath_capable
&& has_adj
)
8078 || (!addpath_capable
&& has_adj
8079 && CHECK_FLAG(binfo
->flags
,
8080 BGP_INFO_SELECTED
))) {
8081 if (json_path
&& !json_adv_to
)
8083 json_object_new_object();
8085 route_vty_out_advertised_to(
8094 json_object_object_add(json_path
,
8105 /* Line 9 display Uptime */
8106 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8108 json_last_update
= json_object_new_object();
8109 json_object_int_add(json_last_update
, "epoch", tbuf
);
8110 json_object_string_add(json_last_update
, "string",
8112 json_object_object_add(json_path
, "lastUpdate",
8115 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8117 /* Line 10 display PMSI tunnel attribute, if present */
8118 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8119 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8120 attr
->pmsi_tnl_type
,
8121 PMSI_TNLTYPE_STR_DEFAULT
);
8124 json_pmsi
= json_object_new_object();
8125 json_object_string_add(json_pmsi
,
8127 json_object_object_add(json_path
, "pmsi",
8130 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8136 /* We've constructed the json object for this path, add it to the json
8140 if (json_nexthop_global
|| json_nexthop_ll
) {
8141 json_nexthops
= json_object_new_array();
8143 if (json_nexthop_global
)
8144 json_object_array_add(json_nexthops
,
8145 json_nexthop_global
);
8147 if (json_nexthop_ll
)
8148 json_object_array_add(json_nexthops
,
8151 json_object_object_add(json_path
, "nexthops",
8155 json_object_object_add(json_path
, "peer", json_peer
);
8156 json_object_array_add(json_paths
, json_path
);
8161 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8162 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8163 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8165 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8166 const char *prefix_list_str
, afi_t afi
,
8167 safi_t safi
, enum bgp_show_type type
);
8168 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8169 const char *filter
, afi_t afi
, safi_t safi
,
8170 enum bgp_show_type type
);
8171 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8172 const char *rmap_str
, afi_t afi
, safi_t safi
,
8173 enum bgp_show_type type
);
8174 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8175 const char *com
, int exact
, afi_t afi
,
8177 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8178 const char *prefix
, afi_t afi
, safi_t safi
,
8179 enum bgp_show_type type
);
8180 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8181 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8182 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8183 const char *comstr
, int exact
, afi_t afi
,
8184 safi_t safi
, bool use_json
);
8187 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8188 struct bgp_table
*table
, enum bgp_show_type type
,
8189 void *output_arg
, bool use_json
, char *rd
,
8190 int is_last
, unsigned long *output_cum
,
8191 unsigned long *total_cum
,
8192 unsigned long *json_header_depth
)
8194 struct bgp_info
*ri
;
8195 struct bgp_node
*rn
;
8198 unsigned long output_count
= 0;
8199 unsigned long total_count
= 0;
8203 json_object
*json_paths
= NULL
;
8206 if (output_cum
&& *output_cum
!= 0)
8209 if (use_json
&& !*json_header_depth
) {
8211 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8212 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8213 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8214 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8216 table
->version
, inet_ntoa(bgp
->router_id
));
8217 *json_header_depth
= 2;
8219 vty_out(vty
, " \"routeDistinguishers\" : {");
8220 ++*json_header_depth
;
8224 if (use_json
&& rd
) {
8225 vty_out(vty
, " \"%s\" : { ", rd
);
8228 /* Start processing of routes. */
8229 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8230 if (rn
->info
== NULL
)
8235 json_paths
= json_object_new_array();
8239 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8241 if (type
== bgp_show_type_flap_statistics
8242 || type
== bgp_show_type_flap_neighbor
8243 || type
== bgp_show_type_dampend_paths
8244 || type
== bgp_show_type_damp_neighbor
) {
8245 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8248 if (type
== bgp_show_type_regexp
) {
8249 regex_t
*regex
= output_arg
;
8251 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8255 if (type
== bgp_show_type_prefix_list
) {
8256 struct prefix_list
*plist
= output_arg
;
8258 if (prefix_list_apply(plist
, &rn
->p
)
8262 if (type
== bgp_show_type_filter_list
) {
8263 struct as_list
*as_list
= output_arg
;
8265 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8266 != AS_FILTER_PERMIT
)
8269 if (type
== bgp_show_type_route_map
) {
8270 struct route_map
*rmap
= output_arg
;
8271 struct bgp_info binfo
;
8272 struct attr dummy_attr
;
8275 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8277 binfo
.peer
= ri
->peer
;
8278 binfo
.attr
= &dummy_attr
;
8280 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8282 if (ret
== RMAP_DENYMATCH
)
8285 if (type
== bgp_show_type_neighbor
8286 || type
== bgp_show_type_flap_neighbor
8287 || type
== bgp_show_type_damp_neighbor
) {
8288 union sockunion
*su
= output_arg
;
8290 if (ri
->peer
== NULL
8291 || ri
->peer
->su_remote
== NULL
8292 || !sockunion_same(ri
->peer
->su_remote
, su
))
8295 if (type
== bgp_show_type_cidr_only
) {
8296 uint32_t destination
;
8298 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8299 if (IN_CLASSC(destination
)
8300 && rn
->p
.prefixlen
== 24)
8302 if (IN_CLASSB(destination
)
8303 && rn
->p
.prefixlen
== 16)
8305 if (IN_CLASSA(destination
)
8306 && rn
->p
.prefixlen
== 8)
8309 if (type
== bgp_show_type_prefix_longer
) {
8311 if (!prefix_match(p
, &rn
->p
))
8314 if (type
== bgp_show_type_community_all
) {
8315 if (!ri
->attr
->community
)
8318 if (type
== bgp_show_type_community
) {
8319 struct community
*com
= output_arg
;
8321 if (!ri
->attr
->community
8322 || !community_match(ri
->attr
->community
,
8326 if (type
== bgp_show_type_community_exact
) {
8327 struct community
*com
= output_arg
;
8329 if (!ri
->attr
->community
8330 || !community_cmp(ri
->attr
->community
, com
))
8333 if (type
== bgp_show_type_community_list
) {
8334 struct community_list
*list
= output_arg
;
8336 if (!community_list_match(ri
->attr
->community
,
8340 if (type
== bgp_show_type_community_list_exact
) {
8341 struct community_list
*list
= output_arg
;
8343 if (!community_list_exact_match(
8344 ri
->attr
->community
, list
))
8347 if (type
== bgp_show_type_lcommunity
) {
8348 struct lcommunity
*lcom
= output_arg
;
8350 if (!ri
->attr
->lcommunity
8351 || !lcommunity_match(ri
->attr
->lcommunity
,
8355 if (type
== bgp_show_type_lcommunity_list
) {
8356 struct community_list
*list
= output_arg
;
8358 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8362 if (type
== bgp_show_type_lcommunity_all
) {
8363 if (!ri
->attr
->lcommunity
)
8366 if (type
== bgp_show_type_dampend_paths
8367 || type
== bgp_show_type_damp_neighbor
) {
8368 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8369 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8373 if (!use_json
&& header
) {
8374 vty_out(vty
, "BGP table version is %" PRIu64
8375 ", local router ID is %s, vrf id ",
8377 inet_ntoa(bgp
->router_id
));
8378 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8379 vty_out(vty
, "%s", VRFID_NONE_STR
);
8381 vty_out(vty
, "%u", bgp
->vrf_id
);
8383 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8384 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8385 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8386 if (type
== bgp_show_type_dampend_paths
8387 || type
== bgp_show_type_damp_neighbor
)
8388 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8389 else if (type
== bgp_show_type_flap_statistics
8390 || type
== bgp_show_type_flap_neighbor
)
8391 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8393 vty_out(vty
, BGP_SHOW_HEADER
);
8396 if (rd
!= NULL
&& !display
&& !output_count
) {
8399 "Route Distinguisher: %s\n",
8402 if (type
== bgp_show_type_dampend_paths
8403 || type
== bgp_show_type_damp_neighbor
)
8404 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8405 safi
, use_json
, json_paths
);
8406 else if (type
== bgp_show_type_flap_statistics
8407 || type
== bgp_show_type_flap_neighbor
)
8408 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8409 safi
, use_json
, json_paths
);
8411 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8422 sprintf(buf2
, "%s/%d",
8423 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8426 vty_out(vty
, "\"%s\": ", buf2
);
8428 vty_out(vty
, ",\"%s\": ", buf2
);
8431 json_object_to_json_string(json_paths
));
8432 json_object_free(json_paths
);
8439 output_count
+= *output_cum
;
8440 *output_cum
= output_count
;
8443 total_count
+= *total_cum
;
8444 *total_cum
= total_count
;
8448 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8452 for (i
= 0; i
< *json_header_depth
; ++i
)
8453 vty_out(vty
, " } ");
8457 /* No route is displayed */
8458 if (output_count
== 0) {
8459 if (type
== bgp_show_type_normal
)
8461 "No BGP prefixes displayed, %ld exist\n",
8465 "\nDisplayed %ld routes and %ld total paths\n",
8466 output_count
, total_count
);
8473 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8474 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8475 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8477 struct bgp_node
*rn
, *next
;
8478 unsigned long output_cum
= 0;
8479 unsigned long total_cum
= 0;
8480 unsigned long json_header_depth
= 0;
8483 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8485 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8486 next
= bgp_route_next(rn
);
8487 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8489 if (rn
->info
!= NULL
) {
8490 struct prefix_rd prd
;
8491 char rd
[RD_ADDRSTRLEN
];
8493 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8494 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8495 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8496 output_arg
, use_json
, rd
, next
== NULL
,
8497 &output_cum
, &total_cum
,
8498 &json_header_depth
);
8504 if (output_cum
== 0)
8505 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8509 "\nDisplayed %ld routes and %ld total paths\n",
8510 output_cum
, total_cum
);
8514 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8515 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8517 struct bgp_table
*table
;
8518 unsigned long json_header_depth
= 0;
8521 bgp
= bgp_get_default();
8526 vty_out(vty
, "No BGP process is configured\n");
8528 vty_out(vty
, "{}\n");
8532 table
= bgp
->rib
[afi
][safi
];
8533 /* use MPLS and ENCAP specific shows until they are merged */
8534 if (safi
== SAFI_MPLS_VPN
) {
8535 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8536 output_arg
, use_json
);
8539 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8540 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8541 output_arg
, use_json
,
8544 /* labeled-unicast routes live in the unicast table */
8545 else if (safi
== SAFI_LABELED_UNICAST
)
8546 safi
= SAFI_UNICAST
;
8548 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8549 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8552 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8553 safi_t safi
, bool use_json
)
8555 struct listnode
*node
, *nnode
;
8558 bool route_output
= false;
8561 vty_out(vty
, "{\n");
8563 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8564 route_output
= true;
8567 vty_out(vty
, ",\n");
8571 vty_out(vty
, "\"%s\":",
8572 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8576 vty_out(vty
, "\nInstance %s:\n",
8577 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8581 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8586 vty_out(vty
, "}\n");
8587 else if (!route_output
)
8588 vty_out(vty
, "%% BGP instance not found\n");
8591 /* Header of detailed BGP route information */
8592 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8593 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8594 afi_t afi
, safi_t safi
, json_object
*json
)
8596 struct bgp_info
*ri
;
8599 struct listnode
*node
, *nnode
;
8600 char buf1
[RD_ADDRSTRLEN
];
8601 char buf2
[INET6_ADDRSTRLEN
];
8602 char buf3
[EVPN_ROUTE_STRLEN
];
8603 char prefix_str
[BUFSIZ
];
8608 int route_filter_translated_v4
= 0;
8609 int route_filter_v4
= 0;
8610 int route_filter_translated_v6
= 0;
8611 int route_filter_v6
= 0;
8614 int accept_own_nexthop
= 0;
8617 int no_advertise
= 0;
8621 int has_valid_label
= 0;
8622 mpls_label_t label
= 0;
8623 json_object
*json_adv_to
= NULL
;
8626 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8628 if (has_valid_label
)
8629 label
= label_pton(&rn
->local_label
);
8632 if (has_valid_label
)
8633 json_object_int_add(json
, "localLabel", label
);
8635 json_object_string_add(
8637 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8639 if (safi
== SAFI_EVPN
)
8640 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8641 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8644 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8645 buf3
, sizeof(buf3
)));
8647 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8648 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8649 ? prefix_rd2str(prd
, buf1
,
8652 safi
== SAFI_MPLS_VPN
? ":" : "",
8653 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8657 if (has_valid_label
)
8658 vty_out(vty
, "Local label: %d\n", label
);
8659 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8660 vty_out(vty
, "not allocated\n");
8663 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8665 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8667 if (ri
->extra
&& ri
->extra
->suppress
)
8670 if (ri
->attr
->community
== NULL
)
8673 no_advertise
+= community_include(
8674 ri
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
8675 no_export
+= community_include(ri
->attr
->community
,
8676 COMMUNITY_NO_EXPORT
);
8677 local_as
+= community_include(ri
->attr
->community
,
8678 COMMUNITY_LOCAL_AS
);
8679 accept_own
+= community_include(ri
->attr
->community
,
8680 COMMUNITY_ACCEPT_OWN
);
8681 route_filter_translated_v4
+= community_include(
8682 ri
->attr
->community
,
8683 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
8684 route_filter_translated_v6
+= community_include(
8685 ri
->attr
->community
,
8686 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
8687 route_filter_v4
+= community_include(
8688 ri
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
8689 route_filter_v6
+= community_include(
8690 ri
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
8691 llgr_stale
+= community_include(ri
->attr
->community
,
8692 COMMUNITY_LLGR_STALE
);
8693 no_llgr
+= community_include(ri
->attr
->community
,
8695 accept_own_nexthop
+=
8696 community_include(ri
->attr
->community
,
8697 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
8698 blackhole
+= community_include(ri
->attr
->community
,
8699 COMMUNITY_BLACKHOLE
);
8700 no_peer
+= community_include(ri
->attr
->community
,
8706 vty_out(vty
, "Paths: (%d available", count
);
8708 vty_out(vty
, ", best #%d", best
);
8709 if (safi
== SAFI_UNICAST
)
8710 vty_out(vty
, ", table %s",
8712 == BGP_INSTANCE_TYPE_DEFAULT
)
8713 ? "Default-IP-Routing-Table"
8716 vty_out(vty
, ", no best path");
8720 ", accept own local route exported and imported in different VRF");
8721 else if (route_filter_translated_v4
)
8723 ", mark translated RTs for VPNv4 route filtering");
8724 else if (route_filter_v4
)
8726 ", attach RT as-is for VPNv4 route filtering");
8727 else if (route_filter_translated_v6
)
8729 ", mark translated RTs for VPNv6 route filtering");
8730 else if (route_filter_v6
)
8732 ", attach RT as-is for VPNv6 route filtering");
8733 else if (llgr_stale
)
8735 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
8738 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
8739 else if (accept_own_nexthop
)
8741 ", accept local nexthop");
8743 vty_out(vty
, ", inform peer to blackhole prefix");
8745 vty_out(vty
, ", not advertised to EBGP peer");
8746 else if (no_advertise
)
8747 vty_out(vty
, ", not advertised to any peer");
8749 vty_out(vty
, ", not advertised outside local AS");
8752 ", inform EBGP peer not to advertise to their EBGP peers");
8756 ", Advertisements suppressed by an aggregate.");
8757 vty_out(vty
, ")\n");
8760 /* If we are not using addpath then we can display Advertised to and
8762 * show what peers we advertised the bestpath to. If we are using
8764 * though then we must display Advertised to on a path-by-path basis. */
8765 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8766 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8767 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8768 if (json
&& !json_adv_to
)
8769 json_adv_to
= json_object_new_object();
8771 route_vty_out_advertised_to(
8773 " Advertised to non peer-group peers:\n ",
8780 json_object_object_add(json
, "advertisedTo",
8785 vty_out(vty
, " Not advertised to any peer");
8791 /* Display specified route of BGP table. */
8792 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8793 struct bgp_table
*rib
, const char *ip_str
,
8794 afi_t afi
, safi_t safi
,
8795 struct prefix_rd
*prd
, int prefix_check
,
8796 enum bgp_path_type pathtype
, bool use_json
)
8801 struct prefix match
;
8802 struct bgp_node
*rn
;
8803 struct bgp_node
*rm
;
8804 struct bgp_info
*ri
;
8805 struct bgp_table
*table
;
8806 json_object
*json
= NULL
;
8807 json_object
*json_paths
= NULL
;
8809 /* Check IP address argument. */
8810 ret
= str2prefix(ip_str
, &match
);
8812 vty_out(vty
, "address is malformed\n");
8816 match
.family
= afi2family(afi
);
8819 json
= json_object_new_object();
8820 json_paths
= json_object_new_array();
8823 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8824 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8825 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8828 if ((table
= rn
->info
) == NULL
)
8833 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8837 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8838 bgp_unlock_node(rm
);
8842 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8844 route_vty_out_detail_header(
8846 (struct prefix_rd
*)&rn
->p
,
8847 AFI_IP
, safi
, json
);
8852 if (pathtype
== BGP_PATH_ALL
8853 || (pathtype
== BGP_PATH_BESTPATH
8854 && CHECK_FLAG(ri
->flags
,
8856 || (pathtype
== BGP_PATH_MULTIPATH
8857 && (CHECK_FLAG(ri
->flags
,
8859 || CHECK_FLAG(ri
->flags
,
8860 BGP_INFO_SELECTED
))))
8861 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8866 bgp_unlock_node(rm
);
8868 } else if (safi
== SAFI_FLOWSPEC
) {
8869 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
8870 &match
, prefix_check
,
8877 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8879 || rn
->p
.prefixlen
== match
.prefixlen
) {
8880 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8882 route_vty_out_detail_header(
8883 vty
, bgp
, rn
, NULL
, afi
,
8889 if (pathtype
== BGP_PATH_ALL
8890 || (pathtype
== BGP_PATH_BESTPATH
8894 || (pathtype
== BGP_PATH_MULTIPATH
8900 BGP_INFO_SELECTED
))))
8901 route_vty_out_detail(
8902 vty
, bgp
, &rn
->p
, ri
,
8903 afi
, safi
, json_paths
);
8907 bgp_unlock_node(rn
);
8913 json_object_object_add(json
, "paths", json_paths
);
8915 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8916 json
, JSON_C_TO_STRING_PRETTY
));
8917 json_object_free(json
);
8920 vty_out(vty
, "%% Network not in table\n");
8928 /* Display specified route of Main RIB */
8929 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8930 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8931 int prefix_check
, enum bgp_path_type pathtype
,
8935 bgp
= bgp_get_default();
8938 vty_out(vty
, "No BGP process is configured\n");
8940 vty_out(vty
, "{}\n");
8945 /* labeled-unicast routes live in the unicast table */
8946 if (safi
== SAFI_LABELED_UNICAST
)
8947 safi
= SAFI_UNICAST
;
8949 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8950 afi
, safi
, prd
, prefix_check
, pathtype
,
8954 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8955 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8958 struct lcommunity
*lcom
;
8964 b
= buffer_new(1024);
8965 for (i
= 0; i
< argc
; i
++) {
8967 buffer_putc(b
, ' ');
8969 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8971 buffer_putstr(b
, argv
[i
]->arg
);
8975 buffer_putc(b
, '\0');
8977 str
= buffer_getstr(b
);
8980 lcom
= lcommunity_str2com(str
);
8981 XFREE(MTYPE_TMP
, str
);
8983 vty_out(vty
, "%% Large-community malformed\n");
8987 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8991 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8992 const char *lcom
, afi_t afi
, safi_t safi
,
8995 struct community_list
*list
;
8997 list
= community_list_lookup(bgp_clist
, lcom
,
8998 LARGE_COMMUNITY_LIST_MASTER
);
9000 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9005 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9009 DEFUN (show_ip_bgp_large_community_list
,
9010 show_ip_bgp_large_community_list_cmd
,
9011 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9015 BGP_INSTANCE_HELP_STR
9017 BGP_SAFI_WITH_LABEL_HELP_STR
9018 "Display routes matching the large-community-list\n"
9019 "large-community-list number\n"
9020 "large-community-list name\n"
9024 afi_t afi
= AFI_IP6
;
9025 safi_t safi
= SAFI_UNICAST
;
9028 if (argv_find(argv
, argc
, "ip", &idx
))
9030 if (argv_find(argv
, argc
, "view", &idx
)
9031 || argv_find(argv
, argc
, "vrf", &idx
))
9032 vrf
= argv
[++idx
]->arg
;
9033 if (argv_find(argv
, argc
, "ipv4", &idx
)
9034 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9035 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9036 if (argv_find(argv
, argc
, "unicast", &idx
)
9037 || argv_find(argv
, argc
, "multicast", &idx
))
9038 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9041 bool uj
= use_json(argc
, argv
);
9043 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9045 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9049 argv_find(argv
, argc
, "large-community-list", &idx
);
9050 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9053 DEFUN (show_ip_bgp_large_community
,
9054 show_ip_bgp_large_community_cmd
,
9055 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9059 BGP_INSTANCE_HELP_STR
9061 BGP_SAFI_WITH_LABEL_HELP_STR
9062 "Display routes matching the large-communities\n"
9063 "List of large-community numbers\n"
9067 afi_t afi
= AFI_IP6
;
9068 safi_t safi
= SAFI_UNICAST
;
9071 if (argv_find(argv
, argc
, "ip", &idx
))
9073 if (argv_find(argv
, argc
, "view", &idx
)
9074 || argv_find(argv
, argc
, "vrf", &idx
))
9075 vrf
= argv
[++idx
]->arg
;
9076 if (argv_find(argv
, argc
, "ipv4", &idx
)
9077 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9078 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9079 if (argv_find(argv
, argc
, "unicast", &idx
)
9080 || argv_find(argv
, argc
, "multicast", &idx
))
9081 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9084 bool uj
= use_json(argc
, argv
);
9086 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9088 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9092 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9093 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9095 return bgp_show(vty
, bgp
, afi
, safi
,
9096 bgp_show_type_lcommunity_all
, NULL
, uj
);
9099 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9103 /* BGP route print out function without JSON */
9106 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9107 <dampening <parameters>\
9112 |community-list <(1-500)|WORD> [exact-match]\
9113 |A.B.C.D/M longer-prefixes\
9114 |X:X::X:X/M longer-prefixes\
9119 BGP_INSTANCE_HELP_STR
9121 BGP_SAFI_WITH_LABEL_HELP_STR
9122 "Display detailed information about dampening\n"
9123 "Display detail of configured dampening parameters\n"
9124 "Display routes matching the route-map\n"
9125 "A route-map to match on\n"
9126 "Display routes conforming to the prefix-list\n"
9127 "Prefix-list name\n"
9128 "Display routes conforming to the filter-list\n"
9129 "Regular expression access list name\n"
9130 "BGP RIB advertisement statistics\n"
9131 "Display routes matching the community-list\n"
9132 "community-list number\n"
9133 "community-list name\n"
9134 "Exact match of the communities\n"
9136 "Display route and more specific routes\n"
9138 "Display route and more specific routes\n")
9140 afi_t afi
= AFI_IP6
;
9141 safi_t safi
= SAFI_UNICAST
;
9142 int exact_match
= 0;
9143 struct bgp
*bgp
= NULL
;
9146 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9151 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9152 if (argv_find(argv
, argc
, "parameters", &idx
))
9153 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9156 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9157 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9158 safi
, bgp_show_type_prefix_list
);
9160 if (argv_find(argv
, argc
, "filter-list", &idx
))
9161 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9162 safi
, bgp_show_type_filter_list
);
9164 if (argv_find(argv
, argc
, "statistics", &idx
))
9165 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9167 if (argv_find(argv
, argc
, "route-map", &idx
))
9168 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9169 safi
, bgp_show_type_route_map
);
9171 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9172 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9173 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9175 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9176 exact_match
, afi
, safi
);
9179 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9180 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9181 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9183 bgp_show_type_prefix_longer
);
9188 /* BGP route print out function with JSON */
9189 DEFUN (show_ip_bgp_json
,
9190 show_ip_bgp_json_cmd
,
9191 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9193 |dampening <flap-statistics|dampened-paths>\
9194 |community [AA:NN|local-AS|no-advertise|no-export\
9195 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9196 |accept-own|accept-own-nexthop|route-filter-v6\
9197 |route-filter-v4|route-filter-translated-v6\
9198 |route-filter-translated-v4] [exact-match]\
9203 BGP_INSTANCE_HELP_STR
9205 BGP_SAFI_WITH_LABEL_HELP_STR
9206 "Display only routes with non-natural netmasks\n"
9207 "Display detailed information about dampening\n"
9208 "Display flap statistics of routes\n"
9209 "Display paths suppressed due to dampening\n"
9210 "Display routes matching the communities\n"
9212 "Do not send outside local AS (well-known community)\n"
9213 "Do not advertise to any peer (well-known community)\n"
9214 "Do not export to next AS (well-known community)\n"
9215 "Graceful shutdown (well-known community)\n"
9216 "Do not export to any peer (well-known community)\n"
9217 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9218 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9219 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9220 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9221 "Should accept VPN route with local nexthop (well-known community)\n"
9222 "RT VPNv6 route filtering (well-known community)\n"
9223 "RT VPNv4 route filtering (well-known community)\n"
9224 "RT translated VPNv6 route filtering (well-known community)\n"
9225 "RT translated VPNv4 route filtering (well-known community)\n"
9226 "Exact match of the communities\n"
9229 afi_t afi
= AFI_IP6
;
9230 safi_t safi
= SAFI_UNICAST
;
9231 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9232 struct bgp
*bgp
= NULL
;
9234 int exact_match
= 0;
9235 bool uj
= use_json(argc
, argv
);
9240 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9245 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9246 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9249 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9250 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9251 return bgp_show(vty
, bgp
, afi
, safi
,
9252 bgp_show_type_dampend_paths
, NULL
, uj
);
9253 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9254 return bgp_show(vty
, bgp
, afi
, safi
,
9255 bgp_show_type_flap_statistics
, NULL
,
9259 if (argv_find(argv
, argc
, "community", &idx
)) {
9260 char *maybecomm
= idx
+ 1 < argc
? argv
[idx
+ 1]->text
: NULL
;
9261 char *community
= NULL
;
9263 if (maybecomm
&& !strmatch(maybecomm
, "json")
9264 && !strmatch(maybecomm
, "exact-match"))
9265 community
= maybecomm
;
9267 if (argv_find(argv
, argc
, "exact-match", &idx
))
9271 return bgp_show_community(vty
, bgp
, community
,
9272 exact_match
, afi
, safi
, uj
);
9274 return (bgp_show(vty
, bgp
, afi
, safi
,
9275 bgp_show_type_community_all
, NULL
,
9279 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9282 DEFUN (show_ip_bgp_route
,
9283 show_ip_bgp_route_cmd
,
9284 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9285 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9289 BGP_INSTANCE_HELP_STR
9291 BGP_SAFI_WITH_LABEL_HELP_STR
9292 "Network in the BGP routing table to display\n"
9294 "Network in the BGP routing table to display\n"
9296 "Display only the bestpath\n"
9297 "Display only multipaths\n"
9300 int prefix_check
= 0;
9302 afi_t afi
= AFI_IP6
;
9303 safi_t safi
= SAFI_UNICAST
;
9304 char *prefix
= NULL
;
9305 struct bgp
*bgp
= NULL
;
9306 enum bgp_path_type path_type
;
9307 bool uj
= use_json(argc
, argv
);
9311 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9318 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9322 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9323 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9324 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9326 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9327 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9330 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9331 && afi
!= AFI_IP6
) {
9333 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9336 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9339 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9343 prefix
= argv
[idx
]->arg
;
9345 /* [<bestpath|multipath>] */
9346 if (argv_find(argv
, argc
, "bestpath", &idx
))
9347 path_type
= BGP_PATH_BESTPATH
;
9348 else if (argv_find(argv
, argc
, "multipath", &idx
))
9349 path_type
= BGP_PATH_MULTIPATH
;
9351 path_type
= BGP_PATH_ALL
;
9353 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9357 DEFUN (show_ip_bgp_regexp
,
9358 show_ip_bgp_regexp_cmd
,
9359 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9363 BGP_INSTANCE_HELP_STR
9365 BGP_SAFI_WITH_LABEL_HELP_STR
9366 "Display routes matching the AS path regular expression\n"
9367 "A regular-expression to match the BGP AS paths\n")
9369 afi_t afi
= AFI_IP6
;
9370 safi_t safi
= SAFI_UNICAST
;
9371 struct bgp
*bgp
= NULL
;
9374 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9379 // get index of regex
9380 argv_find(argv
, argc
, "regexp", &idx
);
9383 char *regstr
= argv_concat(argv
, argc
, idx
);
9384 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9385 bgp_show_type_regexp
);
9386 XFREE(MTYPE_TMP
, regstr
);
9390 DEFUN (show_ip_bgp_instance_all
,
9391 show_ip_bgp_instance_all_cmd
,
9392 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9396 BGP_INSTANCE_ALL_HELP_STR
9398 BGP_SAFI_WITH_LABEL_HELP_STR
9402 safi_t safi
= SAFI_UNICAST
;
9403 struct bgp
*bgp
= NULL
;
9405 bool uj
= use_json(argc
, argv
);
9410 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9415 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9419 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9420 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9425 regex
= bgp_regcomp(regstr
);
9427 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9431 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9432 bgp_regex_free(regex
);
9436 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9437 const char *prefix_list_str
, afi_t afi
,
9438 safi_t safi
, enum bgp_show_type type
)
9440 struct prefix_list
*plist
;
9442 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9443 if (plist
== NULL
) {
9444 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9449 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9452 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9453 const char *filter
, afi_t afi
, safi_t safi
,
9454 enum bgp_show_type type
)
9456 struct as_list
*as_list
;
9458 as_list
= as_list_lookup(filter
);
9459 if (as_list
== NULL
) {
9460 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9465 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9468 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9469 const char *rmap_str
, afi_t afi
, safi_t safi
,
9470 enum bgp_show_type type
)
9472 struct route_map
*rmap
;
9474 rmap
= route_map_lookup_by_name(rmap_str
);
9476 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9480 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9483 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9484 const char *comstr
, int exact
, afi_t afi
,
9485 safi_t safi
, bool use_json
)
9487 struct community
*com
;
9490 com
= community_str2com(comstr
);
9492 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9496 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9497 (exact
? bgp_show_type_community_exact
9498 : bgp_show_type_community
),
9500 community_free(com
);
9505 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9506 const char *com
, int exact
, afi_t afi
,
9509 struct community_list
*list
;
9511 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9513 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9517 return bgp_show(vty
, bgp
, afi
, safi
,
9518 (exact
? bgp_show_type_community_list_exact
9519 : bgp_show_type_community_list
),
9523 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9524 const char *prefix
, afi_t afi
, safi_t safi
,
9525 enum bgp_show_type type
)
9532 ret
= str2prefix(prefix
, p
);
9534 vty_out(vty
, "%% Malformed Prefix\n");
9538 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9543 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9544 const char *ip_str
, bool use_json
)
9550 /* Get peer sockunion. */
9551 ret
= str2sockunion(ip_str
, &su
);
9553 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9555 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9559 json_object
*json_no
= NULL
;
9560 json_no
= json_object_new_object();
9561 json_object_string_add(
9563 "malformedAddressOrName",
9565 vty_out(vty
, "%s\n",
9566 json_object_to_json_string_ext(
9568 JSON_C_TO_STRING_PRETTY
));
9569 json_object_free(json_no
);
9572 "%% Malformed address or name: %s\n",
9580 /* Peer structure lookup. */
9581 peer
= peer_lookup(bgp
, &su
);
9584 json_object
*json_no
= NULL
;
9585 json_no
= json_object_new_object();
9586 json_object_string_add(json_no
, "warning",
9587 "No such neighbor in this view/vrf");
9588 vty_out(vty
, "%s\n",
9589 json_object_to_json_string_ext(
9590 json_no
, JSON_C_TO_STRING_PRETTY
));
9591 json_object_free(json_no
);
9593 vty_out(vty
, "No such neighbor in this view/vrf\n");
9601 BGP_STATS_MAXBITLEN
= 0,
9605 BGP_STATS_UNAGGREGATEABLE
,
9606 BGP_STATS_MAX_AGGREGATEABLE
,
9607 BGP_STATS_AGGREGATES
,
9609 BGP_STATS_ASPATH_COUNT
,
9610 BGP_STATS_ASPATH_MAXHOPS
,
9611 BGP_STATS_ASPATH_TOTHOPS
,
9612 BGP_STATS_ASPATH_MAXSIZE
,
9613 BGP_STATS_ASPATH_TOTSIZE
,
9614 BGP_STATS_ASN_HIGHEST
,
9618 static const char *table_stats_strs
[] = {
9619 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9620 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9621 [BGP_STATS_RIB
] = "Total Advertisements",
9622 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9623 [BGP_STATS_MAX_AGGREGATEABLE
] =
9624 "Maximum aggregateable prefixes",
9625 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9626 [BGP_STATS_SPACE
] = "Address space advertised",
9627 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9628 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9629 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9630 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9631 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9632 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9633 [BGP_STATS_MAX
] = NULL
,
9636 struct bgp_table_stats
{
9637 struct bgp_table
*table
;
9638 unsigned long long counts
[BGP_STATS_MAX
];
9643 #define TALLY_SIGFIG 100000
9644 static unsigned long
9645 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9647 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9648 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9649 unsigned long ret
= newtot
/ count
;
9651 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9658 static int bgp_table_stats_walker(struct thread
*t
)
9660 struct bgp_node
*rn
;
9661 struct bgp_node
*top
;
9662 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9663 unsigned int space
= 0;
9665 if (!(top
= bgp_table_top(ts
->table
)))
9668 switch (top
->p
.family
) {
9670 space
= IPV4_MAX_BITLEN
;
9673 space
= IPV6_MAX_BITLEN
;
9677 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9679 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9680 struct bgp_info
*ri
;
9681 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9682 unsigned int rinum
= 0;
9690 ts
->counts
[BGP_STATS_PREFIXES
]++;
9691 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9694 ts
->counts
[BGP_STATS_AVGPLEN
]
9695 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9696 ts
->counts
[BGP_STATS_AVGPLEN
],
9700 /* check if the prefix is included by any other announcements */
9701 while (prn
&& !prn
->info
)
9702 prn
= bgp_node_parent_nolock(prn
);
9704 if (prn
== NULL
|| prn
== top
) {
9705 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9706 /* announced address space */
9709 pow(2.0, space
- rn
->p
.prefixlen
);
9710 } else if (prn
->info
)
9711 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9713 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9715 ts
->counts
[BGP_STATS_RIB
]++;
9718 && (CHECK_FLAG(ri
->attr
->flag
,
9720 BGP_ATTR_ATOMIC_AGGREGATE
))))
9721 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9724 if (ri
->attr
&& ri
->attr
->aspath
) {
9726 aspath_count_hops(ri
->attr
->aspath
);
9728 aspath_size(ri
->attr
->aspath
);
9729 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9731 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9733 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9734 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9737 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9738 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9741 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9742 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9744 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9745 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9746 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9748 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9749 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9750 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9753 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9754 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9762 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9765 struct bgp_table_stats ts
;
9768 if (!bgp
->rib
[afi
][safi
]) {
9769 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9774 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9776 /* labeled-unicast routes live in the unicast table */
9777 if (safi
== SAFI_LABELED_UNICAST
)
9778 safi
= SAFI_UNICAST
;
9780 memset(&ts
, 0, sizeof(ts
));
9781 ts
.table
= bgp
->rib
[afi
][safi
];
9782 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9784 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9785 if (!table_stats_strs
[i
])
9790 case BGP_STATS_ASPATH_AVGHOPS
:
9791 case BGP_STATS_ASPATH_AVGSIZE
:
9792 case BGP_STATS_AVGPLEN
:
9793 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9794 vty_out (vty
, "%12.2f",
9795 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9798 case BGP_STATS_ASPATH_TOTHOPS
:
9799 case BGP_STATS_ASPATH_TOTSIZE
:
9800 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9801 vty_out(vty
, "%12.2f",
9803 ? (float)ts
.counts
[i
]
9805 [BGP_STATS_ASPATH_COUNT
]
9808 case BGP_STATS_TOTPLEN
:
9809 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9810 vty_out(vty
, "%12.2f",
9812 ? (float)ts
.counts
[i
]
9814 [BGP_STATS_PREFIXES
]
9817 case BGP_STATS_SPACE
:
9818 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9819 vty_out(vty
, "%12g\n", ts
.total_space
);
9821 if (afi
== AFI_IP6
) {
9822 vty_out(vty
, "%30s: ", "/32 equivalent ");
9823 vty_out(vty
, "%12g\n",
9824 ts
.total_space
* pow(2.0, -128 + 32));
9825 vty_out(vty
, "%30s: ", "/48 equivalent ");
9826 vty_out(vty
, "%12g\n",
9827 ts
.total_space
* pow(2.0, -128 + 48));
9829 vty_out(vty
, "%30s: ", "% announced ");
9830 vty_out(vty
, "%12.2f\n",
9831 ts
.total_space
* 100. * pow(2.0, -32));
9832 vty_out(vty
, "%30s: ", "/8 equivalent ");
9833 vty_out(vty
, "%12.2f\n",
9834 ts
.total_space
* pow(2.0, -32 + 8));
9835 vty_out(vty
, "%30s: ", "/24 equivalent ");
9836 vty_out(vty
, "%12.2f\n",
9837 ts
.total_space
* pow(2.0, -32 + 24));
9841 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9842 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9859 PCOUNT_PFCNT
, /* the figure we display to users */
9863 static const char *pcount_strs
[] = {
9864 [PCOUNT_ADJ_IN
] = "Adj-in",
9865 [PCOUNT_DAMPED
] = "Damped",
9866 [PCOUNT_REMOVED
] = "Removed",
9867 [PCOUNT_HISTORY
] = "History",
9868 [PCOUNT_STALE
] = "Stale",
9869 [PCOUNT_VALID
] = "Valid",
9870 [PCOUNT_ALL
] = "All RIB",
9871 [PCOUNT_COUNTED
] = "PfxCt counted",
9872 [PCOUNT_PFCNT
] = "Useable",
9873 [PCOUNT_MAX
] = NULL
,
9876 struct peer_pcounts
{
9877 unsigned int count
[PCOUNT_MAX
];
9878 const struct peer
*peer
;
9879 const struct bgp_table
*table
;
9882 static int bgp_peer_count_walker(struct thread
*t
)
9884 struct bgp_node
*rn
;
9885 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9886 const struct peer
*peer
= pc
->peer
;
9888 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9889 struct bgp_adj_in
*ain
;
9890 struct bgp_info
*ri
;
9892 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9893 if (ain
->peer
== peer
)
9894 pc
->count
[PCOUNT_ADJ_IN
]++;
9896 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9897 if (ri
->peer
!= peer
)
9900 pc
->count
[PCOUNT_ALL
]++;
9902 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9903 pc
->count
[PCOUNT_DAMPED
]++;
9904 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9905 pc
->count
[PCOUNT_HISTORY
]++;
9906 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9907 pc
->count
[PCOUNT_REMOVED
]++;
9908 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9909 pc
->count
[PCOUNT_STALE
]++;
9910 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9911 pc
->count
[PCOUNT_VALID
]++;
9912 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9913 pc
->count
[PCOUNT_PFCNT
]++;
9915 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9916 pc
->count
[PCOUNT_COUNTED
]++;
9917 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9920 "Attempting to count but flags say it is unusable");
9922 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9925 "Not counted but flags say we should");
9932 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9933 safi_t safi
, bool use_json
)
9935 struct peer_pcounts pcounts
= {.peer
= peer
};
9937 json_object
*json
= NULL
;
9938 json_object
*json_loop
= NULL
;
9941 json
= json_object_new_object();
9942 json_loop
= json_object_new_object();
9945 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9946 || !peer
->bgp
->rib
[afi
][safi
]) {
9948 json_object_string_add(
9950 "No such neighbor or address family");
9951 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9952 json_object_free(json
);
9954 vty_out(vty
, "%% No such neighbor or address family\n");
9959 memset(&pcounts
, 0, sizeof(pcounts
));
9960 pcounts
.peer
= peer
;
9961 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9963 /* in-place call via thread subsystem so as to record execution time
9964 * stats for the thread-walk (i.e. ensure this can't be blamed on
9965 * on just vty_read()).
9967 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9970 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9971 json_object_string_add(json
, "multiProtocol",
9972 afi_safi_print(afi
, safi
));
9973 json_object_int_add(json
, "pfxCounter",
9974 peer
->pcount
[afi
][safi
]);
9976 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9977 json_object_int_add(json_loop
, pcount_strs
[i
],
9980 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9982 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9983 json_object_string_add(json
, "pfxctDriftFor",
9985 json_object_string_add(
9986 json
, "recommended",
9987 "Please report this bug, with the above command output");
9989 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9990 json
, JSON_C_TO_STRING_PRETTY
));
9991 json_object_free(json
);
9995 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9996 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9997 peer
->hostname
, peer
->host
,
9998 afi_safi_print(afi
, safi
));
10000 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10001 afi_safi_print(afi
, safi
));
10004 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10005 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10007 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10008 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10011 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10012 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10014 "Please report this bug, with the above command output\n");
10018 return CMD_SUCCESS
;
10021 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10022 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10023 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10024 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10028 BGP_INSTANCE_HELP_STR
10031 "Detailed information on TCP and BGP neighbor connections\n"
10032 "Neighbor to display information about\n"
10033 "Neighbor to display information about\n"
10034 "Neighbor on BGP configured interface\n"
10035 "Display detailed prefix count information\n"
10038 afi_t afi
= AFI_IP6
;
10039 safi_t safi
= SAFI_UNICAST
;
10042 struct bgp
*bgp
= NULL
;
10043 bool uj
= use_json(argc
, argv
);
10048 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10051 return CMD_WARNING
;
10053 argv_find(argv
, argc
, "neighbors", &idx
);
10054 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10056 return CMD_WARNING
;
10058 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10061 #ifdef KEEP_OLD_VPN_COMMANDS
10062 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10063 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10064 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10069 "Display information about all VPNv4 NLRIs\n"
10070 "Detailed information on TCP and BGP neighbor connections\n"
10071 "Neighbor to display information about\n"
10072 "Neighbor to display information about\n"
10073 "Neighbor on BGP configured interface\n"
10074 "Display detailed prefix count information\n"
10079 bool uj
= use_json(argc
, argv
);
10081 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10083 return CMD_WARNING
;
10085 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10088 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10089 show_ip_bgp_vpn_all_route_prefix_cmd
,
10090 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10095 "Display information about all VPNv4 NLRIs\n"
10096 "Network in the BGP routing table to display\n"
10097 "Network in the BGP routing table to display\n"
10101 char *network
= NULL
;
10102 struct bgp
*bgp
= bgp_get_default();
10104 vty_out(vty
, "Can't find default instance\n");
10105 return CMD_WARNING
;
10108 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10109 network
= argv
[idx
]->arg
;
10110 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10111 network
= argv
[idx
]->arg
;
10113 vty_out(vty
, "Unable to figure out Network\n");
10114 return CMD_WARNING
;
10117 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10118 BGP_PATH_ALL
, use_json(argc
, argv
));
10120 #endif /* KEEP_OLD_VPN_COMMANDS */
10122 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10123 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10124 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10130 "Display information about all EVPN NLRIs\n"
10131 "Network in the BGP routing table to display\n"
10132 "Network in the BGP routing table to display\n"
10136 char *network
= NULL
;
10138 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10139 network
= argv
[idx
]->arg
;
10140 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10141 network
= argv
[idx
]->arg
;
10143 vty_out(vty
, "Unable to figure out Network\n");
10144 return CMD_WARNING
;
10146 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10147 BGP_PATH_ALL
, use_json(argc
, argv
));
10150 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10151 safi_t safi
, enum bgp_show_adj_route_type type
,
10152 const char *rmap_name
, bool use_json
,
10155 struct bgp_table
*table
;
10156 struct bgp_adj_in
*ain
;
10157 struct bgp_adj_out
*adj
;
10158 unsigned long output_count
;
10159 unsigned long filtered_count
;
10160 struct bgp_node
*rn
;
10166 struct update_subgroup
*subgrp
;
10167 json_object
*json_scode
= NULL
;
10168 json_object
*json_ocode
= NULL
;
10169 json_object
*json_ar
= NULL
;
10170 struct peer_af
*paf
;
10171 bool route_filtered
;
10174 json_scode
= json_object_new_object();
10175 json_ocode
= json_object_new_object();
10176 json_ar
= json_object_new_object();
10178 json_object_string_add(json_scode
, "suppressed", "s");
10179 json_object_string_add(json_scode
, "damped", "d");
10180 json_object_string_add(json_scode
, "history", "h");
10181 json_object_string_add(json_scode
, "valid", "*");
10182 json_object_string_add(json_scode
, "best", ">");
10183 json_object_string_add(json_scode
, "multipath", "=");
10184 json_object_string_add(json_scode
, "internal", "i");
10185 json_object_string_add(json_scode
, "ribFailure", "r");
10186 json_object_string_add(json_scode
, "stale", "S");
10187 json_object_string_add(json_scode
, "removed", "R");
10189 json_object_string_add(json_ocode
, "igp", "i");
10190 json_object_string_add(json_ocode
, "egp", "e");
10191 json_object_string_add(json_ocode
, "incomplete", "?");
10198 json_object_string_add(json
, "alert", "no BGP");
10199 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10200 json_object_free(json
);
10202 vty_out(vty
, "%% No bgp\n");
10206 table
= bgp
->rib
[afi
][safi
];
10208 output_count
= filtered_count
= 0;
10209 subgrp
= peer_subgroup(peer
, afi
, safi
);
10211 if (type
== bgp_show_adj_route_advertised
&& subgrp
10212 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10214 json_object_int_add(json
, "bgpTableVersion",
10216 json_object_string_add(json
, "bgpLocalRouterId",
10217 inet_ntoa(bgp
->router_id
));
10218 json_object_object_add(json
, "bgpStatusCodes",
10220 json_object_object_add(json
, "bgpOriginCodes",
10222 json_object_string_add(
10223 json
, "bgpOriginatingDefaultNetwork",
10224 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10226 vty_out(vty
, "BGP table version is %" PRIu64
10227 ", local router ID is %s, vrf id ",
10228 table
->version
, inet_ntoa(bgp
->router_id
));
10229 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10230 vty_out(vty
, "%s", VRFID_NONE_STR
);
10232 vty_out(vty
, "%u", bgp
->vrf_id
);
10233 vty_out(vty
, "\n");
10234 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10235 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10236 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10238 vty_out(vty
, "Originating default network %s\n\n",
10239 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10244 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10245 if (type
== bgp_show_adj_route_received
10246 || type
== bgp_show_adj_route_filtered
) {
10247 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10248 if (ain
->peer
!= peer
|| !ain
->attr
)
10253 json_object_int_add(
10254 json
, "bgpTableVersion",
10256 json_object_string_add(
10258 "bgpLocalRouterId",
10261 json_object_object_add(
10262 json
, "bgpStatusCodes",
10264 json_object_object_add(
10265 json
, "bgpOriginCodes",
10269 "BGP table version is 0, local router ID is %s, vrf id ",
10272 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10278 vty_out(vty
, "\n");
10280 BGP_SHOW_SCODE_HEADER
);
10282 BGP_SHOW_NCODE_HEADER
);
10284 BGP_SHOW_OCODE_HEADER
);
10290 vty_out(vty
, BGP_SHOW_HEADER
);
10294 bgp_attr_dup(&attr
, ain
->attr
);
10295 route_filtered
= false;
10297 /* Filter prefix using distribute list,
10298 * filter list or prefix list
10300 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10301 safi
)) == FILTER_DENY
)
10302 route_filtered
= true;
10304 /* Filter prefix using route-map */
10305 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10306 afi
, safi
, rmap_name
);
10308 if (type
== bgp_show_adj_route_filtered
&&
10309 !route_filtered
&& ret
!= RMAP_DENY
) {
10310 bgp_attr_undup(&attr
, ain
->attr
);
10314 if (type
== bgp_show_adj_route_received
&&
10315 (route_filtered
|| ret
== RMAP_DENY
))
10318 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10319 use_json
, json_ar
);
10320 bgp_attr_undup(&attr
, ain
->attr
);
10323 } else if (type
== bgp_show_adj_route_advertised
) {
10324 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10325 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10326 if (paf
->peer
!= peer
|| !adj
->attr
)
10331 json_object_int_add(
10335 json_object_string_add(
10337 "bgpLocalRouterId",
10340 json_object_object_add(
10344 json_object_object_add(
10350 "BGP table version is %" PRIu64
10351 ", local router ID is %s, vrf id ",
10364 vty_out(vty
, "\n");
10366 BGP_SHOW_SCODE_HEADER
);
10368 BGP_SHOW_NCODE_HEADER
);
10370 BGP_SHOW_OCODE_HEADER
);
10381 bgp_attr_dup(&attr
, adj
->attr
);
10382 ret
= bgp_output_modifier(
10383 peer
, &rn
->p
, &attr
, afi
, safi
,
10386 if (ret
!= RMAP_DENY
) {
10387 route_vty_out_tmp(vty
, &rn
->p
,
10396 bgp_attr_undup(&attr
, adj
->attr
);
10402 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10403 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10404 json_object_int_add(json
, "filteredPrefixCounter",
10407 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10408 json
, JSON_C_TO_STRING_PRETTY
));
10409 json_object_free(json
);
10410 } else if (output_count
> 0) {
10411 if (filtered_count
> 0)
10413 "\nTotal number of prefixes %ld (%ld filtered)\n",
10414 output_count
, filtered_count
);
10416 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10421 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10422 safi_t safi
, enum bgp_show_adj_route_type type
,
10423 const char *rmap_name
, bool use_json
)
10425 json_object
*json
= NULL
;
10428 json
= json_object_new_object();
10430 /* labeled-unicast routes live in the unicast table */
10431 if (safi
== SAFI_LABELED_UNICAST
)
10432 safi
= SAFI_UNICAST
;
10434 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10436 json_object_string_add(
10438 "No such neighbor or address family");
10439 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10440 json_object_free(json
);
10442 vty_out(vty
, "%% No such neighbor or address family\n");
10444 return CMD_WARNING
;
10447 if ((type
== bgp_show_adj_route_received
10448 || type
== bgp_show_adj_route_filtered
)
10449 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10450 PEER_FLAG_SOFT_RECONFIG
)) {
10452 json_object_string_add(
10454 "Inbound soft reconfiguration not enabled");
10455 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10456 json_object_free(json
);
10459 "%% Inbound soft reconfiguration not enabled\n");
10461 return CMD_WARNING
;
10464 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10466 return CMD_SUCCESS
;
10469 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10470 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10471 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10472 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10476 BGP_INSTANCE_HELP_STR
10478 BGP_SAFI_WITH_LABEL_HELP_STR
10479 "Detailed information on TCP and BGP neighbor connections\n"
10480 "Neighbor to display information about\n"
10481 "Neighbor to display information about\n"
10482 "Neighbor on BGP configured interface\n"
10483 "Display the routes advertised to a BGP neighbor\n"
10484 "Display the received routes from neighbor\n"
10485 "Display the filtered routes received from neighbor\n"
10486 "Route-map to modify the attributes\n"
10487 "Name of the route map\n"
10490 afi_t afi
= AFI_IP6
;
10491 safi_t safi
= SAFI_UNICAST
;
10492 char *rmap_name
= NULL
;
10493 char *peerstr
= NULL
;
10494 struct bgp
*bgp
= NULL
;
10496 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10498 bool uj
= use_json(argc
, argv
);
10503 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10506 return CMD_WARNING
;
10508 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10509 argv_find(argv
, argc
, "neighbors", &idx
);
10510 peerstr
= argv
[++idx
]->arg
;
10512 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10514 return CMD_WARNING
;
10516 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10517 type
= bgp_show_adj_route_advertised
;
10518 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10519 type
= bgp_show_adj_route_received
;
10520 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10521 type
= bgp_show_adj_route_filtered
;
10523 if (argv_find(argv
, argc
, "route-map", &idx
))
10524 rmap_name
= argv
[++idx
]->arg
;
10526 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10529 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10530 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10531 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10537 "Address Family modifier\n"
10538 "Detailed information on TCP and BGP neighbor connections\n"
10539 "Neighbor to display information about\n"
10540 "Neighbor to display information about\n"
10541 "Neighbor on BGP configured interface\n"
10542 "Display information received from a BGP neighbor\n"
10543 "Display the prefixlist filter\n"
10546 afi_t afi
= AFI_IP6
;
10547 safi_t safi
= SAFI_UNICAST
;
10548 char *peerstr
= NULL
;
10551 union sockunion su
;
10557 /* show [ip] bgp */
10558 if (argv_find(argv
, argc
, "ip", &idx
))
10560 /* [<ipv4|ipv6> [unicast]] */
10561 if (argv_find(argv
, argc
, "ipv4", &idx
))
10563 if (argv_find(argv
, argc
, "ipv6", &idx
))
10565 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10566 argv_find(argv
, argc
, "neighbors", &idx
);
10567 peerstr
= argv
[++idx
]->arg
;
10569 bool uj
= use_json(argc
, argv
);
10571 ret
= str2sockunion(peerstr
, &su
);
10573 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10576 vty_out(vty
, "{}\n");
10579 "%% Malformed address or name: %s\n",
10581 return CMD_WARNING
;
10584 peer
= peer_lookup(NULL
, &su
);
10587 vty_out(vty
, "{}\n");
10589 vty_out(vty
, "No peer\n");
10590 return CMD_WARNING
;
10594 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10595 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10598 vty_out(vty
, "Address Family: %s\n",
10599 afi_safi_print(afi
, safi
));
10600 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10603 vty_out(vty
, "{}\n");
10605 vty_out(vty
, "No functional output\n");
10608 return CMD_SUCCESS
;
10611 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10612 afi_t afi
, safi_t safi
,
10613 enum bgp_show_type type
, bool use_json
)
10615 /* labeled-unicast routes live in the unicast table */
10616 if (safi
== SAFI_LABELED_UNICAST
)
10617 safi
= SAFI_UNICAST
;
10619 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10621 json_object
*json_no
= NULL
;
10622 json_no
= json_object_new_object();
10623 json_object_string_add(
10624 json_no
, "warning",
10625 "No such neighbor or address family");
10626 vty_out(vty
, "%s\n",
10627 json_object_to_json_string(json_no
));
10628 json_object_free(json_no
);
10630 vty_out(vty
, "%% No such neighbor or address family\n");
10631 return CMD_WARNING
;
10634 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10637 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10638 show_ip_bgp_flowspec_routes_detailed_cmd
,
10639 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10643 BGP_INSTANCE_HELP_STR
10646 "Detailed information on flowspec entries\n"
10649 afi_t afi
= AFI_IP
;
10650 safi_t safi
= SAFI_UNICAST
;
10651 struct bgp
*bgp
= NULL
;
10653 bool uj
= use_json(argc
, argv
);
10658 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10661 return CMD_WARNING
;
10663 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
10666 DEFUN (show_ip_bgp_neighbor_routes
,
10667 show_ip_bgp_neighbor_routes_cmd
,
10668 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10669 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10673 BGP_INSTANCE_HELP_STR
10675 BGP_SAFI_WITH_LABEL_HELP_STR
10676 "Detailed information on TCP and BGP neighbor connections\n"
10677 "Neighbor to display information about\n"
10678 "Neighbor to display information about\n"
10679 "Neighbor on BGP configured interface\n"
10680 "Display flap statistics of the routes learned from neighbor\n"
10681 "Display the dampened routes received from neighbor\n"
10682 "Display routes learned from neighbor\n"
10685 char *peerstr
= NULL
;
10686 struct bgp
*bgp
= NULL
;
10687 afi_t afi
= AFI_IP6
;
10688 safi_t safi
= SAFI_UNICAST
;
10690 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10692 bool uj
= use_json(argc
, argv
);
10697 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10700 return CMD_WARNING
;
10702 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10703 argv_find(argv
, argc
, "neighbors", &idx
);
10704 peerstr
= argv
[++idx
]->arg
;
10706 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10708 return CMD_WARNING
;
10710 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10711 sh_type
= bgp_show_type_flap_neighbor
;
10712 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10713 sh_type
= bgp_show_type_damp_neighbor
;
10714 else if (argv_find(argv
, argc
, "routes", &idx
))
10715 sh_type
= bgp_show_type_neighbor
;
10717 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10720 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10722 struct bgp_distance
{
10723 /* Distance value for the IP source prefix. */
10726 /* Name of the access-list to be matched. */
10730 DEFUN (show_bgp_afi_vpn_rd_route
,
10731 show_bgp_afi_vpn_rd_route_cmd
,
10732 "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]",
10736 "Address Family modifier\n"
10737 "Display information for a route distinguisher\n"
10738 "Route Distinguisher\n"
10739 "Network in the BGP routing table to display\n"
10740 "Network in the BGP routing table to display\n"
10744 struct prefix_rd prd
;
10745 afi_t afi
= AFI_MAX
;
10748 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10749 vty_out(vty
, "%% Malformed Address Family\n");
10750 return CMD_WARNING
;
10753 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10755 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10756 return CMD_WARNING
;
10759 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10760 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10763 static struct bgp_distance
*bgp_distance_new(void)
10765 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10768 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10770 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10773 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10774 const char *ip_str
, const char *access_list_str
)
10781 struct bgp_node
*rn
;
10782 struct bgp_distance
*bdistance
;
10784 afi
= bgp_node_afi(vty
);
10785 safi
= bgp_node_safi(vty
);
10787 ret
= str2prefix(ip_str
, &p
);
10789 vty_out(vty
, "Malformed prefix\n");
10790 return CMD_WARNING_CONFIG_FAILED
;
10793 distance
= atoi(distance_str
);
10795 /* Get BGP distance node. */
10796 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10797 bdistance
= bgp_distance_get_node(rn
);
10799 bgp_unlock_node(rn
);
10801 bdistance
= bgp_distance_new();
10802 bgp_distance_set_node_info(rn
, bdistance
);
10805 /* Set distance value. */
10806 bdistance
->distance
= distance
;
10808 /* Reset access-list configuration. */
10809 if (bdistance
->access_list
) {
10810 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10811 bdistance
->access_list
= NULL
;
10813 if (access_list_str
)
10814 bdistance
->access_list
=
10815 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10817 return CMD_SUCCESS
;
10820 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10821 const char *ip_str
, const char *access_list_str
)
10828 struct bgp_node
*rn
;
10829 struct bgp_distance
*bdistance
;
10831 afi
= bgp_node_afi(vty
);
10832 safi
= bgp_node_safi(vty
);
10834 ret
= str2prefix(ip_str
, &p
);
10836 vty_out(vty
, "Malformed prefix\n");
10837 return CMD_WARNING_CONFIG_FAILED
;
10840 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10841 (struct prefix
*)&p
);
10843 vty_out(vty
, "Can't find specified prefix\n");
10844 return CMD_WARNING_CONFIG_FAILED
;
10847 bdistance
= bgp_distance_get_node(rn
);
10848 distance
= atoi(distance_str
);
10850 if (bdistance
->distance
!= distance
) {
10851 vty_out(vty
, "Distance does not match configured\n");
10852 return CMD_WARNING_CONFIG_FAILED
;
10855 if (bdistance
->access_list
)
10856 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10857 bgp_distance_free(bdistance
);
10860 bgp_unlock_node(rn
);
10861 bgp_unlock_node(rn
);
10863 return CMD_SUCCESS
;
10866 /* Apply BGP information to distance method. */
10867 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10868 safi_t safi
, struct bgp
*bgp
)
10870 struct bgp_node
*rn
;
10873 struct bgp_distance
*bdistance
;
10874 struct access_list
*alist
;
10875 struct bgp_static
*bgp_static
;
10880 peer
= rinfo
->peer
;
10882 /* Check source address. */
10883 sockunion2hostprefix(&peer
->su
, &q
);
10884 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10886 bdistance
= bgp_distance_get_node(rn
);
10887 bgp_unlock_node(rn
);
10889 if (bdistance
->access_list
) {
10890 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10892 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10893 return bdistance
->distance
;
10895 return bdistance
->distance
;
10898 /* Backdoor check. */
10899 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10901 bgp_static
= bgp_static_get_node_info(rn
);
10902 bgp_unlock_node(rn
);
10904 if (bgp_static
->backdoor
) {
10905 if (bgp
->distance_local
[afi
][safi
])
10906 return bgp
->distance_local
[afi
][safi
];
10908 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10912 if (peer
->sort
== BGP_PEER_EBGP
) {
10913 if (bgp
->distance_ebgp
[afi
][safi
])
10914 return bgp
->distance_ebgp
[afi
][safi
];
10915 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10917 if (bgp
->distance_ibgp
[afi
][safi
])
10918 return bgp
->distance_ibgp
[afi
][safi
];
10919 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10923 DEFUN (bgp_distance
,
10925 "distance bgp (1-255) (1-255) (1-255)",
10926 "Define an administrative distance\n"
10928 "Distance for routes external to the AS\n"
10929 "Distance for routes internal to the AS\n"
10930 "Distance for local routes\n")
10932 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10933 int idx_number
= 2;
10934 int idx_number_2
= 3;
10935 int idx_number_3
= 4;
10939 afi
= bgp_node_afi(vty
);
10940 safi
= bgp_node_safi(vty
);
10942 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10943 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10944 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10945 return CMD_SUCCESS
;
10948 DEFUN (no_bgp_distance
,
10949 no_bgp_distance_cmd
,
10950 "no distance bgp [(1-255) (1-255) (1-255)]",
10952 "Define an administrative distance\n"
10954 "Distance for routes external to the AS\n"
10955 "Distance for routes internal to the AS\n"
10956 "Distance for local routes\n")
10958 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10962 afi
= bgp_node_afi(vty
);
10963 safi
= bgp_node_safi(vty
);
10965 bgp
->distance_ebgp
[afi
][safi
] = 0;
10966 bgp
->distance_ibgp
[afi
][safi
] = 0;
10967 bgp
->distance_local
[afi
][safi
] = 0;
10968 return CMD_SUCCESS
;
10972 DEFUN (bgp_distance_source
,
10973 bgp_distance_source_cmd
,
10974 "distance (1-255) A.B.C.D/M",
10975 "Define an administrative distance\n"
10976 "Administrative distance\n"
10977 "IP source prefix\n")
10979 int idx_number
= 1;
10980 int idx_ipv4_prefixlen
= 2;
10981 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10982 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10983 return CMD_SUCCESS
;
10986 DEFUN (no_bgp_distance_source
,
10987 no_bgp_distance_source_cmd
,
10988 "no distance (1-255) A.B.C.D/M",
10990 "Define an administrative distance\n"
10991 "Administrative distance\n"
10992 "IP source prefix\n")
10994 int idx_number
= 2;
10995 int idx_ipv4_prefixlen
= 3;
10996 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10997 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10998 return CMD_SUCCESS
;
11001 DEFUN (bgp_distance_source_access_list
,
11002 bgp_distance_source_access_list_cmd
,
11003 "distance (1-255) A.B.C.D/M WORD",
11004 "Define an administrative distance\n"
11005 "Administrative distance\n"
11006 "IP source prefix\n"
11007 "Access list name\n")
11009 int idx_number
= 1;
11010 int idx_ipv4_prefixlen
= 2;
11012 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11013 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11014 return CMD_SUCCESS
;
11017 DEFUN (no_bgp_distance_source_access_list
,
11018 no_bgp_distance_source_access_list_cmd
,
11019 "no distance (1-255) A.B.C.D/M WORD",
11021 "Define an administrative distance\n"
11022 "Administrative distance\n"
11023 "IP source prefix\n"
11024 "Access list name\n")
11026 int idx_number
= 2;
11027 int idx_ipv4_prefixlen
= 3;
11029 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11030 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11031 return CMD_SUCCESS
;
11034 DEFUN (ipv6_bgp_distance_source
,
11035 ipv6_bgp_distance_source_cmd
,
11036 "distance (1-255) X:X::X:X/M",
11037 "Define an administrative distance\n"
11038 "Administrative distance\n"
11039 "IP source prefix\n")
11041 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11042 return CMD_SUCCESS
;
11045 DEFUN (no_ipv6_bgp_distance_source
,
11046 no_ipv6_bgp_distance_source_cmd
,
11047 "no distance (1-255) X:X::X:X/M",
11049 "Define an administrative distance\n"
11050 "Administrative distance\n"
11051 "IP source prefix\n")
11053 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11054 return CMD_SUCCESS
;
11057 DEFUN (ipv6_bgp_distance_source_access_list
,
11058 ipv6_bgp_distance_source_access_list_cmd
,
11059 "distance (1-255) X:X::X:X/M WORD",
11060 "Define an administrative distance\n"
11061 "Administrative distance\n"
11062 "IP source prefix\n"
11063 "Access list name\n")
11065 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11066 return CMD_SUCCESS
;
11069 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11070 no_ipv6_bgp_distance_source_access_list_cmd
,
11071 "no distance (1-255) X:X::X:X/M WORD",
11073 "Define an administrative distance\n"
11074 "Administrative distance\n"
11075 "IP source prefix\n"
11076 "Access list name\n")
11078 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11079 return CMD_SUCCESS
;
11082 DEFUN (bgp_damp_set
,
11084 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11085 "BGP Specific commands\n"
11086 "Enable route-flap dampening\n"
11087 "Half-life time for the penalty\n"
11088 "Value to start reusing a route\n"
11089 "Value to start suppressing a route\n"
11090 "Maximum duration to suppress a stable route\n")
11092 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11093 int idx_half_life
= 2;
11095 int idx_suppress
= 4;
11096 int idx_max_suppress
= 5;
11097 int half
= DEFAULT_HALF_LIFE
* 60;
11098 int reuse
= DEFAULT_REUSE
;
11099 int suppress
= DEFAULT_SUPPRESS
;
11100 int max
= 4 * half
;
11103 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11104 reuse
= atoi(argv
[idx_reuse
]->arg
);
11105 suppress
= atoi(argv
[idx_suppress
]->arg
);
11106 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11107 } else if (argc
== 3) {
11108 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11112 if (suppress
< reuse
) {
11114 "Suppress value cannot be less than reuse value \n");
11118 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11119 reuse
, suppress
, max
);
11122 DEFUN (bgp_damp_unset
,
11123 bgp_damp_unset_cmd
,
11124 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11126 "BGP Specific commands\n"
11127 "Enable route-flap dampening\n"
11128 "Half-life time for the penalty\n"
11129 "Value to start reusing a route\n"
11130 "Value to start suppressing a route\n"
11131 "Maximum duration to suppress a stable route\n")
11133 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11134 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11137 /* Display specified route of BGP table. */
11138 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11139 const char *ip_str
, afi_t afi
, safi_t safi
,
11140 struct prefix_rd
*prd
, int prefix_check
)
11143 struct prefix match
;
11144 struct bgp_node
*rn
;
11145 struct bgp_node
*rm
;
11146 struct bgp_info
*ri
;
11147 struct bgp_info
*ri_temp
;
11149 struct bgp_table
*table
;
11151 /* BGP structure lookup. */
11153 bgp
= bgp_lookup_by_name(view_name
);
11155 vty_out(vty
, "%% Can't find BGP instance %s\n",
11157 return CMD_WARNING
;
11160 bgp
= bgp_get_default();
11162 vty_out(vty
, "%% No BGP process is configured\n");
11163 return CMD_WARNING
;
11167 /* Check IP address argument. */
11168 ret
= str2prefix(ip_str
, &match
);
11170 vty_out(vty
, "%% address is malformed\n");
11171 return CMD_WARNING
;
11174 match
.family
= afi2family(afi
);
11176 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11177 || (safi
== SAFI_EVPN
)) {
11178 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11179 rn
= bgp_route_next(rn
)) {
11180 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11182 if ((table
= rn
->info
) == NULL
)
11184 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11188 || rm
->p
.prefixlen
== match
.prefixlen
) {
11191 if (ri
->extra
&& ri
->extra
->damp_info
) {
11192 ri_temp
= ri
->next
;
11193 bgp_damp_info_free(
11194 ri
->extra
->damp_info
,
11202 bgp_unlock_node(rm
);
11205 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11208 || rn
->p
.prefixlen
== match
.prefixlen
) {
11211 if (ri
->extra
&& ri
->extra
->damp_info
) {
11212 ri_temp
= ri
->next
;
11213 bgp_damp_info_free(
11214 ri
->extra
->damp_info
,
11222 bgp_unlock_node(rn
);
11226 return CMD_SUCCESS
;
11229 DEFUN (clear_ip_bgp_dampening
,
11230 clear_ip_bgp_dampening_cmd
,
11231 "clear ip bgp dampening",
11235 "Clear route flap dampening information\n")
11237 bgp_damp_info_clean();
11238 return CMD_SUCCESS
;
11241 DEFUN (clear_ip_bgp_dampening_prefix
,
11242 clear_ip_bgp_dampening_prefix_cmd
,
11243 "clear ip bgp dampening A.B.C.D/M",
11247 "Clear route flap dampening information\n"
11250 int idx_ipv4_prefixlen
= 4;
11251 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11252 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11255 DEFUN (clear_ip_bgp_dampening_address
,
11256 clear_ip_bgp_dampening_address_cmd
,
11257 "clear ip bgp dampening A.B.C.D",
11261 "Clear route flap dampening information\n"
11262 "Network to clear damping information\n")
11265 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11266 SAFI_UNICAST
, NULL
, 0);
11269 DEFUN (clear_ip_bgp_dampening_address_mask
,
11270 clear_ip_bgp_dampening_address_mask_cmd
,
11271 "clear ip bgp dampening A.B.C.D A.B.C.D",
11275 "Clear route flap dampening information\n"
11276 "Network to clear damping information\n"
11280 int idx_ipv4_2
= 5;
11282 char prefix_str
[BUFSIZ
];
11284 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11287 vty_out(vty
, "%% Inconsistent address and mask\n");
11288 return CMD_WARNING
;
11291 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11295 /* also used for encap safi */
11296 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11297 afi_t afi
, safi_t safi
)
11299 struct bgp_node
*prn
;
11300 struct bgp_node
*rn
;
11301 struct bgp_table
*table
;
11303 struct prefix_rd
*prd
;
11304 struct bgp_static
*bgp_static
;
11305 mpls_label_t label
;
11306 char buf
[SU_ADDRSTRLEN
];
11307 char rdbuf
[RD_ADDRSTRLEN
];
11309 /* Network configuration. */
11310 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11311 prn
= bgp_route_next(prn
)) {
11312 if ((table
= prn
->info
) == NULL
)
11315 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11316 bgp_static
= bgp_static_get_node_info(rn
);
11317 if (bgp_static
== NULL
)
11321 prd
= (struct prefix_rd
*)&prn
->p
;
11323 /* "network" configuration display. */
11324 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11325 label
= decode_label(&bgp_static
->label
);
11327 vty_out(vty
, " network %s/%d rd %s",
11328 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11330 p
->prefixlen
, rdbuf
);
11331 if (safi
== SAFI_MPLS_VPN
)
11332 vty_out(vty
, " label %u", label
);
11334 if (bgp_static
->rmap
.name
)
11335 vty_out(vty
, " route-map %s",
11336 bgp_static
->rmap
.name
);
11338 if (bgp_static
->backdoor
)
11339 vty_out(vty
, " backdoor");
11341 vty_out(vty
, "\n");
11346 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11347 afi_t afi
, safi_t safi
)
11349 struct bgp_node
*prn
;
11350 struct bgp_node
*rn
;
11351 struct bgp_table
*table
;
11353 struct prefix_rd
*prd
;
11354 struct bgp_static
*bgp_static
;
11355 char buf
[PREFIX_STRLEN
* 2];
11356 char buf2
[SU_ADDRSTRLEN
];
11357 char rdbuf
[RD_ADDRSTRLEN
];
11359 /* Network configuration. */
11360 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11361 prn
= bgp_route_next(prn
)) {
11362 if ((table
= prn
->info
) == NULL
)
11365 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11366 bgp_static
= bgp_static_get_node_info(rn
);
11367 if (bgp_static
== NULL
)
11370 char *macrouter
= NULL
;
11373 if (bgp_static
->router_mac
)
11374 macrouter
= prefix_mac2str(
11375 bgp_static
->router_mac
, NULL
, 0);
11376 if (bgp_static
->eth_s_id
)
11377 esi
= esi2str(bgp_static
->eth_s_id
);
11379 prd
= (struct prefix_rd
*)&prn
->p
;
11381 /* "network" configuration display. */
11382 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11383 if (p
->u
.prefix_evpn
.route_type
== 5) {
11384 char local_buf
[PREFIX_STRLEN
];
11385 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11386 struct prefix_evpn
*)p
)
11390 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11391 local_buf
, PREFIX_STRLEN
);
11392 sprintf(buf
, "%s/%u", local_buf
,
11393 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11395 prefix2str(p
, buf
, sizeof(buf
));
11398 if (bgp_static
->gatewayIp
.family
== AF_INET
11399 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11400 inet_ntop(bgp_static
->gatewayIp
.family
,
11401 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11404 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11406 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11407 decode_label(&bgp_static
->label
), esi
, buf2
,
11411 XFREE(MTYPE_TMP
, macrouter
);
11413 XFREE(MTYPE_TMP
, esi
);
11418 /* Configuration of static route announcement and aggregate
11420 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11423 struct bgp_node
*rn
;
11425 struct bgp_static
*bgp_static
;
11426 struct bgp_aggregate
*bgp_aggregate
;
11427 char buf
[SU_ADDRSTRLEN
];
11429 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11430 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11434 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11435 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11439 /* Network configuration. */
11440 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11441 rn
= bgp_route_next(rn
)) {
11442 bgp_static
= bgp_static_get_node_info(rn
);
11443 if (bgp_static
== NULL
)
11448 /* "network" configuration display. */
11449 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11450 uint32_t destination
;
11451 struct in_addr netmask
;
11453 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11454 masklen2ip(p
->prefixlen
, &netmask
);
11455 vty_out(vty
, " network %s",
11456 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11459 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11460 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11461 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11462 || p
->u
.prefix4
.s_addr
== 0) {
11463 /* Natural mask is not display. */
11465 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11467 vty_out(vty
, " network %s/%d",
11468 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11473 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11474 vty_out(vty
, " label-index %u",
11475 bgp_static
->label_index
);
11477 if (bgp_static
->rmap
.name
)
11478 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11480 if (bgp_static
->backdoor
)
11481 vty_out(vty
, " backdoor");
11483 vty_out(vty
, "\n");
11486 /* Aggregate-address configuration. */
11487 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11488 rn
= bgp_route_next(rn
)) {
11489 bgp_aggregate
= bgp_aggregate_get_node_info(rn
);
11490 if (bgp_aggregate
== NULL
)
11495 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11496 struct in_addr netmask
;
11498 masklen2ip(p
->prefixlen
, &netmask
);
11499 vty_out(vty
, " aggregate-address %s %s",
11500 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11502 inet_ntoa(netmask
));
11504 vty_out(vty
, " aggregate-address %s/%d",
11505 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11510 if (bgp_aggregate
->as_set
)
11511 vty_out(vty
, " as-set");
11513 if (bgp_aggregate
->summary_only
)
11514 vty_out(vty
, " summary-only");
11516 vty_out(vty
, "\n");
11520 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11523 struct bgp_node
*rn
;
11524 struct bgp_distance
*bdistance
;
11526 /* Distance configuration. */
11527 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11528 && bgp
->distance_local
[afi
][safi
]
11529 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11530 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11531 || bgp
->distance_local
[afi
][safi
]
11532 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11533 vty_out(vty
, " distance bgp %d %d %d\n",
11534 bgp
->distance_ebgp
[afi
][safi
],
11535 bgp
->distance_ibgp
[afi
][safi
],
11536 bgp
->distance_local
[afi
][safi
]);
11539 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11540 rn
= bgp_route_next(rn
)) {
11541 bdistance
= bgp_distance_get_node(rn
);
11542 if (bdistance
!= NULL
) {
11543 char buf
[PREFIX_STRLEN
];
11545 vty_out(vty
, " distance %d %s %s\n",
11546 bdistance
->distance
,
11547 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11548 bdistance
->access_list
? bdistance
->access_list
11554 /* Allocate routing table structure and install commands. */
11555 void bgp_route_init(void)
11560 /* Init BGP distance table. */
11561 FOREACH_AFI_SAFI (afi
, safi
)
11562 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11564 /* IPv4 BGP commands. */
11565 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11566 install_element(BGP_NODE
, &bgp_network_cmd
);
11567 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11569 install_element(BGP_NODE
, &aggregate_address_cmd
);
11570 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11571 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11572 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11574 /* IPv4 unicast configuration. */
11575 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11576 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11577 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11579 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11580 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11581 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11582 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11584 /* IPv4 multicast configuration. */
11585 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11586 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11587 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11588 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11589 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11590 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11591 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11593 /* IPv4 labeled-unicast configuration. */
11594 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11595 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11596 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11597 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11598 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11600 install_element(VIEW_NODE
,
11601 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11602 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11603 install_element(VIEW_NODE
,
11604 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11605 #ifdef KEEP_OLD_VPN_COMMANDS
11606 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11607 #endif /* KEEP_OLD_VPN_COMMANDS */
11608 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11609 install_element(VIEW_NODE
,
11610 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11612 /* BGP dampening clear commands */
11613 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11614 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11616 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11617 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11620 install_element(ENABLE_NODE
,
11621 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11622 #ifdef KEEP_OLD_VPN_COMMANDS
11623 install_element(ENABLE_NODE
,
11624 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11625 #endif /* KEEP_OLD_VPN_COMMANDS */
11627 /* New config IPv6 BGP commands. */
11628 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11629 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11630 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11632 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11633 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11635 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11637 install_element(BGP_NODE
, &bgp_distance_cmd
);
11638 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11639 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11640 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11641 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11642 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11643 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11644 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11645 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11646 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11647 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11648 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11649 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11650 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11651 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11652 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11653 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11654 install_element(BGP_IPV4M_NODE
,
11655 &no_bgp_distance_source_access_list_cmd
);
11656 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11657 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11658 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11659 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11660 install_element(BGP_IPV6_NODE
,
11661 &ipv6_bgp_distance_source_access_list_cmd
);
11662 install_element(BGP_IPV6_NODE
,
11663 &no_ipv6_bgp_distance_source_access_list_cmd
);
11664 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11665 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11666 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11667 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11668 install_element(BGP_IPV6M_NODE
,
11669 &ipv6_bgp_distance_source_access_list_cmd
);
11670 install_element(BGP_IPV6M_NODE
,
11671 &no_ipv6_bgp_distance_source_access_list_cmd
);
11673 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11674 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11675 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11676 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11678 /* IPv4 Multicast Mode */
11679 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11680 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11682 /* Large Communities */
11683 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11684 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11686 /* show bgp ipv4 flowspec detailed */
11687 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11691 void bgp_route_finish(void)
11696 FOREACH_AFI_SAFI (afi
, safi
) {
11697 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11698 bgp_distance_table
[afi
][safi
] = NULL
;