1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "sockunion.h"
37 #include "workqueue.h"
42 #include "bgpd/bgpd.h"
43 #include "bgpd/bgp_table.h"
44 #include "bgpd/bgp_route.h"
45 #include "bgpd/bgp_attr.h"
46 #include "bgpd/bgp_debug.h"
47 #include "bgpd/bgp_aspath.h"
48 #include "bgpd/bgp_regex.h"
49 #include "bgpd/bgp_community.h"
50 #include "bgpd/bgp_ecommunity.h"
51 #include "bgpd/bgp_lcommunity.h"
52 #include "bgpd/bgp_clist.h"
53 #include "bgpd/bgp_packet.h"
54 #include "bgpd/bgp_filter.h"
55 #include "bgpd/bgp_fsm.h"
56 #include "bgpd/bgp_mplsvpn.h"
57 #include "bgpd/bgp_nexthop.h"
58 #include "bgpd/bgp_damp.h"
59 #include "bgpd/bgp_advertise.h"
60 #include "bgpd/bgp_zebra.h"
61 #include "bgpd/bgp_vty.h"
62 #include "bgpd/bgp_mpath.h"
63 #include "bgpd/bgp_nht.h"
64 #include "bgpd/bgp_updgrp.h"
65 #include "bgpd/bgp_label.h"
68 #include "bgpd/rfapi/rfapi_backend.h"
69 #include "bgpd/rfapi/vnc_import_bgp.h"
70 #include "bgpd/rfapi/vnc_export_bgp.h"
72 #include "bgpd/bgp_encap_types.h"
73 #include "bgpd/bgp_encap_tlv.h"
74 #include "bgpd/bgp_evpn.h"
75 #include "bgpd/bgp_evpn_vty.h"
76 #include "bgpd/bgp_flowspec.h"
77 #include "bgpd/bgp_flowspec_util.h"
78 #include "bgpd/bgp_pbr.h"
80 #ifndef VTYSH_EXTRACT_PL
81 #include "bgpd/bgp_route_clippy.c"
84 /* Extern from bgp_dump.c */
85 extern const char *bgp_origin_str
[];
86 extern const char *bgp_origin_long_str
[];
89 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
90 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
91 static const struct message bgp_pmsi_tnltype_str
[] = {
92 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
93 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
94 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
95 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
96 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
97 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
98 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
99 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
103 #define VRFID_NONE_STR "-"
105 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
106 safi_t safi
, struct prefix
*p
,
107 struct prefix_rd
*prd
)
110 struct bgp_node
*prn
= NULL
;
116 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
117 || (safi
== SAFI_EVPN
)) {
118 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
120 if (prn
->info
== NULL
)
121 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
123 bgp_unlock_node(prn
);
127 rn
= bgp_node_get(table
, p
);
129 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
130 || (safi
== SAFI_EVPN
))
136 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
137 safi_t safi
, struct prefix
*p
,
138 struct prefix_rd
*prd
)
141 struct bgp_node
*prn
= NULL
;
146 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
147 || (safi
== SAFI_EVPN
)) {
148 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
152 if (prn
->info
== NULL
) {
153 bgp_unlock_node(prn
);
160 rn
= bgp_node_lookup(table
, p
);
165 /* Allocate bgp_info_extra */
166 static struct bgp_info_extra
*bgp_info_extra_new(void)
168 struct bgp_info_extra
*new;
169 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
170 new->label
[0] = MPLS_INVALID_LABEL
;
175 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
177 if (extra
&& *extra
) {
178 if ((*extra
)->damp_info
)
179 bgp_damp_info_free((*extra
)->damp_info
, 0);
181 (*extra
)->damp_info
= NULL
;
183 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
189 /* Get bgp_info extra information for the given bgp_info, lazy allocated
192 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
195 ri
->extra
= bgp_info_extra_new();
199 /* Allocate new bgp info structure. */
200 struct bgp_info
*bgp_info_new(void)
202 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
205 /* Free bgp route information. */
206 static void bgp_info_free(struct bgp_info
*binfo
)
208 /* unlink reference to parent, if any. */
209 if (binfo
->extra
&& binfo
->extra
->parent
) {
210 bgp_info_unlock((struct bgp_info
*)binfo
->extra
->parent
);
211 bgp_unlock_node((struct bgp_node
*)((struct bgp_info
*)binfo
212 ->extra
->parent
)->net
);
213 binfo
->extra
->parent
= NULL
;
217 bgp_attr_unintern(&binfo
->attr
);
219 bgp_unlink_nexthop(binfo
);
220 bgp_info_extra_free(&binfo
->extra
);
221 bgp_info_mpath_free(&binfo
->mpath
);
223 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
225 XFREE(MTYPE_BGP_ROUTE
, binfo
);
228 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
234 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
236 assert(binfo
&& binfo
->lock
> 0);
239 if (binfo
->lock
== 0) {
241 zlog_debug ("%s: unlocked and freeing", __func__
);
242 zlog_backtrace (LOG_DEBUG
);
244 bgp_info_free(binfo
);
249 if (binfo
->lock
== 1)
251 zlog_debug ("%s: unlocked to 1", __func__
);
252 zlog_backtrace (LOG_DEBUG
);
259 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
261 struct bgp_info
*top
;
273 peer_lock(ri
->peer
); /* bgp_info peer reference */
276 /* Do the actual removal of info from RIB, for use by bgp_process
277 completion callback *only* */
278 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
281 ri
->next
->prev
= ri
->prev
;
283 ri
->prev
->next
= ri
->next
;
287 bgp_info_mpath_dequeue(ri
);
292 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
294 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
295 /* set of previous already took care of pcount */
296 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
299 /* undo the effects of a previous call to bgp_info_delete; typically
300 called when a route is deleted and then quickly re-added before the
301 deletion has been processed */
302 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
304 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
305 /* unset of previous already took care of pcount */
306 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
309 /* Adjust pcount as required */
310 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
312 struct bgp_table
*table
;
314 assert(rn
&& bgp_node_table(rn
));
315 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
317 table
= bgp_node_table(rn
);
319 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
322 if (!BGP_INFO_COUNTABLE(ri
)
323 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
325 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
327 /* slight hack, but more robust against errors. */
328 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
329 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
332 "%s: Asked to decrement 0 prefix count for peer %s",
333 __func__
, ri
->peer
->host
);
334 zlog_backtrace(LOG_WARNING
);
335 zlog_warn("%s: Please report to Quagga bugzilla",
338 } else if (BGP_INFO_COUNTABLE(ri
)
339 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
340 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
341 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
345 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
347 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
350 /* Set/unset bgp_info flags, adjusting any other state as needed.
351 * This is here primarily to keep prefix-count in check.
353 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, uint32_t flag
)
355 SET_FLAG(ri
->flags
, flag
);
357 /* early bath if we know it's not a flag that changes countability state
359 if (!CHECK_FLAG(flag
,
360 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
363 bgp_pcount_adjust(rn
, ri
);
366 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
369 UNSET_FLAG(ri
->flags
, flag
);
371 /* early bath if we know it's not a flag that changes countability state
373 if (!CHECK_FLAG(flag
,
374 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
377 bgp_pcount_adjust(rn
, ri
);
380 /* Get MED value. If MED value is missing and "bgp bestpath
381 missing-as-worst" is specified, treat it as the worst value. */
382 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
384 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
387 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
394 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
396 if (ri
->addpath_rx_id
)
397 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
400 sprintf(buf
, "path %s", ri
->peer
->host
);
403 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
405 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
406 struct bgp_info
*exist
, int *paths_eq
,
407 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
408 char *pfx_buf
, afi_t afi
, safi_t safi
)
410 struct attr
*newattr
, *existattr
;
411 bgp_peer_sort_t new_sort
;
412 bgp_peer_sort_t exist_sort
;
418 uint32_t exist_weight
;
419 uint32_t newm
, existm
;
420 struct in_addr new_id
;
421 struct in_addr exist_id
;
424 int internal_as_route
;
427 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
428 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
430 uint32_t exist_mm_seq
;
437 zlog_debug("%s: new is NULL", pfx_buf
);
442 bgp_info_path_with_addpath_rx_str(new, new_buf
);
446 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
452 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
453 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
454 pfx_buf
, new_buf
, new->flags
, exist_buf
,
459 existattr
= exist
->attr
;
461 /* For EVPN routes, we cannot just go by local vs remote, we have to
462 * look at the MAC mobility sequence number, if present.
464 if (safi
== SAFI_EVPN
) {
465 /* This is an error condition described in RFC 7432 Section
467 * states that in this scenario "the PE MUST alert the operator"
469 * does not state what other action to take. In order to provide
471 * consistency in this scenario we are going to prefer the path
475 if (newattr
->sticky
!= existattr
->sticky
) {
477 prefix2str(&new->net
->p
, pfx_buf
,
479 * PREFIX2STR_BUFFER
);
480 bgp_info_path_with_addpath_rx_str(new, new_buf
);
481 bgp_info_path_with_addpath_rx_str(exist
,
485 if (newattr
->sticky
&& !existattr
->sticky
) {
487 "%s: %s wins over %s due to sticky MAC flag",
488 pfx_buf
, new_buf
, exist_buf
);
492 if (!newattr
->sticky
&& existattr
->sticky
) {
494 "%s: %s loses to %s due to sticky MAC flag",
495 pfx_buf
, new_buf
, exist_buf
);
500 new_mm_seq
= mac_mobility_seqnum(newattr
);
501 exist_mm_seq
= mac_mobility_seqnum(existattr
);
503 if (new_mm_seq
> exist_mm_seq
) {
506 "%s: %s wins over %s due to MM seq %u > %u",
507 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
512 if (new_mm_seq
< exist_mm_seq
) {
515 "%s: %s loses to %s due to MM seq %u < %u",
516 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
522 /* 1. Weight check. */
523 new_weight
= newattr
->weight
;
524 exist_weight
= existattr
->weight
;
526 if (new_weight
> exist_weight
) {
528 zlog_debug("%s: %s wins over %s due to weight %d > %d",
529 pfx_buf
, new_buf
, exist_buf
, new_weight
,
534 if (new_weight
< exist_weight
) {
536 zlog_debug("%s: %s loses to %s due to weight %d < %d",
537 pfx_buf
, new_buf
, exist_buf
, new_weight
,
542 /* 2. Local preference check. */
543 new_pref
= exist_pref
= bgp
->default_local_pref
;
545 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
546 new_pref
= newattr
->local_pref
;
547 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
548 exist_pref
= existattr
->local_pref
;
550 if (new_pref
> exist_pref
) {
553 "%s: %s wins over %s due to localpref %d > %d",
554 pfx_buf
, new_buf
, exist_buf
, new_pref
,
559 if (new_pref
< exist_pref
) {
562 "%s: %s loses to %s due to localpref %d < %d",
563 pfx_buf
, new_buf
, exist_buf
, new_pref
,
568 /* 3. Local route check. We prefer:
570 * - BGP_ROUTE_AGGREGATE
571 * - BGP_ROUTE_REDISTRIBUTE
573 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
574 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
577 "%s: %s wins over %s due to preferred BGP_ROUTE type",
578 pfx_buf
, new_buf
, exist_buf
);
582 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
583 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
586 "%s: %s loses to %s due to preferred BGP_ROUTE type",
587 pfx_buf
, new_buf
, exist_buf
);
591 /* 4. AS path length check. */
592 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
593 int exist_hops
= aspath_count_hops(existattr
->aspath
);
594 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
596 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
599 aspath_hops
= aspath_count_hops(newattr
->aspath
);
600 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
602 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
605 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
606 pfx_buf
, new_buf
, exist_buf
,
608 (exist_hops
+ exist_confeds
));
612 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
615 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
616 pfx_buf
, new_buf
, exist_buf
,
618 (exist_hops
+ exist_confeds
));
622 int newhops
= aspath_count_hops(newattr
->aspath
);
624 if (newhops
< exist_hops
) {
627 "%s: %s wins over %s due to aspath hopcount %d < %d",
628 pfx_buf
, new_buf
, exist_buf
,
629 newhops
, exist_hops
);
633 if (newhops
> exist_hops
) {
636 "%s: %s loses to %s due to aspath hopcount %d > %d",
637 pfx_buf
, new_buf
, exist_buf
,
638 newhops
, exist_hops
);
644 /* 5. Origin check. */
645 if (newattr
->origin
< existattr
->origin
) {
647 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
648 pfx_buf
, new_buf
, exist_buf
,
649 bgp_origin_long_str
[newattr
->origin
],
650 bgp_origin_long_str
[existattr
->origin
]);
654 if (newattr
->origin
> existattr
->origin
) {
656 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
657 pfx_buf
, new_buf
, exist_buf
,
658 bgp_origin_long_str
[newattr
->origin
],
659 bgp_origin_long_str
[existattr
->origin
]);
664 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
665 && aspath_count_hops(existattr
->aspath
) == 0);
666 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
667 && aspath_count_confeds(existattr
->aspath
) > 0
668 && aspath_count_hops(newattr
->aspath
) == 0
669 && aspath_count_hops(existattr
->aspath
) == 0);
671 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
672 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
673 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
674 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
675 || internal_as_route
) {
676 new_med
= bgp_med_value(new->attr
, bgp
);
677 exist_med
= bgp_med_value(exist
->attr
, bgp
);
679 if (new_med
< exist_med
) {
682 "%s: %s wins over %s due to MED %d < %d",
683 pfx_buf
, new_buf
, exist_buf
, new_med
,
688 if (new_med
> exist_med
) {
691 "%s: %s loses to %s due to MED %d > %d",
692 pfx_buf
, new_buf
, exist_buf
, new_med
,
698 /* 7. Peer type check. */
699 new_sort
= new->peer
->sort
;
700 exist_sort
= exist
->peer
->sort
;
702 if (new_sort
== BGP_PEER_EBGP
703 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
706 "%s: %s wins over %s due to eBGP peer > iBGP peer",
707 pfx_buf
, new_buf
, exist_buf
);
711 if (exist_sort
== BGP_PEER_EBGP
712 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
715 "%s: %s loses to %s due to iBGP peer < eBGP peer",
716 pfx_buf
, new_buf
, exist_buf
);
720 /* 8. IGP metric check. */
724 newm
= new->extra
->igpmetric
;
726 existm
= exist
->extra
->igpmetric
;
731 "%s: %s wins over %s due to IGP metric %d < %d",
732 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
739 "%s: %s loses to %s due to IGP metric %d > %d",
740 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
744 /* 9. Same IGP metric. Compare the cluster list length as
745 representative of IGP hops metric. Rewrite the metric value
746 pair (newm, existm) with the cluster list length. Prefer the
747 path with smaller cluster list length. */
748 if (newm
== existm
) {
749 if (peer_sort(new->peer
) == BGP_PEER_IBGP
750 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
751 && (mpath_cfg
== NULL
753 mpath_cfg
->ibgp_flags
,
754 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
755 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
756 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
761 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
762 pfx_buf
, new_buf
, exist_buf
,
770 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
771 pfx_buf
, new_buf
, exist_buf
,
778 /* 10. confed-external vs. confed-internal */
779 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
780 if (new_sort
== BGP_PEER_CONFED
781 && exist_sort
== BGP_PEER_IBGP
) {
784 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
785 pfx_buf
, new_buf
, exist_buf
);
789 if (exist_sort
== BGP_PEER_CONFED
790 && new_sort
== BGP_PEER_IBGP
) {
793 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
794 pfx_buf
, new_buf
, exist_buf
);
799 /* 11. Maximum path check. */
800 if (newm
== existm
) {
801 /* If one path has a label but the other does not, do not treat
802 * them as equals for multipath
804 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
806 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
809 "%s: %s and %s cannot be multipath, one has a label while the other does not",
810 pfx_buf
, new_buf
, exist_buf
);
811 } else if (bgp_flag_check(bgp
,
812 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
815 * For the two paths, all comparison steps till IGP
817 * have succeeded - including AS_PATH hop count. Since
819 * bestpath as-path multipath-relax' knob is on, we
821 * an exact match of AS_PATH. Thus, mark the paths are
823 * That will trigger both these paths to get into the
831 "%s: %s and %s are equal via multipath-relax",
832 pfx_buf
, new_buf
, exist_buf
);
833 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
834 if (aspath_cmp(new->attr
->aspath
,
835 exist
->attr
->aspath
)) {
840 "%s: %s and %s are equal via matching aspaths",
841 pfx_buf
, new_buf
, exist_buf
);
843 } else if (new->peer
->as
== exist
->peer
->as
) {
848 "%s: %s and %s are equal via same remote-as",
849 pfx_buf
, new_buf
, exist_buf
);
853 * TODO: If unequal cost ibgp multipath is enabled we can
854 * mark the paths as equal here instead of returning
859 "%s: %s wins over %s after IGP metric comparison",
860 pfx_buf
, new_buf
, exist_buf
);
863 "%s: %s loses to %s after IGP metric comparison",
864 pfx_buf
, new_buf
, exist_buf
);
869 /* 12. If both paths are external, prefer the path that was received
870 first (the oldest one). This step minimizes route-flap, since a
871 newer path won't displace an older one, even if it was the
872 preferred route based on the additional decision criteria below. */
873 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
874 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
875 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
878 "%s: %s wins over %s due to oldest external",
879 pfx_buf
, new_buf
, exist_buf
);
883 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
886 "%s: %s loses to %s due to oldest external",
887 pfx_buf
, new_buf
, exist_buf
);
892 /* 13. Router-ID comparision. */
893 /* If one of the paths is "stale", the corresponding peer router-id will
894 * be 0 and would always win over the other path. If originator id is
895 * used for the comparision, it will decide which path is better.
897 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
898 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
900 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
901 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
902 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
904 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
906 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
909 "%s: %s wins over %s due to Router-ID comparison",
910 pfx_buf
, new_buf
, exist_buf
);
914 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
917 "%s: %s loses to %s due to Router-ID comparison",
918 pfx_buf
, new_buf
, exist_buf
);
922 /* 14. Cluster length comparision. */
923 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
924 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
926 if (new_cluster
< exist_cluster
) {
929 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
930 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
935 if (new_cluster
> exist_cluster
) {
938 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
939 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
944 /* 15. Neighbor address comparision. */
945 /* Do this only if neither path is "stale" as stale paths do not have
946 * valid peer information (as the connection may or may not be up).
948 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
951 "%s: %s wins over %s due to latter path being STALE",
952 pfx_buf
, new_buf
, exist_buf
);
956 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
959 "%s: %s loses to %s due to former path being STALE",
960 pfx_buf
, new_buf
, exist_buf
);
964 /* locally configured routes to advertise do not have su_remote */
965 if (new->peer
->su_remote
== NULL
)
967 if (exist
->peer
->su_remote
== NULL
)
970 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
975 "%s: %s loses to %s due to Neighor IP comparison",
976 pfx_buf
, new_buf
, exist_buf
);
983 "%s: %s wins over %s due to Neighor IP comparison",
984 pfx_buf
, new_buf
, exist_buf
);
989 zlog_debug("%s: %s wins over %s due to nothing left to compare",
990 pfx_buf
, new_buf
, exist_buf
);
995 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
996 * is preferred, or 0 if they are the same (usually will only occur if
997 * multipath is enabled
998 * This version is compatible with */
999 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
1000 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
1005 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
1019 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1020 struct attr
*attr
, afi_t afi
,
1023 struct bgp_filter
*filter
;
1025 filter
= &peer
->filter
[afi
][safi
];
1027 #define FILTER_EXIST_WARN(F, f, filter) \
1028 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1029 zlog_warn("%s: Could not find configured input %s-list %s!", \
1030 peer->host, #f, F##_IN_NAME(filter));
1032 if (DISTRIBUTE_IN_NAME(filter
)) {
1033 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1035 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1039 if (PREFIX_LIST_IN_NAME(filter
)) {
1040 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1042 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1046 if (FILTER_LIST_IN_NAME(filter
)) {
1047 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1049 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1054 return FILTER_PERMIT
;
1055 #undef FILTER_EXIST_WARN
1058 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1059 struct attr
*attr
, afi_t afi
,
1062 struct bgp_filter
*filter
;
1064 filter
= &peer
->filter
[afi
][safi
];
1066 #define FILTER_EXIST_WARN(F, f, filter) \
1067 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1068 zlog_warn("%s: Could not find configured output %s-list %s!", \
1069 peer->host, #f, F##_OUT_NAME(filter));
1071 if (DISTRIBUTE_OUT_NAME(filter
)) {
1072 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1074 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1078 if (PREFIX_LIST_OUT_NAME(filter
)) {
1079 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1081 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1086 if (FILTER_LIST_OUT_NAME(filter
)) {
1087 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1089 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1094 return FILTER_PERMIT
;
1095 #undef FILTER_EXIST_WARN
1098 /* If community attribute includes no_export then return 1. */
1099 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1101 if (attr
->community
) {
1102 /* NO_ADVERTISE check. */
1103 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1106 /* NO_EXPORT check. */
1107 if (peer
->sort
== BGP_PEER_EBGP
1108 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1111 /* NO_EXPORT_SUBCONFED check. */
1112 if (peer
->sort
== BGP_PEER_EBGP
1113 || peer
->sort
== BGP_PEER_CONFED
)
1114 if (community_include(attr
->community
,
1115 COMMUNITY_NO_EXPORT_SUBCONFED
))
1121 /* Route reflection loop check. */
1122 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1124 struct in_addr cluster_id
;
1126 if (attr
->cluster
) {
1127 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1128 cluster_id
= peer
->bgp
->cluster_id
;
1130 cluster_id
= peer
->bgp
->router_id
;
1132 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1138 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1139 struct attr
*attr
, afi_t afi
, safi_t safi
,
1140 const char *rmap_name
)
1142 struct bgp_filter
*filter
;
1143 struct bgp_info info
;
1144 route_map_result_t ret
;
1145 struct route_map
*rmap
= NULL
;
1147 filter
= &peer
->filter
[afi
][safi
];
1149 /* Apply default weight value. */
1150 if (peer
->weight
[afi
][safi
])
1151 attr
->weight
= peer
->weight
[afi
][safi
];
1154 rmap
= route_map_lookup_by_name(rmap_name
);
1159 if (ROUTE_MAP_IN_NAME(filter
)) {
1160 rmap
= ROUTE_MAP_IN(filter
);
1167 /* Route map apply. */
1169 /* Duplicate current value to new strucutre for modification. */
1173 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1175 /* Apply BGP route map to the attribute. */
1176 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1178 peer
->rmap_type
= 0;
1180 if (ret
== RMAP_DENYMATCH
) {
1181 /* Free newly generated AS path and community by
1183 bgp_attr_flush(attr
);
1190 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1191 struct attr
*attr
, afi_t afi
, safi_t safi
,
1192 const char *rmap_name
)
1194 struct bgp_info info
;
1195 route_map_result_t ret
;
1196 struct route_map
*rmap
= NULL
;
1200 * So if we get to this point and have no rmap_name
1201 * we want to just show the output as it currently
1207 /* Apply default weight value. */
1208 if (peer
->weight
[afi
][safi
])
1209 attr
->weight
= peer
->weight
[afi
][safi
];
1211 rmap
= route_map_lookup_by_name(rmap_name
);
1214 * If we have a route map name and we do not find
1215 * the routemap that means we have an implicit
1221 /* Route map apply. */
1222 /* Duplicate current value to new strucutre for modification. */
1226 rmap_type
= peer
->rmap_type
;
1227 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1229 /* Apply BGP route map to the attribute. */
1230 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1232 peer
->rmap_type
= rmap_type
;
1234 if (ret
== RMAP_DENYMATCH
)
1236 * caller has multiple error paths with bgp_attr_flush()
1243 /* If this is an EBGP peer with remove-private-AS */
1244 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1245 struct peer
*peer
, struct attr
*attr
)
1247 if (peer
->sort
== BGP_PEER_EBGP
1248 && (peer_af_flag_check(peer
, afi
, safi
,
1249 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1250 || peer_af_flag_check(peer
, afi
, safi
,
1251 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1252 || peer_af_flag_check(peer
, afi
, safi
,
1253 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1254 || peer_af_flag_check(peer
, afi
, safi
,
1255 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1256 // Take action on the entire aspath
1257 if (peer_af_flag_check(peer
, afi
, safi
,
1258 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1259 || peer_af_flag_check(peer
, afi
, safi
,
1260 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1261 if (peer_af_flag_check(
1263 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1264 attr
->aspath
= aspath_replace_private_asns(
1265 attr
->aspath
, bgp
->as
);
1267 // The entire aspath consists of private ASNs so create
1269 else if (aspath_private_as_check(attr
->aspath
))
1270 attr
->aspath
= aspath_empty_get();
1272 // There are some public and some private ASNs, remove
1275 attr
->aspath
= aspath_remove_private_asns(
1279 // 'all' was not specified so the entire aspath must be private
1281 // for us to do anything
1282 else if (aspath_private_as_check(attr
->aspath
)) {
1283 if (peer_af_flag_check(
1285 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1286 attr
->aspath
= aspath_replace_private_asns(
1287 attr
->aspath
, bgp
->as
);
1289 attr
->aspath
= aspath_empty_get();
1294 /* If this is an EBGP peer with as-override */
1295 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1296 struct peer
*peer
, struct attr
*attr
)
1298 if (peer
->sort
== BGP_PEER_EBGP
1299 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1300 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1301 attr
->aspath
= aspath_replace_specific_asn(
1302 attr
->aspath
, peer
->as
, bgp
->as
);
1306 void bgp_attr_add_gshut_community(struct attr
*attr
)
1308 struct community
*old
;
1309 struct community
*new;
1310 struct community
*merge
;
1311 struct community
*gshut
;
1313 old
= attr
->community
;
1314 gshut
= community_str2com("graceful-shutdown");
1317 merge
= community_merge(community_dup(old
), gshut
);
1319 if (old
->refcnt
== 0)
1320 community_free(old
);
1322 new = community_uniq_sort(merge
);
1323 community_free(merge
);
1325 new = community_dup(gshut
);
1328 community_free(gshut
);
1329 attr
->community
= new;
1330 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1332 /* When we add the graceful-shutdown community we must also
1333 * lower the local-preference */
1334 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1335 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1339 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1341 if (family
== AF_INET
) {
1342 attr
->nexthop
.s_addr
= 0;
1343 attr
->mp_nexthop_global_in
.s_addr
= 0;
1345 if (family
== AF_INET6
)
1346 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1347 if (family
== AF_EVPN
)
1348 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1351 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1352 struct update_subgroup
*subgrp
, struct prefix
*p
,
1355 struct bgp_filter
*filter
;
1358 struct peer
*onlypeer
;
1360 struct attr
*riattr
;
1361 char buf
[PREFIX_STRLEN
];
1367 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1369 if (DISABLE_BGP_ANNOUNCE
)
1372 afi
= SUBGRP_AFI(subgrp
);
1373 safi
= SUBGRP_SAFI(subgrp
);
1374 peer
= SUBGRP_PEER(subgrp
);
1376 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1377 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1380 filter
= &peer
->filter
[afi
][safi
];
1381 bgp
= SUBGRP_INST(subgrp
);
1382 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1385 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1386 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1387 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1390 * direct and direct_ext type routes originate internally even
1391 * though they can have peer pointers that reference other
1394 prefix2str(p
, buf
, PREFIX_STRLEN
);
1395 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1401 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1402 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1403 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1404 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1406 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1411 /* With addpath we may be asked to TX all kinds of paths so make sure
1413 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1414 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1415 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1419 /* If this is not the bestpath then check to see if there is an enabled
1421 * feature that requires us to advertise it */
1422 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1423 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1428 /* Aggregate-address suppress check. */
1429 if (ri
->extra
&& ri
->extra
->suppress
)
1430 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1435 * If we are doing VRF 2 VRF leaking via the import
1436 * statement, we want to prevent the route going
1437 * off box as that the RT and RD created are localy
1438 * significant and globaly useless.
1440 if (safi
== SAFI_MPLS_VPN
&& ri
->extra
&& ri
->extra
->num_labels
1441 && ri
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1444 /* If it's labeled safi, make sure the route has a valid label. */
1445 if (safi
== SAFI_LABELED_UNICAST
) {
1446 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1447 if (!bgp_is_valid_label(&label
)) {
1448 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1449 zlog_debug("u%" PRIu64
":s%" PRIu64
1450 " %s/%d is filtered - no label (%p)",
1451 subgrp
->update_group
->id
, subgrp
->id
,
1452 inet_ntop(p
->family
, &p
->u
.prefix
,
1453 buf
, SU_ADDRSTRLEN
),
1454 p
->prefixlen
, &label
);
1459 /* Do not send back route to sender. */
1460 if (onlypeer
&& from
== onlypeer
) {
1464 /* Do not send the default route in the BGP table if the neighbor is
1465 * configured for default-originate */
1466 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1467 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1468 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1470 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1474 /* Transparency check. */
1475 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1476 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1481 /* If community is not disabled check the no-export and local. */
1482 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1483 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1485 "subgrpannouncecheck: community filter check fail");
1489 /* If the attribute has originator-id and it is same as remote
1491 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1492 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1493 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1495 "%s [Update:SEND] %s originator-id is same as "
1498 prefix2str(p
, buf
, sizeof(buf
)));
1502 /* ORF prefix-list filter check */
1503 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1504 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1505 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1506 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1507 if (peer
->orf_plist
[afi
][safi
]) {
1508 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1510 if (bgp_debug_update(NULL
, p
,
1511 subgrp
->update_group
, 0))
1513 "%s [Update:SEND] %s is filtered via ORF",
1521 /* Output filter check. */
1522 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1523 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1524 zlog_debug("%s [Update:SEND] %s is filtered",
1525 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1529 #ifdef BGP_SEND_ASPATH_CHECK
1530 /* AS path loop check. */
1531 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1532 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1534 "%s [Update:SEND] suppress announcement to peer AS %u "
1535 "that is part of AS path.",
1536 onlypeer
->host
, onlypeer
->as
);
1539 #endif /* BGP_SEND_ASPATH_CHECK */
1541 /* If we're a CONFED we need to loop check the CONFED ID too */
1542 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1543 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1544 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1546 "%s [Update:SEND] suppress announcement to peer AS %u"
1548 peer
->host
, bgp
->confed_id
);
1553 /* Route-Reflect check. */
1554 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1559 /* IBGP reflection check. */
1560 if (reflect
&& !samepeer_safe
) {
1561 /* A route from a Client peer. */
1562 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1563 PEER_FLAG_REFLECTOR_CLIENT
)) {
1564 /* Reflect to all the Non-Client peers and also to the
1565 Client peers other than the originator. Originator
1567 is already done. So there is noting to do. */
1568 /* no bgp client-to-client reflection check. */
1569 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1570 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1571 PEER_FLAG_REFLECTOR_CLIENT
))
1574 /* A route from a Non-client peer. Reflect to all other
1576 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1577 PEER_FLAG_REFLECTOR_CLIENT
))
1582 /* For modify attribute, copy it to temporary structure. */
1583 bgp_attr_dup(attr
, riattr
);
1585 /* If local-preference is not set. */
1586 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1587 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1588 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1589 attr
->local_pref
= bgp
->default_local_pref
;
1592 /* If originator-id is not set and the route is to be reflected,
1593 set the originator id */
1595 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1596 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1597 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1600 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1602 if (peer
->sort
== BGP_PEER_EBGP
1603 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1604 if (from
!= bgp
->peer_self
&& !transparent
1605 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1606 PEER_FLAG_MED_UNCHANGED
))
1608 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1611 /* Since the nexthop attribute can vary per peer, it is not explicitly
1613 * in announce check, only certain flags and length (or number of
1615 * -- for IPv6/MP_REACH) are set here in order to guide the update
1617 * code in setting the nexthop(s) on a per peer basis in
1619 * Typically, the source nexthop in the attribute is preserved but in
1621 * scenarios where we know it will always be overwritten, we reset the
1622 * nexthop to "0" in an attempt to achieve better Update packing. An
1623 * example of this is when a prefix from each of 2 IBGP peers needs to
1625 * announced to an EBGP peer (and they have the same attributes barring
1629 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1631 #define NEXTHOP_IS_V6 \
1632 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1633 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1634 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1635 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1637 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1639 * the peer (group) is configured to receive link-local nexthop
1641 * and it is available in the prefix OR we're not reflecting the route
1643 * the peer (group) to whom we're going to announce is on a shared
1645 * and this is either a self-originated route or the peer is EBGP.
1647 if (NEXTHOP_IS_V6
) {
1648 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1649 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1650 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1651 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1652 || (!reflect
&& peer
->shared_network
1653 && (from
== bgp
->peer_self
1654 || peer
->sort
== BGP_PEER_EBGP
))) {
1655 attr
->mp_nexthop_len
=
1656 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1659 /* Clear off link-local nexthop in source, whenever it is not
1661 * ensure more prefixes share the same attribute for
1664 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1665 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1666 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1669 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1670 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1672 /* Route map & unsuppress-map apply. */
1673 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1674 struct bgp_info info
;
1675 struct bgp_info_extra dummy_info_extra
;
1676 struct attr dummy_attr
;
1682 memcpy(&dummy_info_extra
, ri
->extra
,
1683 sizeof(struct bgp_info_extra
));
1684 info
.extra
= &dummy_info_extra
;
1687 /* don't confuse inbound and outbound setting */
1688 RESET_FLAG(attr
->rmap_change_flags
);
1691 * The route reflector is not allowed to modify the attributes
1692 * of the reflected IBGP routes unless explicitly allowed.
1694 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1695 && !bgp_flag_check(bgp
,
1696 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1697 bgp_attr_dup(&dummy_attr
, attr
);
1698 info
.attr
= &dummy_attr
;
1701 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1703 if (ri
->extra
&& ri
->extra
->suppress
)
1704 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1707 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1710 peer
->rmap_type
= 0;
1712 if (ret
== RMAP_DENYMATCH
) {
1713 bgp_attr_flush(attr
);
1718 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1719 if (peer
->sort
== BGP_PEER_IBGP
1720 || peer
->sort
== BGP_PEER_CONFED
) {
1721 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1722 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1724 bgp_attr_add_gshut_community(attr
);
1728 /* After route-map has been applied, we check to see if the nexthop to
1729 * be carried in the attribute (that is used for the announcement) can
1730 * be cleared off or not. We do this in all cases where we would be
1731 * setting the nexthop to "ourselves". For IPv6, we only need to
1733 * the global nexthop here; the link-local nexthop would have been
1735 * already, and if not, it is required by the update formation code.
1736 * Also see earlier comments in this function.
1739 * If route-map has performed some operation on the nexthop or the peer
1740 * configuration says to pass it unchanged, we cannot reset the nexthop
1741 * here, so only attempt to do it if these aren't true. Note that the
1742 * route-map handler itself might have cleared the nexthop, if for
1744 * it is configured as 'peer-address'.
1746 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1747 riattr
->rmap_change_flags
)
1749 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1750 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1751 /* We can reset the nexthop, if setting (or forcing) it to
1753 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1754 PEER_FLAG_NEXTHOP_SELF
)
1755 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1756 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1758 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1759 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1760 subgroup_announce_reset_nhop(
1761 (peer_cap_enhe(peer
, afi
, safi
)
1765 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1766 /* Can also reset the nexthop if announcing to EBGP, but
1768 * no peer in the subgroup is on a shared subnet.
1769 * Note: 3rd party nexthop currently implemented for
1772 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1774 subgroup_announce_reset_nhop(
1775 (peer_cap_enhe(peer
, afi
, safi
)
1779 } else if (CHECK_FLAG(ri
->flags
, BGP_INFO_ANNC_NH_SELF
)) {
1781 * This flag is used for leaked vpn-vrf routes
1783 int family
= p
->family
;
1785 if (peer_cap_enhe(peer
, afi
, safi
))
1788 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1790 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1791 __func__
, family2str(family
));
1792 subgroup_announce_reset_nhop(family
, attr
);
1795 /* If IPv6/MP and nexthop does not have any override and happens
1797 * be a link-local address, reset it so that we don't pass along
1799 * source's link-local IPv6 address to recipients who may not be
1801 * the same interface.
1803 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1804 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1805 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1812 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1813 struct bgp_maxpaths_cfg
*mpath_cfg
,
1814 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1816 struct bgp_info
*new_select
;
1817 struct bgp_info
*old_select
;
1818 struct bgp_info
*ri
;
1819 struct bgp_info
*ri1
;
1820 struct bgp_info
*ri2
;
1821 struct bgp_info
*nextri
= NULL
;
1822 int paths_eq
, do_mpath
, debug
;
1823 struct list mp_list
;
1824 char pfx_buf
[PREFIX2STR_BUFFER
];
1825 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1827 bgp_mp_list_init(&mp_list
);
1829 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1831 debug
= bgp_debug_bestpath(&rn
->p
);
1834 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1836 /* bgp deterministic-med */
1838 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1840 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1841 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1842 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1844 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1845 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1847 if (BGP_INFO_HOLDDOWN(ri1
))
1849 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1850 if (ri1
->peer
->status
!= Established
)
1855 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1856 if (CHECK_FLAG(ri2
->flags
,
1857 BGP_INFO_DMED_CHECK
))
1859 if (BGP_INFO_HOLDDOWN(ri2
))
1862 && ri2
->peer
!= bgp
->peer_self
1865 PEER_STATUS_NSF_WAIT
))
1866 if (ri2
->peer
->status
1870 if (aspath_cmp_left(ri1
->attr
->aspath
,
1872 || aspath_cmp_left_confed(
1874 ri2
->attr
->aspath
)) {
1875 if (bgp_info_cmp(bgp
, ri2
,
1881 bgp_info_unset_flag(
1883 BGP_INFO_DMED_SELECTED
);
1889 BGP_INFO_DMED_CHECK
);
1893 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1894 bgp_info_set_flag(rn
, new_select
,
1895 BGP_INFO_DMED_SELECTED
);
1898 bgp_info_path_with_addpath_rx_str(new_select
,
1900 zlog_debug("%s: %s is the bestpath from AS %u",
1902 aspath_get_first_as(
1903 new_select
->attr
->aspath
));
1908 /* Check old selected route and new selected route. */
1911 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1913 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1916 if (BGP_INFO_HOLDDOWN(ri
)) {
1917 /* reap REMOVED routes, if needs be
1918 * selected route must stay for a while longer though
1920 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1921 && (ri
!= old_select
))
1922 bgp_info_reap(rn
, ri
);
1925 zlog_debug("%s: ri %p in holddown", __func__
,
1931 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1932 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1933 if (ri
->peer
->status
!= Established
) {
1937 "%s: ri %p non self peer %s not estab state",
1938 __func__
, ri
, ri
->peer
->host
);
1943 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1944 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1945 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1947 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1951 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1953 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1954 debug
, pfx_buf
, afi
, safi
)) {
1959 /* Now that we know which path is the bestpath see if any of the other
1961 * qualify as multipaths
1965 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1967 sprintf(path_buf
, "NONE");
1969 "%s: After path selection, newbest is %s oldbest was %s",
1971 old_select
? old_select
->peer
->host
: "NONE");
1974 if (do_mpath
&& new_select
) {
1975 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1979 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1981 if (ri
== new_select
) {
1984 "%s: %s is the bestpath, add to the multipath list",
1986 bgp_mp_list_add(&mp_list
, ri
);
1990 if (BGP_INFO_HOLDDOWN(ri
))
1993 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1994 && !CHECK_FLAG(ri
->peer
->sflags
,
1995 PEER_STATUS_NSF_WAIT
))
1996 if (ri
->peer
->status
!= Established
)
1999 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
2002 "%s: %s has the same nexthop as the bestpath, skip it",
2007 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
2008 debug
, pfx_buf
, afi
, safi
);
2013 "%s: %s is equivalent to the bestpath, add to the multipath list",
2015 bgp_mp_list_add(&mp_list
, ri
);
2020 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
2021 bgp_info_mpath_aggregate_update(new_select
, old_select
);
2022 bgp_mp_list_clear(&mp_list
);
2024 result
->old
= old_select
;
2025 result
->new = new_select
;
2031 * A new route/change in bestpath of an existing route. Evaluate the path
2032 * for advertisement to the subgroup.
2034 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2035 struct bgp_info
*selected
,
2036 struct bgp_node
*rn
,
2037 uint32_t addpath_tx_id
)
2040 struct peer
*onlypeer
;
2046 afi
= SUBGRP_AFI(subgrp
);
2047 safi
= SUBGRP_SAFI(subgrp
);
2048 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2051 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2052 char buf_prefix
[PREFIX_STRLEN
];
2053 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2054 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2058 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2059 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2060 PEER_STATUS_ORF_WAIT_REFRESH
))
2063 memset(&attr
, 0, sizeof(struct attr
));
2064 /* It's initialized in bgp_announce_check() */
2066 /* Announcement to the subgroup. If the route is filtered withdraw it.
2069 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2070 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2072 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2073 selected
->addpath_tx_id
);
2076 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2078 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2085 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2086 * This is called at the end of route processing.
2088 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2090 struct bgp_info
*ri
;
2092 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2093 if (BGP_INFO_HOLDDOWN(ri
))
2095 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2096 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2101 * Has the route changed from the RIB's perspective? This is invoked only
2102 * if the route selection returns the same best route as earlier - to
2103 * determine if we need to update zebra or not.
2105 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2107 struct bgp_info
*mpinfo
;
2109 /* If this is multipath, check all selected paths for any nexthop
2110 * change or attribute change. Some attribute changes (e.g., community)
2111 * aren't of relevance to the RIB, but we'll update zebra to ensure
2112 * we handle the case of BGP nexthop change. This is the behavior
2113 * when the best path has an attribute change anyway.
2115 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2116 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2120 * If this is multipath, check all selected paths for any nexthop change
2122 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2123 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2124 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2125 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2129 /* Nothing has changed from the RIB's perspective. */
2133 struct bgp_process_queue
{
2135 STAILQ_HEAD(, bgp_node
) pqueue
;
2136 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2138 unsigned int queued
;
2142 * old_select = The old best path
2143 * new_select = the new best path
2145 * if (!old_select && new_select)
2146 * We are sending new information on.
2148 * if (old_select && new_select) {
2149 * if (new_select != old_select)
2150 * We have a new best path send a change
2152 * We've received a update with new attributes that needs
2156 * if (old_select && !new_select)
2157 * We have no eligible route that we can announce or the rn
2160 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2161 afi_t afi
, safi_t safi
)
2163 struct prefix
*p
= &rn
->p
;
2164 struct bgp_info
*new_select
;
2165 struct bgp_info
*old_select
;
2166 struct bgp_info_pair old_and_new
;
2167 char pfx_buf
[PREFIX2STR_BUFFER
];
2170 /* Is it end of initial update? (after startup) */
2172 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2173 sizeof(bgp
->update_delay_zebra_resume_time
));
2175 bgp
->main_zebra_update_hold
= 0;
2176 FOREACH_AFI_SAFI (afi
, safi
) {
2177 if (bgp_fibupd_safi(safi
))
2178 bgp_zebra_announce_table(bgp
, afi
, safi
);
2180 bgp
->main_peers_update_hold
= 0;
2182 bgp_start_routeadv(bgp
);
2186 debug
= bgp_debug_bestpath(&rn
->p
);
2188 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2189 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2190 afi2str(afi
), safi2str(safi
));
2193 /* Best path selection. */
2194 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2196 old_select
= old_and_new
.old
;
2197 new_select
= old_and_new
.new;
2199 /* Do we need to allocate or free labels?
2200 * Right now, since we only deal with per-prefix labels, it is not
2201 * necessary to do this upon changes to best path except if the label
2204 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2207 || bgp_label_index_differs(new_select
, old_select
)
2208 || new_select
->sub_type
!= old_select
->sub_type
) {
2209 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2210 && new_select
->attr
->flag
2212 BGP_ATTR_PREFIX_SID
)
2213 && new_select
->attr
->label_index
2214 != BGP_INVALID_LABEL_INDEX
) {
2217 BGP_NODE_REGISTERED_FOR_LABEL
))
2218 bgp_unregister_for_label(rn
);
2219 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2221 bgp_set_valid_label(&rn
->local_label
);
2223 bgp_register_for_label(rn
, new_select
);
2225 } else if (CHECK_FLAG(rn
->flags
,
2226 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2227 bgp_unregister_for_label(rn
);
2229 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2230 bgp_unregister_for_label(rn
);
2234 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2236 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2237 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2238 old_select
, new_select
);
2241 /* If best route remains the same and this is not due to user-initiated
2242 * clear, see exactly what needs to be done.
2244 if (old_select
&& old_select
== new_select
2245 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2246 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2247 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2248 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2250 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2251 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2253 if (bgp_fibupd_safi(safi
)
2254 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2256 if (new_select
->type
== ZEBRA_ROUTE_BGP
2257 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2258 || new_select
->sub_type
2259 == BGP_ROUTE_IMPORTED
))
2261 bgp_zebra_announce(rn
, p
, old_select
,
2265 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2266 bgp_zebra_clear_route_change_flags(rn
);
2268 /* If there is a change of interest to peers, reannounce the
2270 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2271 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2272 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2274 /* unicast routes must also be annouced to
2275 * labeled-unicast update-groups */
2276 if (safi
== SAFI_UNICAST
)
2277 group_announce_route(bgp
, afi
,
2278 SAFI_LABELED_UNICAST
, rn
,
2281 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2282 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2285 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2289 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2291 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2293 /* bestpath has changed; bump version */
2294 if (old_select
|| new_select
) {
2295 bgp_bump_version(rn
);
2297 if (!bgp
->t_rmap_def_originate_eval
) {
2301 update_group_refresh_default_originate_route_map
,
2302 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2303 &bgp
->t_rmap_def_originate_eval
);
2308 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2311 zlog_debug("%s: setting SELECTED flag", __func__
);
2312 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2313 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2314 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2318 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2319 if (old_select
!= new_select
) {
2321 vnc_import_bgp_exterior_del_route(bgp
, p
,
2323 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2326 vnc_import_bgp_exterior_add_route(bgp
, p
,
2328 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2334 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2336 /* unicast routes must also be annouced to labeled-unicast update-groups
2338 if (safi
== SAFI_UNICAST
)
2339 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2343 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2344 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2345 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2346 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2347 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2348 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2350 /* if this is an evpn imported type-5 prefix,
2351 * we need to withdraw the route first to clear
2352 * the nh neigh and the RMAC entry.
2355 is_route_parent_evpn(old_select
))
2356 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2358 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2360 /* Withdraw the route from the kernel. */
2361 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2362 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2363 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2364 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2366 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2370 /* advertise/withdraw type-5 routes */
2371 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2372 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2373 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2375 /* apply the route-map */
2376 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2379 ret
= route_map_apply(
2380 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2381 &rn
->p
, RMAP_BGP
, new_select
);
2382 if (ret
== RMAP_MATCH
)
2383 bgp_evpn_advertise_type5_route(
2384 bgp
, &rn
->p
, new_select
->attr
,
2387 bgp_evpn_advertise_type5_route(bgp
,
2393 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2394 (!old_select
->extra
|| !old_select
->extra
->parent
))
2395 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2398 /* Clear any route change flags. */
2399 bgp_zebra_clear_route_change_flags(rn
);
2401 /* Reap old select bgp_info, if it has been removed */
2402 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2403 bgp_info_reap(rn
, old_select
);
2405 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2409 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2411 struct bgp_process_queue
*pqnode
= data
;
2412 struct bgp
*bgp
= pqnode
->bgp
;
2413 struct bgp_table
*table
;
2414 struct bgp_node
*rn
;
2417 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2418 bgp_process_main_one(bgp
, NULL
, 0, 0);
2419 /* should always have dedicated wq call */
2420 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2424 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2425 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2426 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2427 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2428 table
= bgp_node_table(rn
);
2429 /* note, new RNs may be added as part of processing */
2430 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2432 bgp_unlock_node(rn
);
2433 bgp_table_unlock(table
);
2439 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2441 struct bgp_process_queue
*pqnode
= data
;
2443 bgp_unlock(pqnode
->bgp
);
2445 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2448 void bgp_process_queue_init(void)
2450 if (!bm
->process_main_queue
) {
2451 bm
->process_main_queue
=
2452 work_queue_new(bm
->master
, "process_main_queue");
2454 if (!bm
->process_main_queue
) {
2455 zlog_err("%s: Failed to allocate work queue", __func__
);
2460 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2461 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2462 bm
->process_main_queue
->spec
.max_retries
= 0;
2463 bm
->process_main_queue
->spec
.hold
= 50;
2464 /* Use a higher yield value of 50ms for main queue processing */
2465 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2468 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2470 struct bgp_process_queue
*pqnode
;
2472 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2473 sizeof(struct bgp_process_queue
));
2475 /* unlocked in bgp_processq_del */
2476 pqnode
->bgp
= bgp_lock(bgp
);
2477 STAILQ_INIT(&pqnode
->pqueue
);
2482 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2484 #define ARBITRARY_PROCESS_QLEN 10000
2485 struct work_queue
*wq
= bm
->process_main_queue
;
2486 struct bgp_process_queue
*pqnode
;
2487 int pqnode_reuse
= 0;
2489 /* already scheduled for processing? */
2490 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2496 /* Add route nodes to an existing work queue item until reaching the
2497 limit only if is from the same BGP view and it's not an EOIU marker
2499 if (work_queue_item_count(wq
)) {
2500 struct work_queue_item
*item
= work_queue_last_item(wq
);
2501 pqnode
= item
->data
;
2503 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2504 || pqnode
->bgp
!= bgp
2505 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2506 pqnode
= bgp_processq_alloc(bgp
);
2510 pqnode
= bgp_processq_alloc(bgp
);
2511 /* all unlocked in bgp_process_wq */
2512 bgp_table_lock(bgp_node_table(rn
));
2514 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2517 /* can't be enqueued twice */
2518 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2519 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2523 work_queue_add(wq
, pqnode
);
2528 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2530 struct bgp_process_queue
*pqnode
;
2532 if (bm
->process_main_queue
== NULL
)
2535 pqnode
= bgp_processq_alloc(bgp
);
2537 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2538 work_queue_add(bm
->process_main_queue
, pqnode
);
2541 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2545 peer
= THREAD_ARG(thread
);
2546 peer
->t_pmax_restart
= NULL
;
2548 if (bgp_debug_neighbor_events(peer
))
2550 "%s Maximum-prefix restart timer expired, restore peering",
2553 peer_clear(peer
, NULL
);
2558 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2562 iana_safi_t pkt_safi
;
2564 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2567 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2568 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2569 PEER_STATUS_PREFIX_LIMIT
)
2574 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2576 afi_safi_print(afi
, safi
), peer
->host
,
2577 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2578 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2580 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2581 PEER_FLAG_MAX_PREFIX_WARNING
))
2584 /* Convert AFI, SAFI to values for packet. */
2585 pkt_afi
= afi_int2iana(afi
);
2586 pkt_safi
= safi_int2iana(safi
);
2590 ndata
[0] = (pkt_afi
>> 8);
2592 ndata
[2] = pkt_safi
;
2593 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2594 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2595 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2596 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2598 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2599 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2600 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2604 /* Dynamic peers will just close their connection. */
2605 if (peer_dynamic_neighbor(peer
))
2608 /* restart timer start */
2609 if (peer
->pmax_restart
[afi
][safi
]) {
2610 peer
->v_pmax_restart
=
2611 peer
->pmax_restart
[afi
][safi
] * 60;
2613 if (bgp_debug_neighbor_events(peer
))
2615 "%s Maximum-prefix restart timer started for %d secs",
2616 peer
->host
, peer
->v_pmax_restart
);
2618 BGP_TIMER_ON(peer
->t_pmax_restart
,
2619 bgp_maximum_prefix_restart_timer
,
2620 peer
->v_pmax_restart
);
2625 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2626 PEER_STATUS_PREFIX_LIMIT
);
2628 if (peer
->pcount
[afi
][safi
]
2629 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2630 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2631 PEER_STATUS_PREFIX_THRESHOLD
)
2636 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2637 afi_safi_print(afi
, safi
), peer
->host
,
2638 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2639 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2640 PEER_STATUS_PREFIX_THRESHOLD
);
2642 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2643 PEER_STATUS_PREFIX_THRESHOLD
);
2647 /* Unconditionally remove the route from the RIB, without taking
2648 * damping into consideration (eg, because the session went down)
2650 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2651 afi_t afi
, safi_t safi
)
2653 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2655 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2656 bgp_info_delete(rn
, ri
); /* keep historical info */
2658 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2661 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2662 struct peer
*peer
, afi_t afi
, safi_t safi
,
2663 struct prefix_rd
*prd
)
2665 int status
= BGP_DAMP_NONE
;
2667 /* apply dampening, if result is suppressed, we'll be retaining
2668 * the bgp_info in the RIB for historical reference.
2670 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2671 && peer
->sort
== BGP_PEER_EBGP
)
2672 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2673 == BGP_DAMP_SUPPRESSED
) {
2674 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2680 if (safi
== SAFI_MPLS_VPN
) {
2681 struct bgp_node
*prn
= NULL
;
2682 struct bgp_table
*table
= NULL
;
2684 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2685 (struct prefix
*)prd
);
2687 table
= (struct bgp_table
*)(prn
->info
);
2689 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2690 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2692 bgp_unlock_node(prn
);
2694 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2695 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2697 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2698 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2704 /* If this is an EVPN route, process for un-import. */
2705 if (safi
== SAFI_EVPN
)
2706 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2708 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2711 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2712 struct peer
*peer
, struct attr
*attr
,
2713 struct bgp_node
*rn
)
2715 struct bgp_info
*new;
2717 /* Make new BGP info. */
2718 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2720 new->instance
= instance
;
2721 new->sub_type
= sub_type
;
2724 new->uptime
= bgp_clock();
2726 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2730 static void overlay_index_update(struct attr
*attr
,
2731 struct eth_segment_id
*eth_s_id
,
2732 union gw_addr
*gw_ip
)
2737 if (eth_s_id
== NULL
) {
2738 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2739 sizeof(struct eth_segment_id
));
2741 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2742 sizeof(struct eth_segment_id
));
2744 if (gw_ip
== NULL
) {
2745 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2747 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2748 sizeof(union gw_addr
));
2752 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2753 struct eth_segment_id
*eth_s_id
,
2754 union gw_addr
*gw_ip
)
2756 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2757 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2760 if (afi
!= AFI_L2VPN
)
2763 memset(&temp
, 0, 16);
2764 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2765 info_gw_ip
= (union gw_addr
*)&temp
;
2766 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2769 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2770 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2773 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2775 info_gw_ip_remote
= gw_ip
;
2776 if (eth_s_id
== NULL
)
2777 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2779 info_eth_s_id_remote
= eth_s_id
;
2780 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2782 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2783 sizeof(struct eth_segment_id
));
2786 /* Check if received nexthop is valid or not. */
2787 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2792 /* Only validated for unicast and multicast currently. */
2793 /* Also valid for EVPN where the nexthop is an IP address. */
2794 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2797 /* If NEXT_HOP is present, validate it. */
2798 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2799 if (attr
->nexthop
.s_addr
== 0
2800 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2801 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2805 /* If MP_NEXTHOP is present, validate it. */
2806 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2807 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2808 * it is not an IPv6 link-local address.
2810 if (attr
->mp_nexthop_len
) {
2811 switch (attr
->mp_nexthop_len
) {
2812 case BGP_ATTR_NHLEN_IPV4
:
2813 case BGP_ATTR_NHLEN_VPNV4
:
2814 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2815 || IPV4_CLASS_DE(ntohl(
2816 attr
->mp_nexthop_global_in
.s_addr
))
2817 || bgp_nexthop_self(bgp
,
2818 attr
->mp_nexthop_global_in
));
2821 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2822 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2823 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2824 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2825 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2826 || IN6_IS_ADDR_MULTICAST(
2827 &attr
->mp_nexthop_global
));
2839 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2840 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2841 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2842 uint32_t num_labels
, int soft_reconfig
,
2843 struct bgp_route_evpn
*evpn
)
2846 int aspath_loop_count
= 0;
2847 struct bgp_node
*rn
;
2849 struct attr new_attr
;
2850 struct attr
*attr_new
;
2851 struct bgp_info
*ri
;
2852 struct bgp_info
*new;
2853 struct bgp_info_extra
*extra
;
2855 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2857 int do_loop_check
= 1;
2858 int has_valid_label
= 0;
2860 int vnc_implicit_withdraw
= 0;
2864 memset(&new_attr
, 0, sizeof(struct attr
));
2865 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2866 new_attr
.label
= MPLS_INVALID_LABEL
;
2869 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2870 /* TODO: Check to see if we can get rid of "is_valid_label" */
2871 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2872 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2874 has_valid_label
= bgp_is_valid_label(label
);
2876 /* When peer's soft reconfiguration enabled. Record input packet in
2879 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2880 && peer
!= bgp
->peer_self
)
2881 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2883 /* Check previously received route. */
2884 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2885 if (ri
->peer
== peer
&& ri
->type
== type
2886 && ri
->sub_type
== sub_type
2887 && ri
->addpath_rx_id
== addpath_id
)
2890 /* AS path local-as loop check. */
2891 if (peer
->change_local_as
) {
2892 if (peer
->allowas_in
[afi
][safi
])
2893 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2894 else if (!CHECK_FLAG(peer
->flags
,
2895 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2896 aspath_loop_count
= 1;
2898 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2899 > aspath_loop_count
) {
2900 reason
= "as-path contains our own AS;";
2905 /* If the peer is configured for "allowas-in origin" and the last ASN in
2907 * as-path is our ASN then we do not need to call aspath_loop_check
2909 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2910 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2913 /* AS path loop check. */
2914 if (do_loop_check
) {
2915 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2916 > peer
->allowas_in
[afi
][safi
]
2917 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2918 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2919 > peer
->allowas_in
[afi
][safi
])) {
2920 reason
= "as-path contains our own AS;";
2925 /* Route reflector originator ID check. */
2926 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2927 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2928 reason
= "originator is us;";
2932 /* Route reflector cluster ID check. */
2933 if (bgp_cluster_filter(peer
, attr
)) {
2934 reason
= "reflected from the same cluster;";
2938 /* Apply incoming filter. */
2939 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2944 bgp_attr_dup(&new_attr
, attr
);
2946 /* Apply incoming route-map.
2947 * NB: new_attr may now contain newly allocated values from route-map
2949 * commands, so we need bgp_attr_flush in the error paths, until we
2951 * the attr (which takes over the memory references) */
2952 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2954 reason
= "route-map;";
2955 bgp_attr_flush(&new_attr
);
2959 if (peer
->sort
== BGP_PEER_EBGP
) {
2961 /* If we receive the graceful-shutdown community from an eBGP
2962 * peer we must lower local-preference */
2963 if (new_attr
.community
2964 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2965 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2966 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2968 /* If graceful-shutdown is configured then add the GSHUT
2969 * community to all paths received from eBGP peers */
2970 } else if (bgp_flag_check(peer
->bgp
,
2971 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2972 bgp_attr_add_gshut_community(&new_attr
);
2976 /* next hop check. */
2977 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2978 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2979 reason
= "martian or self next-hop;";
2980 bgp_attr_flush(&new_attr
);
2984 attr_new
= bgp_attr_intern(&new_attr
);
2986 /* If the update is implicit withdraw. */
2988 ri
->uptime
= bgp_clock();
2989 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2991 /* Same attribute comes in. */
2992 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2993 && attrhash_cmp(ri
->attr
, attr_new
)
2994 && (!has_valid_label
2995 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2996 num_labels
* sizeof(mpls_label_t
))
2998 && (overlay_index_equal(
2999 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3000 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3001 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3002 BGP_CONFIG_DAMPENING
)
3003 && peer
->sort
== BGP_PEER_EBGP
3004 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3005 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3006 bgp_debug_rdpfxpath2str(
3007 afi
, safi
, prd
, p
, label
,
3008 num_labels
, addpath_id
? 1 : 0,
3009 addpath_id
, pfx_buf
,
3011 zlog_debug("%s rcvd %s", peer
->host
,
3015 if (bgp_damp_update(ri
, rn
, afi
, safi
)
3016 != BGP_DAMP_SUPPRESSED
) {
3017 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
3019 bgp_process(bgp
, rn
, afi
, safi
);
3021 } else /* Duplicate - odd */
3023 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3024 if (!peer
->rcvd_attr_printed
) {
3026 "%s rcvd UPDATE w/ attr: %s",
3028 peer
->rcvd_attr_str
);
3029 peer
->rcvd_attr_printed
= 1;
3032 bgp_debug_rdpfxpath2str(
3033 afi
, safi
, prd
, p
, label
,
3034 num_labels
, addpath_id
? 1 : 0,
3035 addpath_id
, pfx_buf
,
3038 "%s rcvd %s...duplicate ignored",
3039 peer
->host
, pfx_buf
);
3042 /* graceful restart STALE flag unset. */
3043 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3044 bgp_info_unset_flag(rn
, ri
,
3046 bgp_process(bgp
, rn
, afi
, safi
);
3050 bgp_unlock_node(rn
);
3051 bgp_attr_unintern(&attr_new
);
3056 /* Withdraw/Announce before we fully processed the withdraw */
3057 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3058 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3059 bgp_debug_rdpfxpath2str(
3060 afi
, safi
, prd
, p
, label
, num_labels
,
3061 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3064 "%s rcvd %s, flapped quicker than processing",
3065 peer
->host
, pfx_buf
);
3068 bgp_info_restore(rn
, ri
);
3071 /* Received Logging. */
3072 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3073 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3074 num_labels
, addpath_id
? 1 : 0,
3075 addpath_id
, pfx_buf
,
3077 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3080 /* graceful restart STALE flag unset. */
3081 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3082 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3084 /* The attribute is changed. */
3085 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3087 /* implicit withdraw, decrement aggregate and pcount here.
3088 * only if update is accepted, they'll increment below.
3090 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3092 /* Update bgp route dampening information. */
3093 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3094 && peer
->sort
== BGP_PEER_EBGP
) {
3095 /* This is implicit withdraw so we should update
3098 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3099 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3102 if (safi
== SAFI_MPLS_VPN
) {
3103 struct bgp_node
*prn
= NULL
;
3104 struct bgp_table
*table
= NULL
;
3106 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3107 (struct prefix
*)prd
);
3109 table
= (struct bgp_table
*)(prn
->info
);
3111 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3112 bgp
, prd
, table
, p
, ri
);
3114 bgp_unlock_node(prn
);
3116 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3117 && (safi
== SAFI_UNICAST
)) {
3118 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3120 * Implicit withdraw case.
3122 ++vnc_implicit_withdraw
;
3123 vnc_import_bgp_del_route(bgp
, p
, ri
);
3124 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3129 /* Special handling for EVPN update of an existing route. If the
3130 * extended community attribute has changed, we need to
3132 * the route using its existing extended community. It will be
3133 * subsequently processed for import with the new extended
3136 if (safi
== SAFI_EVPN
&& !same_attr
) {
3138 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3140 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3143 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3144 attr_new
->ecommunity
);
3146 if (bgp_debug_update(peer
, p
, NULL
, 1))
3148 "Change in EXT-COMM, existing %s new %s",
3150 ri
->attr
->ecommunity
),
3152 attr_new
->ecommunity
));
3153 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3159 /* Update to new attribute. */
3160 bgp_attr_unintern(&ri
->attr
);
3161 ri
->attr
= attr_new
;
3163 /* Update MPLS label */
3164 if (has_valid_label
) {
3165 extra
= bgp_info_extra_get(ri
);
3166 memcpy(&extra
->label
, label
,
3167 num_labels
* sizeof(mpls_label_t
));
3168 extra
->num_labels
= num_labels
;
3169 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3170 bgp_set_valid_label(&extra
->label
[0]);
3174 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3175 && (safi
== SAFI_UNICAST
)) {
3176 if (vnc_implicit_withdraw
) {
3178 * Add back the route with its new attributes
3180 * The route is still selected, until the route
3182 * queued by bgp_process actually runs. We have
3184 * update to the VNC side immediately to avoid
3186 * configuration changes (e.g., route-map
3188 * trigger re-importation of the entire RIB.
3190 vnc_import_bgp_add_route(bgp
, p
, ri
);
3191 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3195 /* Update Overlay Index */
3196 if (afi
== AFI_L2VPN
) {
3197 overlay_index_update(
3198 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3199 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3202 /* Update bgp route dampening information. */
3203 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3204 && peer
->sort
== BGP_PEER_EBGP
) {
3205 /* Now we do normal update dampening. */
3206 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3207 if (ret
== BGP_DAMP_SUPPRESSED
) {
3208 bgp_unlock_node(rn
);
3213 /* Nexthop reachability check - for unicast and
3214 * labeled-unicast.. */
3215 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3216 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3217 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3218 && !CHECK_FLAG(peer
->flags
,
3219 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3221 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3226 struct bgp
*bgp_nexthop
= bgp
;
3228 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3229 bgp_nexthop
= ri
->extra
->bgp_orig
;
3231 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3232 ri
, NULL
, connected
)
3233 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3234 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3236 if (BGP_DEBUG(nht
, NHT
)) {
3237 char buf1
[INET6_ADDRSTRLEN
];
3239 (const void *)&attr_new
3241 buf1
, INET6_ADDRSTRLEN
);
3242 zlog_debug("%s(%s): NH unresolved",
3243 __FUNCTION__
, buf1
);
3245 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3248 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3251 if (safi
== SAFI_MPLS_VPN
) {
3252 struct bgp_node
*prn
= NULL
;
3253 struct bgp_table
*table
= NULL
;
3255 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3256 (struct prefix
*)prd
);
3258 table
= (struct bgp_table
*)(prn
->info
);
3260 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3261 bgp
, prd
, table
, p
, ri
);
3263 bgp_unlock_node(prn
);
3267 /* If this is an EVPN route and some attribute has changed,
3269 * route for import. If the extended community has changed, we
3271 * have done the un-import earlier and the import would result
3273 * route getting injected into appropriate L2 VNIs. If it is
3275 * some other attribute change, the import will result in
3277 * the attributes for the route in the VNI(s).
3279 if (safi
== SAFI_EVPN
&& !same_attr
)
3280 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3282 /* Process change. */
3283 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3285 bgp_process(bgp
, rn
, afi
, safi
);
3286 bgp_unlock_node(rn
);
3288 if (SAFI_UNICAST
== safi
3289 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3290 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3292 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3294 if ((SAFI_MPLS_VPN
== safi
)
3295 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3297 vpn_leak_to_vrf_update(bgp
, ri
);
3301 if (SAFI_MPLS_VPN
== safi
) {
3302 mpls_label_t label_decoded
= decode_label(label
);
3304 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3305 type
, sub_type
, &label_decoded
);
3307 if (SAFI_ENCAP
== safi
) {
3308 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3309 type
, sub_type
, NULL
);
3314 } // End of implicit withdraw
3316 /* Received Logging. */
3317 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3318 if (!peer
->rcvd_attr_printed
) {
3319 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3320 peer
->rcvd_attr_str
);
3321 peer
->rcvd_attr_printed
= 1;
3324 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3325 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3327 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3330 /* Make new BGP info. */
3331 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3333 /* Update MPLS label */
3334 if (has_valid_label
) {
3335 extra
= bgp_info_extra_get(new);
3336 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3337 extra
->num_labels
= num_labels
;
3338 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3339 bgp_set_valid_label(&extra
->label
[0]);
3342 /* Update Overlay Index */
3343 if (afi
== AFI_L2VPN
) {
3344 overlay_index_update(new->attr
,
3345 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3346 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3348 /* Nexthop reachability check. */
3349 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3350 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3351 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3352 && !CHECK_FLAG(peer
->flags
,
3353 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3354 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3359 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3360 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3361 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3363 if (BGP_DEBUG(nht
, NHT
)) {
3364 char buf1
[INET6_ADDRSTRLEN
];
3366 (const void *)&attr_new
->nexthop
,
3367 buf1
, INET6_ADDRSTRLEN
);
3368 zlog_debug("%s(%s): NH unresolved",
3369 __FUNCTION__
, buf1
);
3371 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3374 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3377 new->addpath_rx_id
= addpath_id
;
3379 /* Increment prefix */
3380 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3382 /* Register new BGP information. */
3383 bgp_info_add(rn
, new);
3385 /* route_node_get lock */
3386 bgp_unlock_node(rn
);
3389 if (safi
== SAFI_MPLS_VPN
) {
3390 struct bgp_node
*prn
= NULL
;
3391 struct bgp_table
*table
= NULL
;
3393 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3395 table
= (struct bgp_table
*)(prn
->info
);
3397 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3398 bgp
, prd
, table
, p
, new);
3400 bgp_unlock_node(prn
);
3404 /* If maximum prefix count is configured and current prefix
3406 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3409 /* If this is an EVPN route, process for import. */
3410 if (safi
== SAFI_EVPN
)
3411 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3413 /* Process change. */
3414 bgp_process(bgp
, rn
, afi
, safi
);
3416 if (SAFI_UNICAST
== safi
3417 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3418 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3419 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3421 if ((SAFI_MPLS_VPN
== safi
)
3422 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3424 vpn_leak_to_vrf_update(bgp
, new);
3427 if (SAFI_MPLS_VPN
== safi
) {
3428 mpls_label_t label_decoded
= decode_label(label
);
3430 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3431 sub_type
, &label_decoded
);
3433 if (SAFI_ENCAP
== safi
) {
3434 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3441 /* This BGP update is filtered. Log the reason then update BGP
3444 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3445 if (!peer
->rcvd_attr_printed
) {
3446 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3447 peer
->rcvd_attr_str
);
3448 peer
->rcvd_attr_printed
= 1;
3451 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3452 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3454 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3455 peer
->host
, pfx_buf
, reason
);
3459 /* If this is an EVPN route, un-import it as it is now filtered.
3461 if (safi
== SAFI_EVPN
)
3462 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3464 if (SAFI_UNICAST
== safi
3465 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3466 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3468 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3470 if ((SAFI_MPLS_VPN
== safi
)
3471 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3473 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3476 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3479 bgp_unlock_node(rn
);
3483 * Filtered update is treated as an implicit withdrawal (see
3485 * a few lines above)
3487 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3488 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3496 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3497 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3498 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3499 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3502 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3503 struct bgp_node
*rn
;
3504 struct bgp_info
*ri
;
3507 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3508 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3516 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3518 /* If peer is soft reconfiguration enabled. Record input packet for
3519 * further calculation.
3521 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3522 * routes that are filtered. This tanks out Quagga RS pretty badly due
3524 * the iteration over all RS clients.
3525 * Since we need to remove the entry from adj_in anyway, do that first
3527 * if there was no entry, we don't need to do anything more.
3529 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3530 && peer
!= bgp
->peer_self
)
3531 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3532 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3533 bgp_debug_rdpfxpath2str(
3534 afi
, safi
, prd
, p
, label
, num_labels
,
3535 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3538 "%s withdrawing route %s not in adj-in",
3539 peer
->host
, pfx_buf
);
3541 bgp_unlock_node(rn
);
3545 /* Lookup withdrawn route. */
3546 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3547 if (ri
->peer
== peer
&& ri
->type
== type
3548 && ri
->sub_type
== sub_type
3549 && ri
->addpath_rx_id
== addpath_id
)
3553 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3554 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3555 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3557 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3561 /* Withdraw specified route from routing table. */
3562 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3563 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3564 if (SAFI_UNICAST
== safi
3565 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3566 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3567 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3569 if ((SAFI_MPLS_VPN
== safi
)
3570 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3572 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3574 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3575 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3576 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3578 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3581 /* Unlock bgp_node_get() lock. */
3582 bgp_unlock_node(rn
);
3587 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3590 struct update_subgroup
*subgrp
;
3591 subgrp
= peer_subgroup(peer
, afi
, safi
);
3592 subgroup_default_originate(subgrp
, withdraw
);
3597 * bgp_stop_announce_route_timer
3599 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3601 if (!paf
->t_announce_route
)
3604 THREAD_TIMER_OFF(paf
->t_announce_route
);
3608 * bgp_announce_route_timer_expired
3610 * Callback that is invoked when the route announcement timer for a
3613 static int bgp_announce_route_timer_expired(struct thread
*t
)
3615 struct peer_af
*paf
;
3618 paf
= THREAD_ARG(t
);
3621 if (peer
->status
!= Established
)
3624 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3627 peer_af_announce_route(paf
, 1);
3632 * bgp_announce_route
3634 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3636 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3638 struct peer_af
*paf
;
3639 struct update_subgroup
*subgrp
;
3641 paf
= peer_af_find(peer
, afi
, safi
);
3644 subgrp
= PAF_SUBGRP(paf
);
3647 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3648 * or a refresh has already been triggered.
3650 if (!subgrp
|| paf
->t_announce_route
)
3654 * Start a timer to stagger/delay the announce. This serves
3655 * two purposes - announcement can potentially be combined for
3656 * multiple peers and the announcement doesn't happen in the
3659 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3660 (subgrp
->peer_count
== 1)
3661 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3662 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3663 &paf
->t_announce_route
);
3667 * Announce routes from all AF tables to a peer.
3669 * This should ONLY be called when there is a need to refresh the
3670 * routes to the peer based on a policy change for this peer alone
3671 * or a route refresh request received from the peer.
3672 * The operation will result in splitting the peer from its existing
3673 * subgroups and putting it in new subgroups.
3675 void bgp_announce_route_all(struct peer
*peer
)
3680 FOREACH_AFI_SAFI (afi
, safi
)
3681 bgp_announce_route(peer
, afi
, safi
);
3684 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3685 struct bgp_table
*table
,
3686 struct prefix_rd
*prd
)
3689 struct bgp_node
*rn
;
3690 struct bgp_adj_in
*ain
;
3693 table
= peer
->bgp
->rib
[afi
][safi
];
3695 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3696 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3697 if (ain
->peer
!= peer
)
3700 struct bgp_info
*ri
= rn
->info
;
3701 uint32_t num_labels
= 0;
3702 mpls_label_t
*label_pnt
= NULL
;
3704 if (ri
&& ri
->extra
)
3705 num_labels
= ri
->extra
->num_labels
;
3707 label_pnt
= &ri
->extra
->label
[0];
3709 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3710 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3711 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3712 num_labels
, 1, NULL
);
3715 bgp_unlock_node(rn
);
3721 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3723 struct bgp_node
*rn
;
3724 struct bgp_table
*table
;
3726 if (peer
->status
!= Established
)
3729 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3730 && (safi
!= SAFI_EVPN
))
3731 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3733 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3734 rn
= bgp_route_next(rn
))
3735 if ((table
= rn
->info
) != NULL
) {
3736 struct prefix_rd prd
;
3737 prd
.family
= AF_UNSPEC
;
3739 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3741 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3747 struct bgp_clear_node_queue
{
3748 struct bgp_node
*rn
;
3751 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3753 struct bgp_clear_node_queue
*cnq
= data
;
3754 struct bgp_node
*rn
= cnq
->rn
;
3755 struct peer
*peer
= wq
->spec
.data
;
3756 struct bgp_info
*ri
;
3758 afi_t afi
= bgp_node_table(rn
)->afi
;
3759 safi_t safi
= bgp_node_table(rn
)->safi
;
3764 /* It is possible that we have multiple paths for a prefix from a peer
3765 * if that peer is using AddPath.
3767 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3768 if (ri
->peer
!= peer
)
3771 /* graceful restart STALE flag set. */
3772 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3773 && peer
->nsf
[afi
][safi
]
3774 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3775 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3776 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3778 /* If this is an EVPN route, process for
3780 if (safi
== SAFI_EVPN
)
3781 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3783 /* Handle withdraw for VRF route-leaking and L3VPN */
3784 if (SAFI_UNICAST
== safi
3785 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3786 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3787 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3790 if (SAFI_MPLS_VPN
== safi
&&
3791 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3792 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3795 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3801 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3803 struct bgp_clear_node_queue
*cnq
= data
;
3804 struct bgp_node
*rn
= cnq
->rn
;
3805 struct bgp_table
*table
= bgp_node_table(rn
);
3807 bgp_unlock_node(rn
);
3808 bgp_table_unlock(table
);
3809 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3812 static void bgp_clear_node_complete(struct work_queue
*wq
)
3814 struct peer
*peer
= wq
->spec
.data
;
3816 /* Tickle FSM to start moving again */
3817 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3819 peer_unlock(peer
); /* bgp_clear_route */
3822 static void bgp_clear_node_queue_init(struct peer
*peer
)
3824 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3826 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3827 #undef CLEAR_QUEUE_NAME_LEN
3829 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3831 zlog_err("%s: Failed to allocate work queue", __func__
);
3834 peer
->clear_node_queue
->spec
.hold
= 10;
3835 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3836 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3837 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3838 peer
->clear_node_queue
->spec
.max_retries
= 0;
3840 /* we only 'lock' this peer reference when the queue is actually active
3842 peer
->clear_node_queue
->spec
.data
= peer
;
3845 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3846 struct bgp_table
*table
)
3848 struct bgp_node
*rn
;
3849 int force
= bm
->process_main_queue
? 0 : 1;
3852 table
= peer
->bgp
->rib
[afi
][safi
];
3854 /* If still no table => afi/safi isn't configured at all or smth. */
3858 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3859 struct bgp_info
*ri
, *next
;
3860 struct bgp_adj_in
*ain
;
3861 struct bgp_adj_in
*ain_next
;
3863 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3864 * queued for every clearing peer, regardless of whether it is
3865 * relevant to the peer at hand.
3867 * Overview: There are 3 different indices which need to be
3868 * scrubbed, potentially, when a peer is removed:
3870 * 1 peer's routes visible via the RIB (ie accepted routes)
3871 * 2 peer's routes visible by the (optional) peer's adj-in index
3872 * 3 other routes visible by the peer's adj-out index
3874 * 3 there is no hurry in scrubbing, once the struct peer is
3875 * removed from bgp->peer, we could just GC such deleted peer's
3876 * adj-outs at our leisure.
3878 * 1 and 2 must be 'scrubbed' in some way, at least made
3879 * invisible via RIB index before peer session is allowed to be
3880 * brought back up. So one needs to know when such a 'search' is
3885 * - there'd be a single global queue or a single RIB walker
3886 * - rather than tracking which route_nodes still need to be
3887 * examined on a peer basis, we'd track which peers still
3890 * Given that our per-peer prefix-counts now should be reliable,
3891 * this may actually be achievable. It doesn't seem to be a huge
3892 * problem at this time,
3894 * It is possible that we have multiple paths for a prefix from
3896 * if that peer is using AddPath.
3900 ain_next
= ain
->next
;
3902 if (ain
->peer
== peer
) {
3903 bgp_adj_in_remove(rn
, ain
);
3904 bgp_unlock_node(rn
);
3910 for (ri
= rn
->info
; ri
; ri
= next
) {
3912 if (ri
->peer
!= peer
)
3916 bgp_info_reap(rn
, ri
);
3918 struct bgp_clear_node_queue
*cnq
;
3920 /* both unlocked in bgp_clear_node_queue_del */
3921 bgp_table_lock(bgp_node_table(rn
));
3924 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3925 sizeof(struct bgp_clear_node_queue
));
3927 work_queue_add(peer
->clear_node_queue
, cnq
);
3935 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3937 struct bgp_node
*rn
;
3938 struct bgp_table
*table
;
3940 if (peer
->clear_node_queue
== NULL
)
3941 bgp_clear_node_queue_init(peer
);
3943 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3944 * Idle until it receives a Clearing_Completed event. This protects
3945 * against peers which flap faster than we can we clear, which could
3948 * a) race with routes from the new session being installed before
3949 * clear_route_node visits the node (to delete the route of that
3951 * b) resource exhaustion, clear_route_node likely leads to an entry
3952 * on the process_main queue. Fast-flapping could cause that queue
3956 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3957 * the unlock will happen upon work-queue completion; other wise, the
3958 * unlock happens at the end of this function.
3960 if (!peer
->clear_node_queue
->thread
)
3963 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3964 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3966 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3967 rn
= bgp_route_next(rn
))
3968 if ((table
= rn
->info
) != NULL
)
3969 bgp_clear_route_table(peer
, afi
, safi
, table
);
3971 /* unlock if no nodes got added to the clear-node-queue. */
3972 if (!peer
->clear_node_queue
->thread
)
3976 void bgp_clear_route_all(struct peer
*peer
)
3981 FOREACH_AFI_SAFI (afi
, safi
)
3982 bgp_clear_route(peer
, afi
, safi
);
3985 rfapiProcessPeerDown(peer
);
3989 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3991 struct bgp_table
*table
;
3992 struct bgp_node
*rn
;
3993 struct bgp_adj_in
*ain
;
3994 struct bgp_adj_in
*ain_next
;
3996 table
= peer
->bgp
->rib
[afi
][safi
];
3998 /* It is possible that we have multiple paths for a prefix from a peer
3999 * if that peer is using AddPath.
4001 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4005 ain_next
= ain
->next
;
4007 if (ain
->peer
== peer
) {
4008 bgp_adj_in_remove(rn
, ain
);
4009 bgp_unlock_node(rn
);
4017 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4019 struct bgp_node
*rn
;
4020 struct bgp_info
*ri
;
4021 struct bgp_table
*table
;
4023 if (safi
== SAFI_MPLS_VPN
) {
4024 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4025 rn
= bgp_route_next(rn
)) {
4026 struct bgp_node
*rm
;
4027 struct bgp_info
*ri
;
4029 /* look for neighbor in tables */
4030 if ((table
= rn
->info
) == NULL
)
4033 for (rm
= bgp_table_top(table
); rm
;
4034 rm
= bgp_route_next(rm
))
4035 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4036 if (ri
->peer
!= peer
)
4038 if (!CHECK_FLAG(ri
->flags
,
4042 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4047 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4048 rn
= bgp_route_next(rn
))
4049 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4050 if (ri
->peer
!= peer
)
4052 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4054 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4060 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4063 struct bgp_node
*rn
;
4064 struct bgp_info
*ri
;
4065 struct bgp_info
*next
;
4067 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4068 for (ri
= rn
->info
; ri
; ri
= next
) {
4070 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4071 && ri
->type
== ZEBRA_ROUTE_BGP
4072 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4073 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4074 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4076 if (bgp_fibupd_safi(safi
))
4077 bgp_zebra_withdraw(&rn
->p
, ri
,
4079 bgp_info_reap(rn
, ri
);
4084 /* Delete all kernel routes. */
4085 void bgp_cleanup_routes(struct bgp
*bgp
)
4088 struct bgp_node
*rn
;
4090 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4091 if (afi
== AFI_L2VPN
)
4093 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4096 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4098 if (afi
!= AFI_L2VPN
) {
4100 safi
= SAFI_MPLS_VPN
;
4101 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4102 rn
= bgp_route_next(rn
)) {
4104 bgp_cleanup_table(bgp
,
4105 (struct bgp_table
*)(rn
->info
),
4107 bgp_table_finish((struct bgp_table
**)&(
4110 bgp_unlock_node(rn
);
4114 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4115 rn
= bgp_route_next(rn
)) {
4117 bgp_cleanup_table(bgp
,
4118 (struct bgp_table
*)(rn
->info
),
4120 bgp_table_finish((struct bgp_table
**)&(
4123 bgp_unlock_node(rn
);
4128 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4129 rn
= bgp_route_next(rn
)) {
4131 bgp_cleanup_table(bgp
,
4132 (struct bgp_table
*)(rn
->info
),
4134 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4136 bgp_unlock_node(rn
);
4141 void bgp_reset(void)
4144 bgp_zclient_reset();
4145 access_list_reset();
4146 prefix_list_reset();
4149 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4151 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4152 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4153 PEER_CAP_ADDPATH_AF_TX_RCV
));
4156 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4158 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4159 struct bgp_nlri
*packet
)
4168 int addpath_encoded
;
4169 uint32_t addpath_id
;
4172 lim
= pnt
+ packet
->length
;
4174 safi
= packet
->safi
;
4176 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4178 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4179 syntactic validity. If the field is syntactically incorrect,
4180 then the Error Subcode is set to Invalid Network Field. */
4181 for (; pnt
< lim
; pnt
+= psize
) {
4182 /* Clear prefix structure. */
4183 memset(&p
, 0, sizeof(struct prefix
));
4185 if (addpath_encoded
) {
4187 /* When packet overflow occurs return immediately. */
4188 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4191 addpath_id
= ntohl(*((uint32_t *)pnt
));
4192 pnt
+= BGP_ADDPATH_ID_LEN
;
4195 /* Fetch prefix length. */
4196 p
.prefixlen
= *pnt
++;
4197 /* afi/safi validity already verified by caller,
4198 * bgp_update_receive */
4199 p
.family
= afi2family(afi
);
4201 /* Prefix length check. */
4202 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4204 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
4205 peer
->host
, p
.prefixlen
, packet
->afi
);
4209 /* Packet size overflow check. */
4210 psize
= PSIZE(p
.prefixlen
);
4212 /* When packet overflow occur return immediately. */
4213 if (pnt
+ psize
> lim
) {
4215 "%s [Error] Update packet error (prefix length %d overflows packet)",
4216 peer
->host
, p
.prefixlen
);
4220 /* Defensive coding, double-check the psize fits in a struct
4222 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4224 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4225 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4229 /* Fetch prefix from NLRI packet. */
4230 memcpy(&p
.u
.prefix
, pnt
, psize
);
4232 /* Check address. */
4233 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4234 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4235 /* From RFC4271 Section 6.3:
4237 * If a prefix in the NLRI field is semantically
4239 * (e.g., an unexpected multicast IP address),
4241 * be logged locally, and the prefix SHOULD be
4245 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4246 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4251 /* Check address. */
4252 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4253 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4257 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4259 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4264 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4268 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4270 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4277 /* Normal process. */
4279 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4280 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4281 NULL
, NULL
, 0, 0, NULL
);
4283 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4284 safi
, ZEBRA_ROUTE_BGP
,
4285 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4288 /* Address family configuration mismatch or maximum-prefix count
4294 /* Packet length consistency check. */
4297 "%s [Error] Update packet error (prefix length mismatch with total length)",
4305 static struct bgp_static
*bgp_static_new(void)
4307 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4310 static void bgp_static_free(struct bgp_static
*bgp_static
)
4312 if (bgp_static
->rmap
.name
)
4313 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4314 if (bgp_static
->eth_s_id
)
4315 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4316 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4319 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4320 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4322 struct bgp_node
*rn
;
4323 struct bgp_info
*ri
;
4324 struct bgp_info
*new;
4325 struct bgp_info info
;
4327 struct attr
*attr_new
;
4330 int vnc_implicit_withdraw
= 0;
4337 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4339 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4341 attr
.nexthop
= bgp_static
->igpnexthop
;
4342 attr
.med
= bgp_static
->igpmetric
;
4343 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4345 if (bgp_static
->atomic
)
4346 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4348 /* Store label index, if required. */
4349 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4350 attr
.label_index
= bgp_static
->label_index
;
4351 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4354 /* Apply route-map. */
4355 if (bgp_static
->rmap
.name
) {
4356 struct attr attr_tmp
= attr
;
4357 info
.peer
= bgp
->peer_self
;
4358 info
.attr
= &attr_tmp
;
4360 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4362 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4364 bgp
->peer_self
->rmap_type
= 0;
4366 if (ret
== RMAP_DENYMATCH
) {
4367 /* Free uninterned attribute. */
4368 bgp_attr_flush(&attr_tmp
);
4370 /* Unintern original. */
4371 aspath_unintern(&attr
.aspath
);
4372 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4376 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4377 bgp_attr_add_gshut_community(&attr_tmp
);
4379 attr_new
= bgp_attr_intern(&attr_tmp
);
4382 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4383 bgp_attr_add_gshut_community(&attr
);
4385 attr_new
= bgp_attr_intern(&attr
);
4388 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4389 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4390 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4394 if (attrhash_cmp(ri
->attr
, attr_new
)
4395 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4396 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4397 bgp_unlock_node(rn
);
4398 bgp_attr_unintern(&attr_new
);
4399 aspath_unintern(&attr
.aspath
);
4402 /* The attribute is changed. */
4403 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4405 /* Rewrite BGP route information. */
4406 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4407 bgp_info_restore(rn
, ri
);
4409 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4411 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4412 && (safi
== SAFI_UNICAST
)) {
4413 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4415 * Implicit withdraw case.
4416 * We have to do this before ri is
4419 ++vnc_implicit_withdraw
;
4420 vnc_import_bgp_del_route(bgp
, p
, ri
);
4421 vnc_import_bgp_exterior_del_route(
4426 bgp_attr_unintern(&ri
->attr
);
4427 ri
->attr
= attr_new
;
4428 ri
->uptime
= bgp_clock();
4430 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4431 && (safi
== SAFI_UNICAST
)) {
4432 if (vnc_implicit_withdraw
) {
4433 vnc_import_bgp_add_route(bgp
, p
, ri
);
4434 vnc_import_bgp_exterior_add_route(
4440 /* Nexthop reachability check. */
4441 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4442 && (safi
== SAFI_UNICAST
4443 || safi
== SAFI_LABELED_UNICAST
)) {
4445 struct bgp
*bgp_nexthop
= bgp
;
4447 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4448 bgp_nexthop
= ri
->extra
->bgp_orig
;
4450 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4452 bgp_info_set_flag(rn
, ri
,
4455 if (BGP_DEBUG(nht
, NHT
)) {
4456 char buf1
[INET6_ADDRSTRLEN
];
4457 inet_ntop(p
->family
,
4461 "%s(%s): Route not in table, not advertising",
4462 __FUNCTION__
, buf1
);
4464 bgp_info_unset_flag(rn
, ri
,
4468 /* Delete the NHT structure if any, if we're
4470 * enabling/disabling import check. We
4471 * deregister the route
4472 * from NHT to avoid overloading NHT and the
4473 * process interaction
4475 bgp_unlink_nexthop(ri
);
4476 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4478 /* Process change. */
4479 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4480 bgp_process(bgp
, rn
, afi
, safi
);
4482 if (SAFI_UNICAST
== safi
4483 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4485 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4486 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4490 bgp_unlock_node(rn
);
4491 aspath_unintern(&attr
.aspath
);
4496 /* Make new BGP info. */
4497 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4499 /* Nexthop reachability check. */
4500 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4501 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4502 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4503 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4505 if (BGP_DEBUG(nht
, NHT
)) {
4506 char buf1
[INET6_ADDRSTRLEN
];
4507 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4510 "%s(%s): Route not in table, not advertising",
4511 __FUNCTION__
, buf1
);
4513 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4516 /* Delete the NHT structure if any, if we're toggling between
4517 * enabling/disabling import check. We deregister the route
4518 * from NHT to avoid overloading NHT and the process interaction
4520 bgp_unlink_nexthop(new);
4522 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4525 /* Aggregate address increment. */
4526 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4528 /* Register new BGP information. */
4529 bgp_info_add(rn
, new);
4531 /* route_node_get lock */
4532 bgp_unlock_node(rn
);
4534 /* Process change. */
4535 bgp_process(bgp
, rn
, afi
, safi
);
4537 if (SAFI_UNICAST
== safi
4538 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4539 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4540 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4543 /* Unintern original. */
4544 aspath_unintern(&attr
.aspath
);
4547 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4550 struct bgp_node
*rn
;
4551 struct bgp_info
*ri
;
4553 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4555 /* Check selected route and self inserted route. */
4556 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4557 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4558 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4561 /* Withdraw static BGP route from routing table. */
4563 if (SAFI_UNICAST
== safi
4564 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4565 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4566 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4568 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4569 bgp_unlink_nexthop(ri
);
4570 bgp_info_delete(rn
, ri
);
4571 bgp_process(bgp
, rn
, afi
, safi
);
4574 /* Unlock bgp_node_lookup. */
4575 bgp_unlock_node(rn
);
4579 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4581 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4582 afi_t afi
, safi_t safi
,
4583 struct prefix_rd
*prd
)
4585 struct bgp_node
*rn
;
4586 struct bgp_info
*ri
;
4588 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4590 /* Check selected route and self inserted route. */
4591 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4592 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4593 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4596 /* Withdraw static BGP route from routing table. */
4599 rfapiProcessWithdraw(
4600 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4601 1); /* Kill, since it is an administrative change */
4603 if (SAFI_MPLS_VPN
== safi
4604 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4605 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4607 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4608 bgp_info_delete(rn
, ri
);
4609 bgp_process(bgp
, rn
, afi
, safi
);
4612 /* Unlock bgp_node_lookup. */
4613 bgp_unlock_node(rn
);
4616 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4617 struct bgp_static
*bgp_static
, afi_t afi
,
4620 struct bgp_node
*rn
;
4621 struct bgp_info
*new;
4622 struct attr
*attr_new
;
4623 struct attr attr
= {0};
4624 struct bgp_info
*ri
;
4626 mpls_label_t label
= 0;
4628 uint32_t num_labels
= 0;
4633 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4635 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4638 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4640 attr
.nexthop
= bgp_static
->igpnexthop
;
4641 attr
.med
= bgp_static
->igpmetric
;
4642 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4644 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4645 || (safi
== SAFI_ENCAP
)) {
4646 if (afi
== AFI_IP
) {
4647 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4648 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4651 if (afi
== AFI_L2VPN
) {
4652 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4654 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4655 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4656 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4657 sizeof(struct in6_addr
));
4658 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4659 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4660 struct bgp_encap_type_vxlan bet
;
4661 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4662 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4663 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4665 if (bgp_static
->router_mac
) {
4666 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4669 /* Apply route-map. */
4670 if (bgp_static
->rmap
.name
) {
4671 struct attr attr_tmp
= attr
;
4672 struct bgp_info info
;
4675 info
.peer
= bgp
->peer_self
;
4676 info
.attr
= &attr_tmp
;
4678 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4680 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4682 bgp
->peer_self
->rmap_type
= 0;
4684 if (ret
== RMAP_DENYMATCH
) {
4685 /* Free uninterned attribute. */
4686 bgp_attr_flush(&attr_tmp
);
4688 /* Unintern original. */
4689 aspath_unintern(&attr
.aspath
);
4690 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4695 attr_new
= bgp_attr_intern(&attr_tmp
);
4697 attr_new
= bgp_attr_intern(&attr
);
4700 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4701 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4702 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4707 memset(&add
, 0, sizeof(union gw_addr
));
4708 if (attrhash_cmp(ri
->attr
, attr_new
)
4709 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4710 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4711 bgp_unlock_node(rn
);
4712 bgp_attr_unintern(&attr_new
);
4713 aspath_unintern(&attr
.aspath
);
4716 /* The attribute is changed. */
4717 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4719 /* Rewrite BGP route information. */
4720 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4721 bgp_info_restore(rn
, ri
);
4723 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4724 bgp_attr_unintern(&ri
->attr
);
4725 ri
->attr
= attr_new
;
4726 ri
->uptime
= bgp_clock();
4729 label
= decode_label(&ri
->extra
->label
[0]);
4732 /* Process change. */
4733 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4734 bgp_process(bgp
, rn
, afi
, safi
);
4736 if (SAFI_MPLS_VPN
== safi
4737 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4738 vpn_leak_to_vrf_update(bgp
, ri
);
4741 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4742 ri
->attr
, afi
, safi
, ri
->type
,
4743 ri
->sub_type
, &label
);
4745 bgp_unlock_node(rn
);
4746 aspath_unintern(&attr
.aspath
);
4752 /* Make new BGP info. */
4753 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4755 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4756 new->extra
= bgp_info_extra_new();
4758 new->extra
->label
[0] = bgp_static
->label
;
4759 new->extra
->num_labels
= num_labels
;
4762 label
= decode_label(&bgp_static
->label
);
4765 /* Aggregate address increment. */
4766 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4768 /* Register new BGP information. */
4769 bgp_info_add(rn
, new);
4770 /* route_node_get lock */
4771 bgp_unlock_node(rn
);
4773 /* Process change. */
4774 bgp_process(bgp
, rn
, afi
, safi
);
4776 if (SAFI_MPLS_VPN
== safi
4777 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4778 vpn_leak_to_vrf_update(bgp
, new);
4781 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4782 safi
, new->type
, new->sub_type
, &label
);
4785 /* Unintern original. */
4786 aspath_unintern(&attr
.aspath
);
4789 /* Configure static BGP network. When user don't run zebra, static
4790 route should be installed as valid. */
4791 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4792 const char *ip_str
, afi_t afi
, safi_t safi
,
4793 const char *rmap
, int backdoor
, uint32_t label_index
)
4795 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4798 struct bgp_static
*bgp_static
;
4799 struct bgp_node
*rn
;
4800 uint8_t need_update
= 0;
4802 /* Convert IP prefix string to struct prefix. */
4803 ret
= str2prefix(ip_str
, &p
);
4805 vty_out(vty
, "%% Malformed prefix\n");
4806 return CMD_WARNING_CONFIG_FAILED
;
4808 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4809 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4810 return CMD_WARNING_CONFIG_FAILED
;
4817 /* Set BGP static route configuration. */
4818 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4821 vty_out(vty
, "%% Can't find static route specified\n");
4822 return CMD_WARNING_CONFIG_FAILED
;
4825 bgp_static
= rn
->info
;
4827 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4828 && (label_index
!= bgp_static
->label_index
)) {
4830 "%% label-index doesn't match static route\n");
4831 return CMD_WARNING_CONFIG_FAILED
;
4834 if ((rmap
&& bgp_static
->rmap
.name
)
4835 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4837 "%% route-map name doesn't match static route\n");
4838 return CMD_WARNING_CONFIG_FAILED
;
4841 /* Update BGP RIB. */
4842 if (!bgp_static
->backdoor
)
4843 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4845 /* Clear configuration. */
4846 bgp_static_free(bgp_static
);
4848 bgp_unlock_node(rn
);
4849 bgp_unlock_node(rn
);
4852 /* Set BGP static route configuration. */
4853 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4856 /* Configuration change. */
4857 bgp_static
= rn
->info
;
4859 /* Label index cannot be changed. */
4860 if (bgp_static
->label_index
!= label_index
) {
4861 vty_out(vty
, "%% cannot change label-index\n");
4862 return CMD_WARNING_CONFIG_FAILED
;
4865 /* Check previous routes are installed into BGP. */
4866 if (bgp_static
->valid
4867 && bgp_static
->backdoor
!= backdoor
)
4870 bgp_static
->backdoor
= backdoor
;
4873 if (bgp_static
->rmap
.name
)
4874 XFREE(MTYPE_ROUTE_MAP_NAME
,
4875 bgp_static
->rmap
.name
);
4876 bgp_static
->rmap
.name
=
4877 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4878 bgp_static
->rmap
.map
=
4879 route_map_lookup_by_name(rmap
);
4881 if (bgp_static
->rmap
.name
)
4882 XFREE(MTYPE_ROUTE_MAP_NAME
,
4883 bgp_static
->rmap
.name
);
4884 bgp_static
->rmap
.name
= NULL
;
4885 bgp_static
->rmap
.map
= NULL
;
4886 bgp_static
->valid
= 0;
4888 bgp_unlock_node(rn
);
4890 /* New configuration. */
4891 bgp_static
= bgp_static_new();
4892 bgp_static
->backdoor
= backdoor
;
4893 bgp_static
->valid
= 0;
4894 bgp_static
->igpmetric
= 0;
4895 bgp_static
->igpnexthop
.s_addr
= 0;
4896 bgp_static
->label_index
= label_index
;
4899 if (bgp_static
->rmap
.name
)
4900 XFREE(MTYPE_ROUTE_MAP_NAME
,
4901 bgp_static
->rmap
.name
);
4902 bgp_static
->rmap
.name
=
4903 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4904 bgp_static
->rmap
.map
=
4905 route_map_lookup_by_name(rmap
);
4907 rn
->info
= bgp_static
;
4910 bgp_static
->valid
= 1;
4912 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4914 if (!bgp_static
->backdoor
)
4915 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4921 void bgp_static_add(struct bgp
*bgp
)
4925 struct bgp_node
*rn
;
4926 struct bgp_node
*rm
;
4927 struct bgp_table
*table
;
4928 struct bgp_static
*bgp_static
;
4930 FOREACH_AFI_SAFI (afi
, safi
)
4931 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4932 rn
= bgp_route_next(rn
)) {
4933 if (rn
->info
== NULL
)
4936 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4937 || (safi
== SAFI_EVPN
)) {
4940 for (rm
= bgp_table_top(table
); rm
;
4941 rm
= bgp_route_next(rm
)) {
4942 bgp_static
= rm
->info
;
4943 bgp_static_update_safi(bgp
, &rm
->p
,
4948 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4954 /* Called from bgp_delete(). Delete all static routes from the BGP
4956 void bgp_static_delete(struct bgp
*bgp
)
4960 struct bgp_node
*rn
;
4961 struct bgp_node
*rm
;
4962 struct bgp_table
*table
;
4963 struct bgp_static
*bgp_static
;
4965 FOREACH_AFI_SAFI (afi
, safi
)
4966 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4967 rn
= bgp_route_next(rn
)) {
4968 if (rn
->info
== NULL
)
4971 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4972 || (safi
== SAFI_EVPN
)) {
4975 for (rm
= bgp_table_top(table
); rm
;
4976 rm
= bgp_route_next(rm
)) {
4977 bgp_static
= rm
->info
;
4978 bgp_static_withdraw_safi(
4979 bgp
, &rm
->p
, AFI_IP
, safi
,
4980 (struct prefix_rd
*)&rn
->p
);
4981 bgp_static_free(bgp_static
);
4983 bgp_unlock_node(rn
);
4986 bgp_static
= rn
->info
;
4987 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
4988 bgp_static_free(bgp_static
);
4990 bgp_unlock_node(rn
);
4995 void bgp_static_redo_import_check(struct bgp
*bgp
)
4999 struct bgp_node
*rn
;
5000 struct bgp_node
*rm
;
5001 struct bgp_table
*table
;
5002 struct bgp_static
*bgp_static
;
5004 /* Use this flag to force reprocessing of the route */
5005 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5006 FOREACH_AFI_SAFI (afi
, safi
) {
5007 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5008 rn
= bgp_route_next(rn
)) {
5009 if (rn
->info
== NULL
)
5012 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5013 || (safi
== SAFI_EVPN
)) {
5016 for (rm
= bgp_table_top(table
); rm
;
5017 rm
= bgp_route_next(rm
)) {
5018 bgp_static
= rm
->info
;
5019 bgp_static_update_safi(bgp
, &rm
->p
,
5024 bgp_static
= rn
->info
;
5025 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5030 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5033 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5036 struct bgp_table
*table
;
5037 struct bgp_node
*rn
;
5038 struct bgp_info
*ri
;
5040 table
= bgp
->rib
[afi
][safi
];
5041 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5042 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5043 if (ri
->peer
== bgp
->peer_self
5044 && ((ri
->type
== ZEBRA_ROUTE_BGP
5045 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5046 || (ri
->type
!= ZEBRA_ROUTE_BGP
5048 == BGP_ROUTE_REDISTRIBUTE
))) {
5049 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5051 bgp_unlink_nexthop(ri
);
5052 bgp_info_delete(rn
, ri
);
5053 bgp_process(bgp
, rn
, afi
, safi
);
5060 * Purge all networks and redistributed routes from routing table.
5061 * Invoked upon the instance going down.
5063 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5068 FOREACH_AFI_SAFI (afi
, safi
)
5069 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5074 * Currently this is used to set static routes for VPN and ENCAP.
5075 * I think it can probably be factored with bgp_static_set.
5077 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5078 const char *ip_str
, const char *rd_str
,
5079 const char *label_str
, const char *rmap_str
,
5080 int evpn_type
, const char *esi
, const char *gwip
,
5081 const char *ethtag
, const char *routermac
)
5083 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5086 struct prefix_rd prd
;
5087 struct bgp_node
*prn
;
5088 struct bgp_node
*rn
;
5089 struct bgp_table
*table
;
5090 struct bgp_static
*bgp_static
;
5091 mpls_label_t label
= MPLS_INVALID_LABEL
;
5092 struct prefix gw_ip
;
5094 /* validate ip prefix */
5095 ret
= str2prefix(ip_str
, &p
);
5097 vty_out(vty
, "%% Malformed prefix\n");
5098 return CMD_WARNING_CONFIG_FAILED
;
5101 if ((afi
== AFI_L2VPN
)
5102 && (bgp_build_evpn_prefix(evpn_type
,
5103 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5104 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5105 return CMD_WARNING_CONFIG_FAILED
;
5108 ret
= str2prefix_rd(rd_str
, &prd
);
5110 vty_out(vty
, "%% Malformed rd\n");
5111 return CMD_WARNING_CONFIG_FAILED
;
5115 unsigned long label_val
;
5116 label_val
= strtoul(label_str
, NULL
, 10);
5117 encode_label(label_val
, &label
);
5120 if (safi
== SAFI_EVPN
) {
5121 if (esi
&& str2esi(esi
, NULL
) == 0) {
5122 vty_out(vty
, "%% Malformed ESI\n");
5123 return CMD_WARNING_CONFIG_FAILED
;
5125 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5126 vty_out(vty
, "%% Malformed Router MAC\n");
5127 return CMD_WARNING_CONFIG_FAILED
;
5130 memset(&gw_ip
, 0, sizeof(struct prefix
));
5131 ret
= str2prefix(gwip
, &gw_ip
);
5133 vty_out(vty
, "%% Malformed GatewayIp\n");
5134 return CMD_WARNING_CONFIG_FAILED
;
5136 if ((gw_ip
.family
== AF_INET
5137 && is_evpn_prefix_ipaddr_v6(
5138 (struct prefix_evpn
*)&p
))
5139 || (gw_ip
.family
== AF_INET6
5140 && is_evpn_prefix_ipaddr_v4(
5141 (struct prefix_evpn
*)&p
))) {
5143 "%% GatewayIp family differs with IP prefix\n");
5144 return CMD_WARNING_CONFIG_FAILED
;
5148 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5149 if (prn
->info
== NULL
)
5150 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5152 bgp_unlock_node(prn
);
5155 rn
= bgp_node_get(table
, &p
);
5158 vty_out(vty
, "%% Same network configuration exists\n");
5159 bgp_unlock_node(rn
);
5161 /* New configuration. */
5162 bgp_static
= bgp_static_new();
5163 bgp_static
->backdoor
= 0;
5164 bgp_static
->valid
= 0;
5165 bgp_static
->igpmetric
= 0;
5166 bgp_static
->igpnexthop
.s_addr
= 0;
5167 bgp_static
->label
= label
;
5168 bgp_static
->prd
= prd
;
5171 if (bgp_static
->rmap
.name
)
5172 XFREE(MTYPE_ROUTE_MAP_NAME
,
5173 bgp_static
->rmap
.name
);
5174 bgp_static
->rmap
.name
=
5175 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5176 bgp_static
->rmap
.map
=
5177 route_map_lookup_by_name(rmap_str
);
5180 if (safi
== SAFI_EVPN
) {
5182 bgp_static
->eth_s_id
=
5184 sizeof(struct eth_segment_id
));
5185 str2esi(esi
, bgp_static
->eth_s_id
);
5188 bgp_static
->router_mac
=
5189 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5190 prefix_str2mac(routermac
,
5191 bgp_static
->router_mac
);
5194 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5196 rn
->info
= bgp_static
;
5198 bgp_static
->valid
= 1;
5199 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5205 /* Configure static BGP network. */
5206 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5207 const char *ip_str
, const char *rd_str
,
5208 const char *label_str
, int evpn_type
, const char *esi
,
5209 const char *gwip
, const char *ethtag
)
5211 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5214 struct prefix_rd prd
;
5215 struct bgp_node
*prn
;
5216 struct bgp_node
*rn
;
5217 struct bgp_table
*table
;
5218 struct bgp_static
*bgp_static
;
5219 mpls_label_t label
= MPLS_INVALID_LABEL
;
5221 /* Convert IP prefix string to struct prefix. */
5222 ret
= str2prefix(ip_str
, &p
);
5224 vty_out(vty
, "%% Malformed prefix\n");
5225 return CMD_WARNING_CONFIG_FAILED
;
5228 if ((afi
== AFI_L2VPN
)
5229 && (bgp_build_evpn_prefix(evpn_type
,
5230 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5231 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5232 return CMD_WARNING_CONFIG_FAILED
;
5234 ret
= str2prefix_rd(rd_str
, &prd
);
5236 vty_out(vty
, "%% Malformed rd\n");
5237 return CMD_WARNING_CONFIG_FAILED
;
5241 unsigned long label_val
;
5242 label_val
= strtoul(label_str
, NULL
, 10);
5243 encode_label(label_val
, &label
);
5246 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5247 if (prn
->info
== NULL
)
5248 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5250 bgp_unlock_node(prn
);
5253 rn
= bgp_node_lookup(table
, &p
);
5256 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5258 bgp_static
= rn
->info
;
5259 bgp_static_free(bgp_static
);
5261 bgp_unlock_node(rn
);
5262 bgp_unlock_node(rn
);
5264 vty_out(vty
, "%% Can't find the route\n");
5269 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5270 const char *rmap_name
)
5272 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5273 struct bgp_rmap
*rmap
;
5275 rmap
= &bgp
->table_map
[afi
][safi
];
5278 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5279 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5280 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5283 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5288 if (bgp_fibupd_safi(safi
))
5289 bgp_zebra_announce_table(bgp
, afi
, safi
);
5294 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5295 const char *rmap_name
)
5297 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5298 struct bgp_rmap
*rmap
;
5300 rmap
= &bgp
->table_map
[afi
][safi
];
5302 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5306 if (bgp_fibupd_safi(safi
))
5307 bgp_zebra_announce_table(bgp
, afi
, safi
);
5312 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5315 if (bgp
->table_map
[afi
][safi
].name
) {
5316 vty_out(vty
, " table-map %s\n",
5317 bgp
->table_map
[afi
][safi
].name
);
5321 DEFUN (bgp_table_map
,
5324 "BGP table to RIB route download filter\n"
5325 "Name of the route map\n")
5328 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5329 argv
[idx_word
]->arg
);
5331 DEFUN (no_bgp_table_map
,
5332 no_bgp_table_map_cmd
,
5333 "no table-map WORD",
5335 "BGP table to RIB route download filter\n"
5336 "Name of the route map\n")
5339 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5340 argv
[idx_word
]->arg
);
5346 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5347 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5348 backdoor$backdoor}]",
5350 "Specify a network to announce via BGP\n"
5355 "Route-map to modify the attributes\n"
5356 "Name of the route map\n"
5357 "Label index to associate with the prefix\n"
5358 "Label index value\n"
5359 "Specify a BGP backdoor route\n")
5361 char addr_prefix_str
[BUFSIZ
];
5366 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5369 vty_out(vty
, "%% Inconsistent address and mask\n");
5370 return CMD_WARNING_CONFIG_FAILED
;
5374 return bgp_static_set(
5375 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5376 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5377 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5380 DEFPY(ipv6_bgp_network
,
5381 ipv6_bgp_network_cmd
,
5382 "[no] network X:X::X:X/M$prefix \
5383 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5385 "Specify a network to announce via BGP\n"
5387 "Route-map to modify the attributes\n"
5388 "Name of the route map\n"
5389 "Label index to associate with the prefix\n"
5390 "Label index value\n")
5392 return bgp_static_set(
5393 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5394 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5397 /* Aggreagete address:
5399 advertise-map Set condition to advertise attribute
5400 as-set Generate AS set path information
5401 attribute-map Set attributes of aggregate
5402 route-map Set parameters of aggregate
5403 summary-only Filter more specific routes from updates
5404 suppress-map Conditionally filter more specific routes from updates
5407 struct bgp_aggregate
{
5408 /* Summary-only flag. */
5409 uint8_t summary_only
;
5411 /* AS set generation. */
5414 /* Route-map for aggregated route. */
5415 struct route_map
*map
;
5417 /* Suppress-count. */
5418 unsigned long count
;
5420 /* SAFI configuration. */
5424 static struct bgp_aggregate
*bgp_aggregate_new(void)
5426 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5429 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5431 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5434 /* Update an aggregate as routes are added/removed from the BGP table */
5435 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5436 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5437 struct bgp_info
*del
,
5438 struct bgp_aggregate
*aggregate
)
5440 struct bgp_table
*table
;
5441 struct bgp_node
*top
;
5442 struct bgp_node
*rn
;
5444 struct aspath
*aspath
= NULL
;
5445 struct aspath
*asmerge
= NULL
;
5446 struct community
*community
= NULL
;
5447 struct community
*commerge
= NULL
;
5448 #if defined(AGGREGATE_NEXTHOP_CHECK)
5449 struct in_addr nexthop
;
5452 struct bgp_info
*ri
;
5453 struct bgp_info
*new;
5455 unsigned long match
= 0;
5456 uint8_t atomic_aggregate
= 0;
5458 /* Record adding route's nexthop and med. */
5460 #if defined(AGGREGATE_NEXTHOP_CHECK)
5461 nexthop
= rinew
->attr
->nexthop
;
5462 med
= rinew
->attr
->med
;
5466 /* ORIGIN attribute: If at least one route among routes that are
5467 aggregated has ORIGIN with the value INCOMPLETE, then the
5468 aggregated route must have the ORIGIN attribute with the value
5469 INCOMPLETE. Otherwise, if at least one route among routes that
5470 are aggregated has ORIGIN with the value EGP, then the aggregated
5471 route must have the origin attribute with the value EGP. In all
5472 other case the value of the ORIGIN attribute of the aggregated
5473 route is INTERNAL. */
5474 origin
= BGP_ORIGIN_IGP
;
5476 table
= bgp
->rib
[afi
][safi
];
5478 top
= bgp_node_get(table
, p
);
5479 for (rn
= bgp_node_get(table
, p
); rn
;
5480 rn
= bgp_route_next_until(rn
, top
))
5481 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5484 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5485 if (BGP_INFO_HOLDDOWN(ri
))
5488 if (del
&& ri
== del
)
5491 if (!rinew
&& first
) {
5492 #if defined(AGGREGATE_NEXTHOP_CHECK)
5493 nexthop
= ri
->attr
->nexthop
;
5494 med
= ri
->attr
->med
;
5499 #ifdef AGGREGATE_NEXTHOP_CHECK
5500 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5502 || ri
->attr
->med
!= med
) {
5504 aspath_free(aspath
);
5506 community_free(community
);
5507 bgp_unlock_node(rn
);
5508 bgp_unlock_node(top
);
5511 #endif /* AGGREGATE_NEXTHOP_CHECK */
5514 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5515 atomic_aggregate
= 1;
5517 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5518 if (aggregate
->summary_only
) {
5519 (bgp_info_extra_get(ri
))
5523 BGP_INFO_ATTR_CHANGED
);
5529 if (origin
< ri
->attr
->origin
)
5530 origin
= ri
->attr
->origin
;
5532 if (aggregate
->as_set
) {
5534 asmerge
= aspath_aggregate(
5537 aspath_free(aspath
);
5540 aspath
= aspath_dup(
5543 if (ri
->attr
->community
) {
5545 commerge
= community_merge(
5547 ri
->attr
->community
);
5548 community
= community_uniq_sort(
5553 community
= community_dup(
5554 ri
->attr
->community
);
5560 bgp_process(bgp
, rn
, afi
, safi
);
5562 bgp_unlock_node(top
);
5567 if (aggregate
->summary_only
)
5568 (bgp_info_extra_get(rinew
))->suppress
++;
5570 if (origin
< rinew
->attr
->origin
)
5571 origin
= rinew
->attr
->origin
;
5573 if (aggregate
->as_set
) {
5575 asmerge
= aspath_aggregate(aspath
,
5576 rinew
->attr
->aspath
);
5577 aspath_free(aspath
);
5580 aspath
= aspath_dup(rinew
->attr
->aspath
);
5582 if (rinew
->attr
->community
) {
5584 commerge
= community_merge(
5586 rinew
->attr
->community
);
5588 community_uniq_sort(commerge
);
5589 community_free(commerge
);
5591 community
= community_dup(
5592 rinew
->attr
->community
);
5597 if (aggregate
->count
> 0) {
5598 rn
= bgp_node_get(table
, p
);
5600 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5601 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5602 community
, aggregate
->as_set
,
5605 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5607 bgp_info_add(rn
, new);
5608 bgp_unlock_node(rn
);
5609 bgp_process(bgp
, rn
, afi
, safi
);
5612 aspath_free(aspath
);
5614 community_free(community
);
5618 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5619 struct bgp_aggregate
*);
5621 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5622 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5624 struct bgp_node
*child
;
5625 struct bgp_node
*rn
;
5626 struct bgp_aggregate
*aggregate
;
5627 struct bgp_table
*table
;
5629 /* MPLS-VPN aggregation is not yet supported. */
5630 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5631 || (safi
== SAFI_EVPN
)
5632 || (safi
== SAFI_FLOWSPEC
))
5635 table
= bgp
->aggregate
[afi
][safi
];
5637 /* No aggregates configured. */
5638 if (bgp_table_top_nolock(table
) == NULL
)
5641 if (p
->prefixlen
== 0)
5644 if (BGP_INFO_HOLDDOWN(ri
))
5647 child
= bgp_node_get(table
, p
);
5649 /* Aggregate address configuration check. */
5650 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5651 if ((aggregate
= rn
->info
) != NULL
5652 && rn
->p
.prefixlen
< p
->prefixlen
) {
5653 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5654 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5657 bgp_unlock_node(child
);
5660 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5661 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5663 struct bgp_node
*child
;
5664 struct bgp_node
*rn
;
5665 struct bgp_aggregate
*aggregate
;
5666 struct bgp_table
*table
;
5668 /* MPLS-VPN aggregation is not yet supported. */
5669 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5670 || (safi
== SAFI_EVPN
)
5671 || (safi
== SAFI_FLOWSPEC
))
5674 table
= bgp
->aggregate
[afi
][safi
];
5676 /* No aggregates configured. */
5677 if (bgp_table_top_nolock(table
) == NULL
)
5680 if (p
->prefixlen
== 0)
5683 child
= bgp_node_get(table
, p
);
5685 /* Aggregate address configuration check. */
5686 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5687 if ((aggregate
= rn
->info
) != NULL
5688 && rn
->p
.prefixlen
< p
->prefixlen
) {
5689 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5690 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5693 bgp_unlock_node(child
);
5696 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5697 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5698 safi_t safi
, struct bgp_aggregate
*aggregate
)
5700 struct bgp_table
*table
;
5701 struct bgp_node
*top
;
5702 struct bgp_node
*rn
;
5703 struct bgp_info
*new;
5704 struct bgp_info
*ri
;
5705 unsigned long match
;
5706 uint8_t origin
= BGP_ORIGIN_IGP
;
5707 struct aspath
*aspath
= NULL
;
5708 struct aspath
*asmerge
= NULL
;
5709 struct community
*community
= NULL
;
5710 struct community
*commerge
= NULL
;
5711 uint8_t atomic_aggregate
= 0;
5713 table
= bgp
->rib
[afi
][safi
];
5716 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5718 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5721 /* If routes exists below this node, generate aggregate routes. */
5722 top
= bgp_node_get(table
, p
);
5723 for (rn
= bgp_node_get(table
, p
); rn
;
5724 rn
= bgp_route_next_until(rn
, top
)) {
5725 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5730 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5731 if (BGP_INFO_HOLDDOWN(ri
))
5735 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5736 atomic_aggregate
= 1;
5738 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5741 /* summary-only aggregate route suppress
5742 * aggregated route announcement. */
5743 if (aggregate
->summary_only
) {
5744 (bgp_info_extra_get(ri
))->suppress
++;
5745 bgp_info_set_flag(rn
, ri
,
5746 BGP_INFO_ATTR_CHANGED
);
5750 /* If at least one route among routes that are
5751 * aggregated has ORIGIN with the value INCOMPLETE,
5752 * then the aggregated route MUST have the ORIGIN
5753 * attribute with the value INCOMPLETE. Otherwise, if
5754 * at least one route among routes that are aggregated
5755 * has ORIGIN with the value EGP, then the aggregated
5756 * route MUST have the ORIGIN attribute with the value
5759 if (origin
< ri
->attr
->origin
)
5760 origin
= ri
->attr
->origin
;
5762 /* as-set aggregate route generate origin, as path,
5763 * community aggregation. */
5764 if (aggregate
->as_set
) {
5766 asmerge
= aspath_aggregate(
5767 aspath
, ri
->attr
->aspath
);
5768 aspath_free(aspath
);
5771 aspath
= aspath_dup(ri
->attr
->aspath
);
5773 if (ri
->attr
->community
) {
5775 commerge
= community_merge(
5777 ri
->attr
->community
);
5778 community
= community_uniq_sort(
5780 community_free(commerge
);
5782 community
= community_dup(
5783 ri
->attr
->community
);
5789 /* If this node is suppressed, process the change. */
5791 bgp_process(bgp
, rn
, afi
, safi
);
5793 bgp_unlock_node(top
);
5795 /* Add aggregate route to BGP table. */
5796 if (aggregate
->count
) {
5797 rn
= bgp_node_get(table
, p
);
5799 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5800 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5801 community
, aggregate
->as_set
,
5804 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5806 bgp_info_add(rn
, new);
5807 bgp_unlock_node(rn
);
5809 /* Process change. */
5810 bgp_process(bgp
, rn
, afi
, safi
);
5813 aspath_free(aspath
);
5815 community_free(community
);
5819 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5820 safi_t safi
, struct bgp_aggregate
*aggregate
)
5822 struct bgp_table
*table
;
5823 struct bgp_node
*top
;
5824 struct bgp_node
*rn
;
5825 struct bgp_info
*ri
;
5826 unsigned long match
;
5828 table
= bgp
->rib
[afi
][safi
];
5830 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5832 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5835 /* If routes exists below this node, generate aggregate routes. */
5836 top
= bgp_node_get(table
, p
);
5837 for (rn
= bgp_node_get(table
, p
); rn
;
5838 rn
= bgp_route_next_until(rn
, top
)) {
5839 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5843 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5844 if (BGP_INFO_HOLDDOWN(ri
))
5847 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5850 if (aggregate
->summary_only
&& ri
->extra
) {
5851 ri
->extra
->suppress
--;
5853 if (ri
->extra
->suppress
== 0) {
5855 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5862 /* If this node was suppressed, process the change. */
5864 bgp_process(bgp
, rn
, afi
, safi
);
5866 bgp_unlock_node(top
);
5868 /* Delete aggregate route from BGP table. */
5869 rn
= bgp_node_get(table
, p
);
5871 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5872 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5873 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5876 /* Withdraw static BGP route from routing table. */
5878 bgp_info_delete(rn
, ri
);
5879 bgp_process(bgp
, rn
, afi
, safi
);
5882 /* Unlock bgp_node_lookup. */
5883 bgp_unlock_node(rn
);
5886 /* Aggregate route attribute. */
5887 #define AGGREGATE_SUMMARY_ONLY 1
5888 #define AGGREGATE_AS_SET 1
5890 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5891 afi_t afi
, safi_t safi
)
5893 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5896 struct bgp_node
*rn
;
5897 struct bgp_aggregate
*aggregate
;
5899 if (safi
== SAFI_FLOWSPEC
)
5900 return CMD_WARNING_CONFIG_FAILED
;
5902 /* Convert string to prefix structure. */
5903 ret
= str2prefix(prefix_str
, &p
);
5905 vty_out(vty
, "Malformed prefix\n");
5906 return CMD_WARNING_CONFIG_FAILED
;
5910 /* Old configuration check. */
5911 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5914 "%% There is no aggregate-address configuration.\n");
5915 return CMD_WARNING_CONFIG_FAILED
;
5918 aggregate
= rn
->info
;
5919 if (aggregate
->safi
== SAFI_UNICAST
)
5920 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5921 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5922 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5924 if (aggregate
->safi
== SAFI_MULTICAST
)
5925 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5927 /* Unlock aggregate address configuration. */
5929 bgp_aggregate_free(aggregate
);
5930 bgp_unlock_node(rn
);
5931 bgp_unlock_node(rn
);
5936 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5937 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5939 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5942 struct bgp_node
*rn
;
5943 struct bgp_aggregate
*aggregate
;
5945 if (safi
== SAFI_FLOWSPEC
)
5946 return CMD_WARNING_CONFIG_FAILED
;
5948 /* Convert string to prefix structure. */
5949 ret
= str2prefix(prefix_str
, &p
);
5951 vty_out(vty
, "Malformed prefix\n");
5952 return CMD_WARNING_CONFIG_FAILED
;
5956 /* Old configuration check. */
5957 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5960 vty_out(vty
, "There is already same aggregate network.\n");
5961 /* try to remove the old entry */
5962 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5964 vty_out(vty
, "Error deleting aggregate.\n");
5965 bgp_unlock_node(rn
);
5966 return CMD_WARNING_CONFIG_FAILED
;
5970 /* Make aggregate address structure. */
5971 aggregate
= bgp_aggregate_new();
5972 aggregate
->summary_only
= summary_only
;
5973 aggregate
->as_set
= as_set
;
5974 aggregate
->safi
= safi
;
5975 rn
->info
= aggregate
;
5977 /* Aggregate address insert into BGP routing table. */
5978 if (safi
== SAFI_UNICAST
)
5979 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5980 if (safi
== SAFI_LABELED_UNICAST
)
5981 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5983 if (safi
== SAFI_MULTICAST
)
5984 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5989 DEFUN (aggregate_address
,
5990 aggregate_address_cmd
,
5991 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5992 "Configure BGP aggregate entries\n"
5993 "Aggregate prefix\n"
5994 "Generate AS set path information\n"
5995 "Filter more specific routes from updates\n"
5996 "Filter more specific routes from updates\n"
5997 "Generate AS set path information\n")
6000 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6001 char *prefix
= argv
[idx
]->arg
;
6003 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6005 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6006 ? AGGREGATE_SUMMARY_ONLY
6009 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6010 summary_only
, as_set
);
6013 DEFUN (aggregate_address_mask
,
6014 aggregate_address_mask_cmd
,
6015 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6016 "Configure BGP aggregate entries\n"
6017 "Aggregate address\n"
6019 "Generate AS set path information\n"
6020 "Filter more specific routes from updates\n"
6021 "Filter more specific routes from updates\n"
6022 "Generate AS set path information\n")
6025 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6026 char *prefix
= argv
[idx
]->arg
;
6027 char *mask
= argv
[idx
+ 1]->arg
;
6029 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6031 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6032 ? AGGREGATE_SUMMARY_ONLY
6035 char prefix_str
[BUFSIZ
];
6036 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6039 vty_out(vty
, "%% Inconsistent address and mask\n");
6040 return CMD_WARNING_CONFIG_FAILED
;
6043 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6044 summary_only
, as_set
);
6047 DEFUN (no_aggregate_address
,
6048 no_aggregate_address_cmd
,
6049 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6051 "Configure BGP aggregate entries\n"
6052 "Aggregate prefix\n"
6053 "Generate AS set path information\n"
6054 "Filter more specific routes from updates\n"
6055 "Filter more specific routes from updates\n"
6056 "Generate AS set path information\n")
6059 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6060 char *prefix
= argv
[idx
]->arg
;
6061 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6064 DEFUN (no_aggregate_address_mask
,
6065 no_aggregate_address_mask_cmd
,
6066 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6068 "Configure BGP aggregate entries\n"
6069 "Aggregate address\n"
6071 "Generate AS set path information\n"
6072 "Filter more specific routes from updates\n"
6073 "Filter more specific routes from updates\n"
6074 "Generate AS set path information\n")
6077 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6078 char *prefix
= argv
[idx
]->arg
;
6079 char *mask
= argv
[idx
+ 1]->arg
;
6081 char prefix_str
[BUFSIZ
];
6082 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6085 vty_out(vty
, "%% Inconsistent address and mask\n");
6086 return CMD_WARNING_CONFIG_FAILED
;
6089 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6092 DEFUN (ipv6_aggregate_address
,
6093 ipv6_aggregate_address_cmd
,
6094 "aggregate-address X:X::X:X/M [summary-only]",
6095 "Configure BGP aggregate entries\n"
6096 "Aggregate prefix\n"
6097 "Filter more specific routes from updates\n")
6100 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6101 char *prefix
= argv
[idx
]->arg
;
6102 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6103 ? AGGREGATE_SUMMARY_ONLY
6105 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6109 DEFUN (no_ipv6_aggregate_address
,
6110 no_ipv6_aggregate_address_cmd
,
6111 "no aggregate-address X:X::X:X/M [summary-only]",
6113 "Configure BGP aggregate entries\n"
6114 "Aggregate prefix\n"
6115 "Filter more specific routes from updates\n")
6118 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6119 char *prefix
= argv
[idx
]->arg
;
6120 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6123 /* Redistribute route treatment. */
6124 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6125 const union g_addr
*nexthop
, ifindex_t ifindex
,
6126 enum nexthop_types_t nhtype
, uint32_t metric
,
6127 uint8_t type
, unsigned short instance
,
6130 struct bgp_info
*new;
6131 struct bgp_info
*bi
;
6132 struct bgp_info info
;
6133 struct bgp_node
*bn
;
6135 struct attr
*new_attr
;
6138 struct bgp_redist
*red
;
6140 /* Make default attribute. */
6141 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6144 case NEXTHOP_TYPE_IFINDEX
:
6146 case NEXTHOP_TYPE_IPV4
:
6147 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6148 attr
.nexthop
= nexthop
->ipv4
;
6150 case NEXTHOP_TYPE_IPV6
:
6151 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6152 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6153 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6155 case NEXTHOP_TYPE_BLACKHOLE
:
6156 switch (p
->family
) {
6158 attr
.nexthop
.s_addr
= INADDR_ANY
;
6161 memset(&attr
.mp_nexthop_global
, 0,
6162 sizeof(attr
.mp_nexthop_global
));
6163 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6168 attr
.nh_ifindex
= ifindex
;
6171 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6174 afi
= family2afi(p
->family
);
6176 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6178 struct attr attr_new
;
6180 /* Copy attribute for modification. */
6181 bgp_attr_dup(&attr_new
, &attr
);
6183 if (red
->redist_metric_flag
)
6184 attr_new
.med
= red
->redist_metric
;
6186 /* Apply route-map. */
6187 if (red
->rmap
.name
) {
6188 info
.peer
= bgp
->peer_self
;
6189 info
.attr
= &attr_new
;
6191 SET_FLAG(bgp
->peer_self
->rmap_type
,
6192 PEER_RMAP_TYPE_REDISTRIBUTE
);
6194 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6197 bgp
->peer_self
->rmap_type
= 0;
6199 if (ret
== RMAP_DENYMATCH
) {
6200 /* Free uninterned attribute. */
6201 bgp_attr_flush(&attr_new
);
6203 /* Unintern original. */
6204 aspath_unintern(&attr
.aspath
);
6205 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6210 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6211 bgp_attr_add_gshut_community(&attr_new
);
6213 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6214 SAFI_UNICAST
, p
, NULL
);
6216 new_attr
= bgp_attr_intern(&attr_new
);
6218 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6219 if (bi
->peer
== bgp
->peer_self
6220 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6224 /* Ensure the (source route) type is updated. */
6226 if (attrhash_cmp(bi
->attr
, new_attr
)
6227 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6228 bgp_attr_unintern(&new_attr
);
6229 aspath_unintern(&attr
.aspath
);
6230 bgp_unlock_node(bn
);
6233 /* The attribute is changed. */
6234 bgp_info_set_flag(bn
, bi
,
6235 BGP_INFO_ATTR_CHANGED
);
6237 /* Rewrite BGP route information. */
6238 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6239 bgp_info_restore(bn
, bi
);
6241 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6243 bgp_attr_unintern(&bi
->attr
);
6244 bi
->attr
= new_attr
;
6245 bi
->uptime
= bgp_clock();
6247 /* Process change. */
6248 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6250 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6251 bgp_unlock_node(bn
);
6252 aspath_unintern(&attr
.aspath
);
6254 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6256 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6258 vpn_leak_from_vrf_update(
6259 bgp_get_default(), bgp
, bi
);
6265 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6266 bgp
->peer_self
, new_attr
, bn
);
6267 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6269 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6270 bgp_info_add(bn
, new);
6271 bgp_unlock_node(bn
);
6272 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6274 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6275 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6277 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6281 /* Unintern original. */
6282 aspath_unintern(&attr
.aspath
);
6285 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6286 unsigned short instance
)
6289 struct bgp_node
*rn
;
6290 struct bgp_info
*ri
;
6291 struct bgp_redist
*red
;
6293 afi
= family2afi(p
->family
);
6295 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6297 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6298 SAFI_UNICAST
, p
, NULL
);
6300 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6301 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6305 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6306 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6308 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6311 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6312 bgp_info_delete(rn
, ri
);
6313 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6315 bgp_unlock_node(rn
);
6319 /* Withdraw specified route type's route. */
6320 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6321 unsigned short instance
)
6323 struct bgp_node
*rn
;
6324 struct bgp_info
*ri
;
6325 struct bgp_table
*table
;
6327 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6329 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6330 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6331 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6332 && ri
->instance
== instance
)
6336 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6337 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6339 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6342 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6344 bgp_info_delete(rn
, ri
);
6345 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6350 /* Static function to display route. */
6351 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6355 uint32_t destination
;
6358 if (p
->family
== AF_INET
) {
6360 len
= vty_out(vty
, "%s",
6361 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6363 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6365 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6366 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6367 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6368 || p
->u
.prefix4
.s_addr
== 0) {
6369 /* When mask is natural,
6370 mask is not displayed. */
6372 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6374 json_object_string_add(json
, "prefix",
6375 inet_ntop(p
->family
,
6378 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6380 } else if (p
->family
== AF_ETHERNET
) {
6381 prefix2str(p
, buf
, PREFIX_STRLEN
);
6382 len
= vty_out(vty
, "%s", buf
);
6383 } else if (p
->family
== AF_EVPN
) {
6384 #if defined(HAVE_CUMULUS)
6388 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6391 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6393 prefix2str(p
, buf
, PREFIX_STRLEN
);
6394 len
= vty_out(vty
, "%s", buf
);
6396 } else if (p
->family
== AF_FLOWSPEC
) {
6397 route_vty_out_flowspec(vty
, p
, NULL
,
6399 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6400 NLRI_STRING_FORMAT_MIN
, json
);
6405 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6412 vty_out(vty
, "\n%*s", 20, " ");
6414 vty_out(vty
, "%*s", len
, " ");
6418 enum bgp_display_type
{
6422 /* Print the short form route status for a bgp_info */
6423 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6424 json_object
*json_path
)
6428 /* Route status display. */
6429 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6430 json_object_boolean_true_add(json_path
, "removed");
6432 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6433 json_object_boolean_true_add(json_path
, "stale");
6435 if (binfo
->extra
&& binfo
->extra
->suppress
)
6436 json_object_boolean_true_add(json_path
, "suppressed");
6438 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6439 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6440 json_object_boolean_true_add(json_path
, "valid");
6443 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6444 json_object_boolean_true_add(json_path
, "history");
6446 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6447 json_object_boolean_true_add(json_path
, "damped");
6449 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6450 json_object_boolean_true_add(json_path
, "bestpath");
6452 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6453 json_object_boolean_true_add(json_path
, "multipath");
6455 /* Internal route. */
6456 if ((binfo
->peer
->as
)
6457 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6458 json_object_string_add(json_path
, "pathFrom",
6461 json_object_string_add(json_path
, "pathFrom",
6467 /* Route status display. */
6468 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6470 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6472 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6474 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6475 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6481 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6483 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6485 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6487 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6492 /* Internal route. */
6493 if (binfo
->peer
&& (binfo
->peer
->as
)
6494 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6500 /* called from terminal list command */
6501 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6502 int display
, safi_t safi
, json_object
*json_paths
)
6505 json_object
*json_path
= NULL
;
6506 json_object
*json_nexthops
= NULL
;
6507 json_object
*json_nexthop_global
= NULL
;
6508 json_object
*json_nexthop_ll
= NULL
;
6509 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6510 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6513 bool nexthop_othervrf
= false;
6514 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6515 const char *nexthop_vrfname
= "Default";
6518 json_path
= json_object_new_object();
6520 /* short status lead text */
6521 route_vty_short_status_out(vty
, binfo
, json_path
);
6524 /* print prefix and mask */
6526 route_vty_out_route(p
, vty
, json_path
);
6528 vty_out(vty
, "%*s", 17, " ");
6530 route_vty_out_route(p
, vty
, json_path
);
6533 /* Print attribute */
6537 json_object_array_add(json_paths
, json_path
);
6545 * If vrf id of nexthop is different from that of prefix,
6546 * set up printable string to append
6548 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6549 const char *self
= "";
6554 nexthop_othervrf
= true;
6555 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6557 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6558 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6559 "@%s%s", VRFID_NONE_STR
, self
);
6561 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6562 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6564 if (binfo
->extra
->bgp_orig
->inst_type
!=
6565 BGP_INSTANCE_TYPE_DEFAULT
)
6567 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6569 const char *self
= "";
6574 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6578 * For ENCAP and EVPN routes, nexthop address family is not
6579 * neccessarily the same as the prefix address family.
6580 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6581 * EVPN routes are also exchanged with a MP nexthop. Currently,
6583 * is only IPv4, the value will be present in either
6585 * attr->mp_nexthop_global_in
6587 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6590 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6594 sprintf(nexthop
, "%s",
6595 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6599 sprintf(nexthop
, "%s",
6600 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6604 sprintf(nexthop
, "?");
6609 json_nexthop_global
= json_object_new_object();
6611 json_object_string_add(json_nexthop_global
, "afi",
6612 (af
== AF_INET
) ? "ip" : "ipv6");
6613 json_object_string_add(json_nexthop_global
,
6614 (af
== AF_INET
) ? "ip" : "ipv6",
6616 json_object_boolean_true_add(json_nexthop_global
,
6619 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6620 } else if (safi
== SAFI_EVPN
) {
6622 json_nexthop_global
= json_object_new_object();
6624 json_object_string_add(json_nexthop_global
, "ip",
6625 inet_ntoa(attr
->nexthop
));
6626 json_object_string_add(json_nexthop_global
, "afi",
6628 json_object_boolean_true_add(json_nexthop_global
,
6631 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6633 } else if (safi
== SAFI_FLOWSPEC
) {
6634 if (attr
->nexthop
.s_addr
!= 0) {
6636 json_nexthop_global
= json_object_new_object();
6637 json_object_string_add(
6638 json_nexthop_global
, "ip",
6639 inet_ntoa(attr
->nexthop
));
6640 json_object_string_add(json_nexthop_global
,
6642 json_object_boolean_true_add(json_nexthop_global
,
6645 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6648 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6650 json_nexthop_global
= json_object_new_object();
6652 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6653 json_object_string_add(
6654 json_nexthop_global
, "ip",
6655 inet_ntoa(attr
->mp_nexthop_global_in
));
6657 json_object_string_add(
6658 json_nexthop_global
, "ip",
6659 inet_ntoa(attr
->nexthop
));
6661 json_object_string_add(json_nexthop_global
, "afi",
6663 json_object_boolean_true_add(json_nexthop_global
,
6668 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6669 snprintf(buf
, sizeof(buf
), "%s%s",
6670 inet_ntoa(attr
->mp_nexthop_global_in
),
6673 snprintf(buf
, sizeof(buf
), "%s%s",
6674 inet_ntoa(attr
->nexthop
),
6676 vty_out(vty
, "%-16s", buf
);
6681 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6686 json_nexthop_global
= json_object_new_object();
6687 json_object_string_add(
6688 json_nexthop_global
, "ip",
6689 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6691 json_object_string_add(json_nexthop_global
, "afi",
6693 json_object_string_add(json_nexthop_global
, "scope",
6696 /* We display both LL & GL if both have been
6698 if ((attr
->mp_nexthop_len
== 32)
6699 || (binfo
->peer
->conf_if
)) {
6700 json_nexthop_ll
= json_object_new_object();
6701 json_object_string_add(
6702 json_nexthop_ll
, "ip",
6704 &attr
->mp_nexthop_local
, buf
,
6706 json_object_string_add(json_nexthop_ll
, "afi",
6708 json_object_string_add(json_nexthop_ll
, "scope",
6711 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6712 &attr
->mp_nexthop_local
)
6714 && !attr
->mp_nexthop_prefer_global
)
6715 json_object_boolean_true_add(
6716 json_nexthop_ll
, "used");
6718 json_object_boolean_true_add(
6719 json_nexthop_global
, "used");
6721 json_object_boolean_true_add(
6722 json_nexthop_global
, "used");
6724 /* Display LL if LL/Global both in table unless
6725 * prefer-global is set */
6726 if (((attr
->mp_nexthop_len
== 32)
6727 && !attr
->mp_nexthop_prefer_global
)
6728 || (binfo
->peer
->conf_if
)) {
6729 if (binfo
->peer
->conf_if
) {
6730 len
= vty_out(vty
, "%s",
6731 binfo
->peer
->conf_if
);
6732 len
= 16 - len
; /* len of IPv6
6738 vty_out(vty
, "\n%*s", 36, " ");
6740 vty_out(vty
, "%*s", len
, " ");
6746 &attr
->mp_nexthop_local
,
6752 vty_out(vty
, "\n%*s", 36, " ");
6754 vty_out(vty
, "%*s", len
, " ");
6760 &attr
->mp_nexthop_global
, buf
,
6766 vty_out(vty
, "\n%*s", 36, " ");
6768 vty_out(vty
, "%*s", len
, " ");
6774 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6776 json_object_int_add(json_path
, "med", attr
->med
);
6778 vty_out(vty
, "%10u", attr
->med
);
6779 else if (!json_paths
)
6783 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6785 json_object_int_add(json_path
, "localpref",
6788 vty_out(vty
, "%7u", attr
->local_pref
);
6789 else if (!json_paths
)
6793 json_object_int_add(json_path
, "weight", attr
->weight
);
6795 vty_out(vty
, "%7u ", attr
->weight
);
6799 json_object_string_add(
6800 json_path
, "peerId",
6801 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6807 json_object_string_add(json_path
, "aspath",
6810 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6815 json_object_string_add(json_path
, "origin",
6816 bgp_origin_long_str
[attr
->origin
]);
6818 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6822 json_object_boolean_true_add(json_path
,
6823 "announceNexthopSelf");
6824 if (nexthop_othervrf
) {
6825 json_object_string_add(json_path
, "nhVrfName",
6828 json_object_int_add(json_path
, "nhVrfId",
6829 ((nexthop_vrfid
== VRF_UNKNOWN
)
6831 : (int)nexthop_vrfid
));
6836 if (json_nexthop_global
|| json_nexthop_ll
) {
6837 json_nexthops
= json_object_new_array();
6839 if (json_nexthop_global
)
6840 json_object_array_add(json_nexthops
,
6841 json_nexthop_global
);
6843 if (json_nexthop_ll
)
6844 json_object_array_add(json_nexthops
,
6847 json_object_object_add(json_path
, "nexthops",
6851 json_object_array_add(json_paths
, json_path
);
6855 /* prints an additional line, indented, with VNC info, if
6857 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6858 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6863 /* called from terminal list command */
6864 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6865 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6867 json_object
*json_status
= NULL
;
6868 json_object
*json_net
= NULL
;
6870 /* Route status display. */
6872 json_status
= json_object_new_object();
6873 json_net
= json_object_new_object();
6880 /* print prefix and mask */
6882 json_object_string_add(
6883 json_net
, "addrPrefix",
6884 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6886 route_vty_out_route(p
, vty
, NULL
);
6888 /* Print attribute */
6891 if (p
->family
== AF_INET
6892 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6893 || safi
== SAFI_EVPN
6894 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6895 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6896 || safi
== SAFI_EVPN
)
6897 json_object_string_add(
6898 json_net
, "nextHop",
6900 attr
->mp_nexthop_global_in
));
6902 json_object_string_add(
6903 json_net
, "nextHop",
6904 inet_ntoa(attr
->nexthop
));
6905 } else if (p
->family
== AF_INET6
6906 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6909 json_object_string_add(
6910 json_net
, "netHopGloabal",
6912 &attr
->mp_nexthop_global
, buf
,
6917 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6918 json_object_int_add(json_net
, "metric",
6921 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6922 json_object_int_add(json_net
, "localPref",
6925 json_object_int_add(json_net
, "weight", attr
->weight
);
6929 json_object_string_add(json_net
, "asPath",
6933 json_object_string_add(json_net
, "bgpOriginCode",
6934 bgp_origin_str
[attr
->origin
]);
6936 if (p
->family
== AF_INET
6937 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6938 || safi
== SAFI_EVPN
6939 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6940 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6941 || safi
== SAFI_EVPN
)
6942 vty_out(vty
, "%-16s",
6944 attr
->mp_nexthop_global_in
));
6946 vty_out(vty
, "%-16s",
6947 inet_ntoa(attr
->nexthop
));
6948 } else if (p
->family
== AF_INET6
6949 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6956 &attr
->mp_nexthop_global
, buf
,
6960 vty_out(vty
, "\n%*s", 36, " ");
6962 vty_out(vty
, "%*s", len
, " ");
6965 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6966 vty_out(vty
, "%10u", attr
->med
);
6970 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6971 vty_out(vty
, "%7u", attr
->local_pref
);
6975 vty_out(vty
, "%7u ", attr
->weight
);
6979 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6982 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6986 json_object_boolean_true_add(json_status
, "*");
6987 json_object_boolean_true_add(json_status
, ">");
6988 json_object_object_add(json_net
, "appliedStatusSymbols",
6990 char buf_cut
[BUFSIZ
];
6991 json_object_object_add(
6993 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6999 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7000 struct bgp_info
*binfo
, int display
, safi_t safi
,
7003 json_object
*json_out
= NULL
;
7005 mpls_label_t label
= MPLS_INVALID_LABEL
;
7011 json_out
= json_object_new_object();
7013 /* short status lead text */
7014 route_vty_short_status_out(vty
, binfo
, json_out
);
7016 /* print prefix and mask */
7019 route_vty_out_route(p
, vty
, NULL
);
7021 vty_out(vty
, "%*s", 17, " ");
7024 /* Print attribute */
7027 if (((p
->family
== AF_INET
)
7028 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7029 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7030 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7031 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7032 || safi
== SAFI_EVPN
) {
7034 json_object_string_add(
7035 json_out
, "mpNexthopGlobalIn",
7037 attr
->mp_nexthop_global_in
));
7039 vty_out(vty
, "%-16s",
7041 attr
->mp_nexthop_global_in
));
7044 json_object_string_add(
7045 json_out
, "nexthop",
7046 inet_ntoa(attr
->nexthop
));
7048 vty_out(vty
, "%-16s",
7049 inet_ntoa(attr
->nexthop
));
7051 } else if (((p
->family
== AF_INET6
)
7052 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7053 || (safi
== SAFI_EVPN
7054 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7055 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7059 if (attr
->mp_nexthop_len
7060 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7062 json_object_string_add(
7063 json_out
, "mpNexthopGlobalIn",
7066 &attr
->mp_nexthop_global
,
7072 &attr
->mp_nexthop_global
,
7074 } else if (attr
->mp_nexthop_len
7075 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7078 &attr
->mp_nexthop_global
,
7081 &attr
->mp_nexthop_local
,
7083 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7084 json_object_string_add(
7086 "mpNexthopGlobalLocal", buf_c
);
7088 vty_out(vty
, "%s(%s)",
7091 &attr
->mp_nexthop_global
,
7095 &attr
->mp_nexthop_local
,
7101 label
= decode_label(&binfo
->extra
->label
[0]);
7103 if (bgp_is_valid_label(&label
)) {
7105 json_object_int_add(json_out
, "notag", label
);
7106 json_object_array_add(json
, json_out
);
7108 vty_out(vty
, "notag/%d", label
);
7114 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7115 struct bgp_info
*binfo
, int display
,
7116 json_object
*json_paths
)
7120 json_object
*json_path
= NULL
;
7123 json_path
= json_object_new_object();
7128 /* short status lead text */
7129 route_vty_short_status_out(vty
, binfo
, json_path
);
7131 /* print prefix and mask */
7133 route_vty_out_route(p
, vty
, NULL
);
7135 vty_out(vty
, "%*s", 17, " ");
7137 /* Print attribute */
7141 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7145 vty_out(vty
, "%-16s",
7146 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7150 vty_out(vty
, "%s(%s)",
7151 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7153 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7160 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7162 vty_out(vty
, "%s", str
);
7163 XFREE(MTYPE_TMP
, str
);
7165 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7167 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7168 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7171 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7174 if (attr
->ecommunity
) {
7176 struct ecommunity_val
*routermac
= ecommunity_lookup(
7177 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7178 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7180 mac
= ecom_mac2str((char *)routermac
->val
);
7182 vty_out(vty
, "/%s", (char *)mac
);
7183 XFREE(MTYPE_TMP
, mac
);
7191 /* dampening route */
7192 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7193 struct bgp_info
*binfo
, int display
, safi_t safi
,
7194 uint8_t use_json
, json_object
*json
)
7198 char timebuf
[BGP_UPTIME_LEN
];
7200 /* short status lead text */
7201 route_vty_short_status_out(vty
, binfo
, json
);
7203 /* print prefix and mask */
7206 route_vty_out_route(p
, vty
, NULL
);
7208 vty_out(vty
, "%*s", 17, " ");
7211 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7215 vty_out(vty
, "\n%*s", 34, " ");
7218 json_object_int_add(json
, "peerHost", len
);
7220 vty_out(vty
, "%*s", len
, " ");
7224 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7227 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7231 /* Print attribute */
7237 json_object_string_add(json
, "asPath",
7240 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7245 json_object_string_add(json
, "origin",
7246 bgp_origin_str
[attr
->origin
]);
7248 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7255 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7256 struct bgp_info
*binfo
, int display
, safi_t safi
,
7257 uint8_t use_json
, json_object
*json
)
7260 struct bgp_damp_info
*bdi
;
7261 char timebuf
[BGP_UPTIME_LEN
];
7267 bdi
= binfo
->extra
->damp_info
;
7269 /* short status lead text */
7270 route_vty_short_status_out(vty
, binfo
, json
);
7272 /* print prefix and mask */
7275 route_vty_out_route(p
, vty
, NULL
);
7277 vty_out(vty
, "%*s", 17, " ");
7280 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7284 vty_out(vty
, "\n%*s", 33, " ");
7287 json_object_int_add(json
, "peerHost", len
);
7289 vty_out(vty
, "%*s", len
, " ");
7292 len
= vty_out(vty
, "%d", bdi
->flap
);
7299 json_object_int_add(json
, "bdiFlap", len
);
7301 vty_out(vty
, "%*s", len
, " ");
7305 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7308 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7309 BGP_UPTIME_LEN
, 0, NULL
));
7311 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7312 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7314 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7315 BGP_UPTIME_LEN
, use_json
, json
);
7318 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7323 vty_out(vty
, "%*s ", 8, " ");
7326 /* Print attribute */
7332 json_object_string_add(json
, "asPath",
7335 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7340 json_object_string_add(json
, "origin",
7341 bgp_origin_str
[attr
->origin
]);
7343 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7349 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7350 int *first
, const char *header
,
7351 json_object
*json_adv_to
)
7353 char buf1
[INET6_ADDRSTRLEN
];
7354 json_object
*json_peer
= NULL
;
7357 /* 'advertised-to' is a dictionary of peers we have advertised
7359 * prefix too. The key is the peer's IP or swpX, the value is
7361 * hostname if we know it and "" if not.
7363 json_peer
= json_object_new_object();
7366 json_object_string_add(json_peer
, "hostname",
7370 json_object_object_add(json_adv_to
, peer
->conf_if
,
7373 json_object_object_add(
7375 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7379 vty_out(vty
, "%s", header
);
7384 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7386 vty_out(vty
, " %s(%s)", peer
->hostname
,
7389 vty_out(vty
, " %s(%s)", peer
->hostname
,
7390 sockunion2str(&peer
->su
, buf1
,
7394 vty_out(vty
, " %s", peer
->conf_if
);
7397 sockunion2str(&peer
->su
, buf1
,
7403 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7404 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7405 json_object
*json_paths
)
7407 char buf
[INET6_ADDRSTRLEN
];
7409 #if defined(HAVE_CUMULUS)
7410 char buf2
[EVPN_ROUTE_STRLEN
];
7413 int sockunion_vty_out(struct vty
*, union sockunion
*);
7415 json_object
*json_bestpath
= NULL
;
7416 json_object
*json_cluster_list
= NULL
;
7417 json_object
*json_cluster_list_list
= NULL
;
7418 json_object
*json_ext_community
= NULL
;
7419 json_object
*json_last_update
= NULL
;
7420 json_object
*json_pmsi
= NULL
;
7421 json_object
*json_nexthop_global
= NULL
;
7422 json_object
*json_nexthop_ll
= NULL
;
7423 json_object
*json_nexthops
= NULL
;
7424 json_object
*json_path
= NULL
;
7425 json_object
*json_peer
= NULL
;
7426 json_object
*json_string
= NULL
;
7427 json_object
*json_adv_to
= NULL
;
7429 struct listnode
*node
, *nnode
;
7431 int addpath_capable
;
7433 unsigned int first_as
;
7434 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7439 json_path
= json_object_new_object();
7440 json_peer
= json_object_new_object();
7441 json_nexthop_global
= json_object_new_object();
7444 #if defined(HAVE_CUMULUS)
7445 if (!json_paths
&& safi
== SAFI_EVPN
) {
7448 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7449 vty_out(vty
, " Route %s", buf2
);
7451 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7452 bgp_evpn_label2str(binfo
->extra
->label
,
7453 binfo
->extra
->num_labels
, tag_buf
,
7455 vty_out(vty
, " VNI %s", tag_buf
);
7458 if (binfo
->extra
&& binfo
->extra
->parent
) {
7459 struct bgp_info
*parent_ri
;
7460 struct bgp_node
*rn
, *prn
;
7462 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7463 rn
= parent_ri
->net
;
7464 if (rn
&& rn
->prn
) {
7466 vty_out(vty
, " Imported from %s:%s\n",
7468 (struct prefix_rd
*)&prn
->p
,
7469 buf1
, sizeof(buf1
)),
7479 /* Line1 display AS-path, Aggregator */
7482 if (!attr
->aspath
->json
)
7483 aspath_str_update(attr
->aspath
, true);
7484 json_object_lock(attr
->aspath
->json
);
7485 json_object_object_add(json_path
, "aspath",
7486 attr
->aspath
->json
);
7488 if (attr
->aspath
->segments
)
7489 aspath_print_vty(vty
, " %s",
7492 vty_out(vty
, " Local");
7496 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7498 json_object_boolean_true_add(json_path
,
7501 vty_out(vty
, ", (removed)");
7504 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7506 json_object_boolean_true_add(json_path
,
7509 vty_out(vty
, ", (stale)");
7512 if (CHECK_FLAG(attr
->flag
,
7513 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7515 json_object_int_add(json_path
, "aggregatorAs",
7516 attr
->aggregator_as
);
7517 json_object_string_add(
7518 json_path
, "aggregatorId",
7519 inet_ntoa(attr
->aggregator_addr
));
7521 vty_out(vty
, ", (aggregated by %u %s)",
7522 attr
->aggregator_as
,
7523 inet_ntoa(attr
->aggregator_addr
));
7527 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7528 PEER_FLAG_REFLECTOR_CLIENT
)) {
7530 json_object_boolean_true_add(
7531 json_path
, "rxedFromRrClient");
7533 vty_out(vty
, ", (Received from a RR-client)");
7536 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7537 PEER_FLAG_RSERVER_CLIENT
)) {
7539 json_object_boolean_true_add(
7540 json_path
, "rxedFromRsClient");
7542 vty_out(vty
, ", (Received from a RS-client)");
7545 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7547 json_object_boolean_true_add(
7548 json_path
, "dampeningHistoryEntry");
7550 vty_out(vty
, ", (history entry)");
7551 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7553 json_object_boolean_true_add(
7554 json_path
, "dampeningSuppressed");
7556 vty_out(vty
, ", (suppressed due to dampening)");
7562 /* Line2 display Next-hop, Neighbor, Router-id */
7563 /* Display the nexthop */
7564 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7565 || p
->family
== AF_EVPN
)
7566 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7567 || safi
== SAFI_EVPN
7568 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7569 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7570 || safi
== SAFI_EVPN
) {
7572 json_object_string_add(
7573 json_nexthop_global
, "ip",
7575 attr
->mp_nexthop_global_in
));
7579 attr
->mp_nexthop_global_in
));
7582 json_object_string_add(
7583 json_nexthop_global
, "ip",
7584 inet_ntoa(attr
->nexthop
));
7587 inet_ntoa(attr
->nexthop
));
7591 json_object_string_add(json_nexthop_global
,
7595 json_object_string_add(
7596 json_nexthop_global
, "ip",
7598 &attr
->mp_nexthop_global
, buf
,
7600 json_object_string_add(json_nexthop_global
,
7602 json_object_string_add(json_nexthop_global
,
7607 &attr
->mp_nexthop_global
, buf
,
7612 /* Display the IGP cost or 'inaccessible' */
7613 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7615 json_object_boolean_false_add(
7616 json_nexthop_global
, "accessible");
7618 vty_out(vty
, " (inaccessible)");
7620 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7622 json_object_int_add(
7623 json_nexthop_global
, "metric",
7624 binfo
->extra
->igpmetric
);
7626 vty_out(vty
, " (metric %u)",
7627 binfo
->extra
->igpmetric
);
7630 /* IGP cost is 0, display this only for json */
7633 json_object_int_add(json_nexthop_global
,
7638 json_object_boolean_true_add(
7639 json_nexthop_global
, "accessible");
7642 /* Display peer "from" output */
7643 /* This path was originated locally */
7644 if (binfo
->peer
== bgp
->peer_self
) {
7646 if (safi
== SAFI_EVPN
7647 || (p
->family
== AF_INET
7648 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7650 json_object_string_add(
7651 json_peer
, "peerId", "0.0.0.0");
7653 vty_out(vty
, " from 0.0.0.0 ");
7656 json_object_string_add(json_peer
,
7659 vty_out(vty
, " from :: ");
7663 json_object_string_add(
7664 json_peer
, "routerId",
7665 inet_ntoa(bgp
->router_id
));
7667 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7670 /* We RXed this path from one of our peers */
7674 json_object_string_add(
7675 json_peer
, "peerId",
7676 sockunion2str(&binfo
->peer
->su
, buf
,
7678 json_object_string_add(
7679 json_peer
, "routerId",
7681 &binfo
->peer
->remote_id
, buf1
,
7684 if (binfo
->peer
->hostname
)
7685 json_object_string_add(
7686 json_peer
, "hostname",
7687 binfo
->peer
->hostname
);
7689 if (binfo
->peer
->domainname
)
7690 json_object_string_add(
7691 json_peer
, "domainname",
7692 binfo
->peer
->domainname
);
7694 if (binfo
->peer
->conf_if
)
7695 json_object_string_add(
7696 json_peer
, "interface",
7697 binfo
->peer
->conf_if
);
7699 if (binfo
->peer
->conf_if
) {
7700 if (binfo
->peer
->hostname
7703 BGP_FLAG_SHOW_HOSTNAME
))
7704 vty_out(vty
, " from %s(%s)",
7705 binfo
->peer
->hostname
,
7706 binfo
->peer
->conf_if
);
7708 vty_out(vty
, " from %s",
7709 binfo
->peer
->conf_if
);
7711 if (binfo
->peer
->hostname
7714 BGP_FLAG_SHOW_HOSTNAME
))
7715 vty_out(vty
, " from %s(%s)",
7716 binfo
->peer
->hostname
,
7719 vty_out(vty
, " from %s",
7728 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7729 vty_out(vty
, " (%s)",
7730 inet_ntoa(attr
->originator_id
));
7732 vty_out(vty
, " (%s)",
7735 &binfo
->peer
->remote_id
,
7736 buf1
, sizeof(buf1
)));
7741 * Note when vrfid of nexthop is different from that of prefix
7743 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7744 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7749 if (binfo
->extra
->bgp_orig
->inst_type
==
7750 BGP_INSTANCE_TYPE_DEFAULT
)
7754 vn
= binfo
->extra
->bgp_orig
->name
;
7756 json_object_string_add(json_path
, "nhVrfName",
7759 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7760 json_object_int_add(json_path
,
7763 json_object_int_add(json_path
,
7764 "nhVrfId", (int)nexthop_vrfid
);
7767 if (nexthop_vrfid
== VRF_UNKNOWN
)
7768 vty_out(vty
, " vrf ?");
7770 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7776 json_object_boolean_true_add(json_path
,
7777 "announceNexthopSelf");
7779 vty_out(vty
, " announce-nh-self");
7786 /* display the link-local nexthop */
7787 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7789 json_nexthop_ll
= json_object_new_object();
7790 json_object_string_add(
7791 json_nexthop_ll
, "ip",
7793 &attr
->mp_nexthop_local
, buf
,
7795 json_object_string_add(json_nexthop_ll
, "afi",
7797 json_object_string_add(json_nexthop_ll
, "scope",
7800 json_object_boolean_true_add(json_nexthop_ll
,
7803 if (!attr
->mp_nexthop_prefer_global
)
7804 json_object_boolean_true_add(
7805 json_nexthop_ll
, "used");
7807 json_object_boolean_true_add(
7808 json_nexthop_global
, "used");
7810 vty_out(vty
, " (%s) %s\n",
7812 &attr
->mp_nexthop_local
, buf
,
7814 attr
->mp_nexthop_prefer_global
7819 /* If we do not have a link-local nexthop then we must flag the
7823 json_object_boolean_true_add(
7824 json_nexthop_global
, "used");
7827 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7828 * Int/Ext/Local, Atomic, best */
7830 json_object_string_add(
7831 json_path
, "origin",
7832 bgp_origin_long_str
[attr
->origin
]);
7834 vty_out(vty
, " Origin %s",
7835 bgp_origin_long_str
[attr
->origin
]);
7837 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7839 json_object_int_add(json_path
, "med",
7842 vty_out(vty
, ", metric %u", attr
->med
);
7845 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7847 json_object_int_add(json_path
, "localpref",
7850 vty_out(vty
, ", localpref %u",
7854 json_object_int_add(json_path
, "localpref",
7855 bgp
->default_local_pref
);
7857 vty_out(vty
, ", localpref %u",
7858 bgp
->default_local_pref
);
7861 if (attr
->weight
!= 0) {
7863 json_object_int_add(json_path
, "weight",
7866 vty_out(vty
, ", weight %u", attr
->weight
);
7869 if (attr
->tag
!= 0) {
7871 json_object_int_add(json_path
, "tag",
7874 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7878 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7880 json_object_boolean_false_add(json_path
,
7883 vty_out(vty
, ", invalid");
7884 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7886 json_object_boolean_true_add(json_path
,
7889 vty_out(vty
, ", valid");
7892 if (binfo
->peer
!= bgp
->peer_self
) {
7893 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7894 if (CHECK_FLAG(bgp
->config
,
7895 BGP_CONFIG_CONFEDERATION
)) {
7897 json_object_string_add(
7902 ", confed-internal");
7905 json_object_string_add(
7909 vty_out(vty
, ", internal");
7912 if (bgp_confederation_peers_check(
7913 bgp
, binfo
->peer
->as
)) {
7915 json_object_string_add(
7920 ", confed-external");
7923 json_object_string_add(
7927 vty_out(vty
, ", external");
7930 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7932 json_object_boolean_true_add(json_path
,
7934 json_object_boolean_true_add(json_path
,
7937 vty_out(vty
, ", aggregated, local");
7939 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7941 json_object_boolean_true_add(json_path
,
7944 vty_out(vty
, ", sourced");
7947 json_object_boolean_true_add(json_path
,
7949 json_object_boolean_true_add(json_path
,
7952 vty_out(vty
, ", sourced, local");
7956 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7958 json_object_boolean_true_add(json_path
,
7961 vty_out(vty
, ", atomic-aggregate");
7964 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7965 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7966 && bgp_info_mpath_count(binfo
))) {
7968 json_object_boolean_true_add(json_path
,
7971 vty_out(vty
, ", multipath");
7974 // Mark the bestpath(s)
7975 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7976 first_as
= aspath_get_first_as(attr
->aspath
);
7981 json_object_new_object();
7982 json_object_int_add(json_bestpath
,
7983 "bestpathFromAs", first_as
);
7986 vty_out(vty
, ", bestpath-from-AS %u",
7990 ", bestpath-from-AS Local");
7994 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7998 json_object_new_object();
7999 json_object_boolean_true_add(json_bestpath
,
8002 vty_out(vty
, ", best");
8006 json_object_object_add(json_path
, "bestpath",
8012 /* Line 4 display Community */
8013 if (attr
->community
) {
8015 if (!attr
->community
->json
)
8016 community_str(attr
->community
, true);
8017 json_object_lock(attr
->community
->json
);
8018 json_object_object_add(json_path
, "community",
8019 attr
->community
->json
);
8021 vty_out(vty
, " Community: %s\n",
8022 attr
->community
->str
);
8026 /* Line 5 display Extended-community */
8027 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8029 json_ext_community
= json_object_new_object();
8030 json_object_string_add(json_ext_community
,
8032 attr
->ecommunity
->str
);
8033 json_object_object_add(json_path
,
8034 "extendedCommunity",
8035 json_ext_community
);
8037 vty_out(vty
, " Extended Community: %s\n",
8038 attr
->ecommunity
->str
);
8042 /* Line 6 display Large community */
8043 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8045 if (!attr
->lcommunity
->json
)
8046 lcommunity_str(attr
->lcommunity
, true);
8047 json_object_lock(attr
->lcommunity
->json
);
8048 json_object_object_add(json_path
,
8050 attr
->lcommunity
->json
);
8052 vty_out(vty
, " Large Community: %s\n",
8053 attr
->lcommunity
->str
);
8057 /* Line 7 display Originator, Cluster-id */
8058 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8059 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8061 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8063 json_object_string_add(
8064 json_path
, "originatorId",
8065 inet_ntoa(attr
->originator_id
));
8067 vty_out(vty
, " Originator: %s",
8068 inet_ntoa(attr
->originator_id
));
8071 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8076 json_object_new_object();
8077 json_cluster_list_list
=
8078 json_object_new_array();
8081 i
< attr
->cluster
->length
/ 4;
8083 json_string
= json_object_new_string(
8087 json_object_array_add(
8088 json_cluster_list_list
,
8092 /* struct cluster_list does not have
8094 * aspath and community do. Add this
8097 json_object_string_add(json_cluster_list,
8098 "string", attr->cluster->str);
8100 json_object_object_add(
8101 json_cluster_list
, "list",
8102 json_cluster_list_list
);
8103 json_object_object_add(
8104 json_path
, "clusterList",
8107 vty_out(vty
, ", Cluster list: ");
8110 i
< attr
->cluster
->length
/ 4;
8124 if (binfo
->extra
&& binfo
->extra
->damp_info
)
8125 bgp_damp_info_vty(vty
, binfo
, json_path
);
8128 #if defined(HAVE_CUMULUS)
8129 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8130 && safi
!= SAFI_EVPN
)
8132 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0]))
8135 mpls_label_t label
=
8136 label_pton(&binfo
->extra
->label
[0]);
8138 json_object_int_add(json_path
, "remoteLabel",
8141 vty_out(vty
, " Remote label: %d\n", label
);
8145 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8147 json_object_int_add(json_path
, "labelIndex",
8150 vty_out(vty
, " Label Index: %d\n",
8154 /* Line 8 display Addpath IDs */
8155 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8157 json_object_int_add(json_path
, "addpathRxId",
8158 binfo
->addpath_rx_id
);
8159 json_object_int_add(json_path
, "addpathTxId",
8160 binfo
->addpath_tx_id
);
8162 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8163 binfo
->addpath_rx_id
,
8164 binfo
->addpath_tx_id
);
8168 /* If we used addpath to TX a non-bestpath we need to display
8169 * "Advertised to" on a path-by-path basis */
8170 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8173 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8175 bgp_addpath_encode_tx(peer
, afi
, safi
);
8176 has_adj
= bgp_adj_out_lookup(
8177 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8179 if ((addpath_capable
&& has_adj
)
8180 || (!addpath_capable
&& has_adj
8181 && CHECK_FLAG(binfo
->flags
,
8182 BGP_INFO_SELECTED
))) {
8183 if (json_path
&& !json_adv_to
)
8185 json_object_new_object();
8187 route_vty_out_advertised_to(
8196 json_object_object_add(json_path
,
8207 /* Line 9 display Uptime */
8208 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8210 json_last_update
= json_object_new_object();
8211 json_object_int_add(json_last_update
, "epoch", tbuf
);
8212 json_object_string_add(json_last_update
, "string",
8214 json_object_object_add(json_path
, "lastUpdate",
8217 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8219 /* Line 10 display PMSI tunnel attribute, if present */
8220 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8221 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8222 attr
->pmsi_tnl_type
,
8223 PMSI_TNLTYPE_STR_DEFAULT
);
8226 json_pmsi
= json_object_new_object();
8227 json_object_string_add(json_pmsi
,
8229 json_object_object_add(json_path
, "pmsi",
8232 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8238 /* We've constructed the json object for this path, add it to the json
8242 if (json_nexthop_global
|| json_nexthop_ll
) {
8243 json_nexthops
= json_object_new_array();
8245 if (json_nexthop_global
)
8246 json_object_array_add(json_nexthops
,
8247 json_nexthop_global
);
8249 if (json_nexthop_ll
)
8250 json_object_array_add(json_nexthops
,
8253 json_object_object_add(json_path
, "nexthops",
8257 json_object_object_add(json_path
, "peer", json_peer
);
8258 json_object_array_add(json_paths
, json_path
);
8263 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8264 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8265 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8267 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8268 const char *prefix_list_str
, afi_t afi
,
8269 safi_t safi
, enum bgp_show_type type
);
8270 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8271 const char *filter
, afi_t afi
, safi_t safi
,
8272 enum bgp_show_type type
);
8273 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8274 const char *rmap_str
, afi_t afi
, safi_t safi
,
8275 enum bgp_show_type type
);
8276 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8277 const char *com
, int exact
, afi_t afi
,
8279 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8280 const char *prefix
, afi_t afi
, safi_t safi
,
8281 enum bgp_show_type type
);
8282 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8283 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8284 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8285 const char *comstr
, int exact
, afi_t afi
,
8289 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8290 struct bgp_table
*table
, enum bgp_show_type type
,
8291 void *output_arg
, uint8_t use_json
, char *rd
,
8292 int is_last
, unsigned long *output_cum
,
8293 unsigned long *total_cum
,
8294 unsigned long *json_header_depth
)
8296 struct bgp_info
*ri
;
8297 struct bgp_node
*rn
;
8300 unsigned long output_count
= 0;
8301 unsigned long total_count
= 0;
8305 json_object
*json_paths
= NULL
;
8308 if (output_cum
&& *output_cum
!= 0)
8311 if (use_json
&& !*json_header_depth
) {
8313 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8314 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8315 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8316 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8318 table
->version
, inet_ntoa(bgp
->router_id
));
8319 *json_header_depth
= 2;
8321 vty_out(vty
, " \"routeDistinguishers\" : {");
8322 ++*json_header_depth
;
8324 json_paths
= json_object_new_object();
8327 if (use_json
&& rd
) {
8328 vty_out(vty
, " \"%s\" : { ", rd
);
8331 /* Start processing of routes. */
8332 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8333 if (rn
->info
== NULL
)
8338 json_paths
= json_object_new_array();
8342 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8344 if (type
== bgp_show_type_flap_statistics
8345 || type
== bgp_show_type_flap_neighbor
8346 || type
== bgp_show_type_dampend_paths
8347 || type
== bgp_show_type_damp_neighbor
) {
8348 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8351 if (type
== bgp_show_type_regexp
) {
8352 regex_t
*regex
= output_arg
;
8354 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8358 if (type
== bgp_show_type_prefix_list
) {
8359 struct prefix_list
*plist
= output_arg
;
8361 if (prefix_list_apply(plist
, &rn
->p
)
8365 if (type
== bgp_show_type_filter_list
) {
8366 struct as_list
*as_list
= output_arg
;
8368 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8369 != AS_FILTER_PERMIT
)
8372 if (type
== bgp_show_type_route_map
) {
8373 struct route_map
*rmap
= output_arg
;
8374 struct bgp_info binfo
;
8375 struct attr dummy_attr
;
8378 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8380 binfo
.peer
= ri
->peer
;
8381 binfo
.attr
= &dummy_attr
;
8383 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8385 if (ret
== RMAP_DENYMATCH
)
8388 if (type
== bgp_show_type_neighbor
8389 || type
== bgp_show_type_flap_neighbor
8390 || type
== bgp_show_type_damp_neighbor
) {
8391 union sockunion
*su
= output_arg
;
8393 if (ri
->peer
== NULL
8394 || ri
->peer
->su_remote
== NULL
8395 || !sockunion_same(ri
->peer
->su_remote
, su
))
8398 if (type
== bgp_show_type_cidr_only
) {
8399 uint32_t destination
;
8401 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8402 if (IN_CLASSC(destination
)
8403 && rn
->p
.prefixlen
== 24)
8405 if (IN_CLASSB(destination
)
8406 && rn
->p
.prefixlen
== 16)
8408 if (IN_CLASSA(destination
)
8409 && rn
->p
.prefixlen
== 8)
8412 if (type
== bgp_show_type_prefix_longer
) {
8413 struct prefix
*p
= output_arg
;
8415 if (!prefix_match(p
, &rn
->p
))
8418 if (type
== bgp_show_type_community_all
) {
8419 if (!ri
->attr
->community
)
8422 if (type
== bgp_show_type_community
) {
8423 struct community
*com
= output_arg
;
8425 if (!ri
->attr
->community
8426 || !community_match(ri
->attr
->community
,
8430 if (type
== bgp_show_type_community_exact
) {
8431 struct community
*com
= output_arg
;
8433 if (!ri
->attr
->community
8434 || !community_cmp(ri
->attr
->community
, com
))
8437 if (type
== bgp_show_type_community_list
) {
8438 struct community_list
*list
= output_arg
;
8440 if (!community_list_match(ri
->attr
->community
,
8444 if (type
== bgp_show_type_community_list_exact
) {
8445 struct community_list
*list
= output_arg
;
8447 if (!community_list_exact_match(
8448 ri
->attr
->community
, list
))
8451 if (type
== bgp_show_type_lcommunity
) {
8452 struct lcommunity
*lcom
= output_arg
;
8454 if (!ri
->attr
->lcommunity
8455 || !lcommunity_match(ri
->attr
->lcommunity
,
8459 if (type
== bgp_show_type_lcommunity_list
) {
8460 struct community_list
*list
= output_arg
;
8462 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8466 if (type
== bgp_show_type_lcommunity_all
) {
8467 if (!ri
->attr
->lcommunity
)
8470 if (type
== bgp_show_type_dampend_paths
8471 || type
== bgp_show_type_damp_neighbor
) {
8472 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8473 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8477 if (!use_json
&& header
) {
8478 vty_out(vty
, "BGP table version is %" PRIu64
8479 ", local router ID is %s, vrf id ",
8481 inet_ntoa(bgp
->router_id
));
8482 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8483 vty_out(vty
, "%s", VRFID_NONE_STR
);
8485 vty_out(vty
, "%u", bgp
->vrf_id
);
8487 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8488 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8489 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8490 if (type
== bgp_show_type_dampend_paths
8491 || type
== bgp_show_type_damp_neighbor
)
8492 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8493 else if (type
== bgp_show_type_flap_statistics
8494 || type
== bgp_show_type_flap_neighbor
)
8495 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8497 vty_out(vty
, BGP_SHOW_HEADER
);
8500 if (rd
!= NULL
&& !display
&& !output_count
) {
8503 "Route Distinguisher: %s\n",
8506 if (type
== bgp_show_type_dampend_paths
8507 || type
== bgp_show_type_damp_neighbor
)
8508 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8509 safi
, use_json
, json_paths
);
8510 else if (type
== bgp_show_type_flap_statistics
8511 || type
== bgp_show_type_flap_neighbor
)
8512 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8513 safi
, use_json
, json_paths
);
8515 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8526 sprintf(buf2
, "%s/%d",
8527 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8530 vty_out(vty
, "\"%s\": ", buf2
);
8532 vty_out(vty
, ",\"%s\": ", buf2
);
8535 json_object_to_json_string(json_paths
));
8536 json_object_free(json_paths
);
8543 output_count
+= *output_cum
;
8544 *output_cum
= output_count
;
8547 total_count
+= *total_cum
;
8548 *total_cum
= total_count
;
8552 json_object_free(json_paths
);
8554 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8558 for (i
= 0; i
< *json_header_depth
; ++i
)
8559 vty_out(vty
, " } ");
8563 /* No route is displayed */
8564 if (output_count
== 0) {
8565 if (type
== bgp_show_type_normal
)
8567 "No BGP prefixes displayed, %ld exist\n",
8571 "\nDisplayed %ld routes and %ld total paths\n",
8572 output_count
, total_count
);
8579 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8580 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8581 enum bgp_show_type type
, void *output_arg
,
8584 struct bgp_node
*rn
, *next
;
8585 unsigned long output_cum
= 0;
8586 unsigned long total_cum
= 0;
8587 unsigned long json_header_depth
= 0;
8590 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8592 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8593 next
= bgp_route_next(rn
);
8594 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8596 if (rn
->info
!= NULL
) {
8597 struct prefix_rd prd
;
8598 char rd
[RD_ADDRSTRLEN
];
8600 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8601 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8602 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8603 output_arg
, use_json
, rd
, next
== NULL
,
8604 &output_cum
, &total_cum
,
8605 &json_header_depth
);
8611 if (output_cum
== 0)
8612 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8616 "\nDisplayed %ld routes and %ld total paths\n",
8617 output_cum
, total_cum
);
8621 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8622 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8624 struct bgp_table
*table
;
8625 unsigned long json_header_depth
= 0;
8628 bgp
= bgp_get_default();
8633 vty_out(vty
, "No BGP process is configured\n");
8635 vty_out(vty
, "{}\n");
8639 table
= bgp
->rib
[afi
][safi
];
8640 /* use MPLS and ENCAP specific shows until they are merged */
8641 if (safi
== SAFI_MPLS_VPN
) {
8642 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8643 output_arg
, use_json
);
8646 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8647 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8648 output_arg
, use_json
,
8651 /* labeled-unicast routes live in the unicast table */
8652 else if (safi
== SAFI_LABELED_UNICAST
)
8653 safi
= SAFI_UNICAST
;
8655 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8656 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8659 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8660 safi_t safi
, uint8_t use_json
)
8662 struct listnode
*node
, *nnode
;
8667 vty_out(vty
, "{\n");
8669 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8672 vty_out(vty
, ",\n");
8676 vty_out(vty
, "\"%s\":",
8677 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8681 vty_out(vty
, "\nInstance %s:\n",
8682 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8686 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8691 vty_out(vty
, "}\n");
8694 /* Header of detailed BGP route information */
8695 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8696 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8697 afi_t afi
, safi_t safi
, json_object
*json
)
8699 struct bgp_info
*ri
;
8702 struct listnode
*node
, *nnode
;
8703 char buf1
[RD_ADDRSTRLEN
];
8704 char buf2
[INET6_ADDRSTRLEN
];
8705 #if defined(HAVE_CUMULUS)
8706 char buf3
[EVPN_ROUTE_STRLEN
];
8708 char prefix_str
[BUFSIZ
];
8713 int no_advertise
= 0;
8716 int has_valid_label
= 0;
8717 mpls_label_t label
= 0;
8718 json_object
*json_adv_to
= NULL
;
8721 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8723 if (has_valid_label
)
8724 label
= label_pton(&rn
->local_label
);
8727 if (has_valid_label
)
8728 json_object_int_add(json
, "localLabel", label
);
8730 json_object_string_add(
8732 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8734 #if defined(HAVE_CUMULUS)
8735 if (safi
== SAFI_EVPN
)
8736 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8737 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8740 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8741 buf3
, sizeof(buf3
)));
8743 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8744 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8745 ? prefix_rd2str(prd
, buf1
,
8748 safi
== SAFI_MPLS_VPN
? ":" : "",
8749 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8753 if (p
->family
== AF_ETHERNET
)
8754 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8756 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8758 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8759 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8760 || safi
== SAFI_EVPN
)
8761 ? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8763 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8765 buf2
, p
->prefixlen
);
8768 if (has_valid_label
)
8769 vty_out(vty
, "Local label: %d\n", label
);
8770 #if defined(HAVE_CUMULUS)
8771 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8773 if (bgp_labeled_safi(safi
))
8775 vty_out(vty
, "not allocated\n");
8778 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8780 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8782 if (ri
->extra
&& ri
->extra
->suppress
)
8784 if (ri
->attr
->community
!= NULL
) {
8785 if (community_include(ri
->attr
->community
,
8786 COMMUNITY_NO_ADVERTISE
))
8788 if (community_include(ri
->attr
->community
,
8789 COMMUNITY_NO_EXPORT
))
8791 if (community_include(ri
->attr
->community
,
8792 COMMUNITY_LOCAL_AS
))
8799 vty_out(vty
, "Paths: (%d available", count
);
8801 vty_out(vty
, ", best #%d", best
);
8802 if (safi
== SAFI_UNICAST
)
8803 vty_out(vty
, ", table %s",
8805 == BGP_INSTANCE_TYPE_DEFAULT
)
8806 ? "Default-IP-Routing-Table"
8809 vty_out(vty
, ", no best path");
8812 vty_out(vty
, ", not advertised to any peer");
8814 vty_out(vty
, ", not advertised to EBGP peer");
8816 vty_out(vty
, ", not advertised outside local AS");
8820 ", Advertisements suppressed by an aggregate.");
8821 vty_out(vty
, ")\n");
8824 /* If we are not using addpath then we can display Advertised to and
8826 * show what peers we advertised the bestpath to. If we are using
8828 * though then we must display Advertised to on a path-by-path basis. */
8829 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8830 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8831 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8832 if (json
&& !json_adv_to
)
8833 json_adv_to
= json_object_new_object();
8835 route_vty_out_advertised_to(
8837 " Advertised to non peer-group peers:\n ",
8844 json_object_object_add(json
, "advertisedTo",
8849 vty_out(vty
, " Not advertised to any peer");
8855 /* Display specified route of BGP table. */
8856 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8857 struct bgp_table
*rib
, const char *ip_str
,
8858 afi_t afi
, safi_t safi
,
8859 struct prefix_rd
*prd
, int prefix_check
,
8860 enum bgp_path_type pathtype
,
8866 struct prefix match
;
8867 struct bgp_node
*rn
;
8868 struct bgp_node
*rm
;
8869 struct bgp_info
*ri
;
8870 struct bgp_table
*table
;
8871 json_object
*json
= NULL
;
8872 json_object
*json_paths
= NULL
;
8874 /* Check IP address argument. */
8875 ret
= str2prefix(ip_str
, &match
);
8877 vty_out(vty
, "address is malformed\n");
8881 match
.family
= afi2family(afi
);
8884 json
= json_object_new_object();
8885 json_paths
= json_object_new_array();
8888 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8889 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8890 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8893 if ((table
= rn
->info
) == NULL
)
8898 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8902 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8903 bgp_unlock_node(rm
);
8907 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8909 route_vty_out_detail_header(
8911 (struct prefix_rd
*)&rn
->p
,
8912 AFI_IP
, safi
, json
);
8917 if (pathtype
== BGP_PATH_ALL
8918 || (pathtype
== BGP_PATH_BESTPATH
8919 && CHECK_FLAG(ri
->flags
,
8921 || (pathtype
== BGP_PATH_MULTIPATH
8922 && (CHECK_FLAG(ri
->flags
,
8924 || CHECK_FLAG(ri
->flags
,
8925 BGP_INFO_SELECTED
))))
8926 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8931 bgp_unlock_node(rm
);
8933 } else if (safi
== SAFI_FLOWSPEC
) {
8934 rn
= bgp_flowspec_get_match_per_ip(afi
, rib
,
8935 &match
, prefix_check
);
8937 route_vty_out_flowspec(vty
, &rn
->p
,
8938 rn
->info
, use_json
?
8939 NLRI_STRING_FORMAT_JSON
:
8940 NLRI_STRING_FORMAT_LARGE
,
8943 bgp_unlock_node(rn
);
8948 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8950 || rn
->p
.prefixlen
== match
.prefixlen
) {
8951 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8953 route_vty_out_detail_header(
8954 vty
, bgp
, rn
, NULL
, afi
,
8960 if (pathtype
== BGP_PATH_ALL
8961 || (pathtype
== BGP_PATH_BESTPATH
8965 || (pathtype
== BGP_PATH_MULTIPATH
8971 BGP_INFO_SELECTED
))))
8972 route_vty_out_detail(
8973 vty
, bgp
, &rn
->p
, ri
,
8974 afi
, safi
, json_paths
);
8978 bgp_unlock_node(rn
);
8984 json_object_object_add(json
, "paths", json_paths
);
8986 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8987 json
, JSON_C_TO_STRING_PRETTY
));
8988 json_object_free(json
);
8991 vty_out(vty
, "%% Network not in table\n");
8999 /* Display specified route of Main RIB */
9000 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9001 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9002 int prefix_check
, enum bgp_path_type pathtype
,
9006 bgp
= bgp_get_default();
9009 vty_out(vty
, "No BGP process is configured\n");
9011 vty_out(vty
, "{}\n");
9016 /* labeled-unicast routes live in the unicast table */
9017 if (safi
== SAFI_LABELED_UNICAST
)
9018 safi
= SAFI_UNICAST
;
9020 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9021 afi
, safi
, prd
, prefix_check
, pathtype
,
9025 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9026 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9029 struct lcommunity
*lcom
;
9035 b
= buffer_new(1024);
9036 for (i
= 0; i
< argc
; i
++) {
9038 buffer_putc(b
, ' ');
9040 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9042 buffer_putstr(b
, argv
[i
]->arg
);
9046 buffer_putc(b
, '\0');
9048 str
= buffer_getstr(b
);
9051 lcom
= lcommunity_str2com(str
);
9052 XFREE(MTYPE_TMP
, str
);
9054 vty_out(vty
, "%% Large-community malformed\n");
9058 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9062 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9063 const char *lcom
, afi_t afi
, safi_t safi
,
9066 struct community_list
*list
;
9068 list
= community_list_lookup(bgp_clist
, lcom
,
9069 LARGE_COMMUNITY_LIST_MASTER
);
9071 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9076 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9080 DEFUN (show_ip_bgp_large_community_list
,
9081 show_ip_bgp_large_community_list_cmd
,
9082 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9086 BGP_INSTANCE_HELP_STR
9088 BGP_SAFI_WITH_LABEL_HELP_STR
9089 "Display routes matching the large-community-list\n"
9090 "large-community-list number\n"
9091 "large-community-list name\n"
9095 afi_t afi
= AFI_IP6
;
9096 safi_t safi
= SAFI_UNICAST
;
9099 if (argv_find(argv
, argc
, "ip", &idx
))
9101 if (argv_find(argv
, argc
, "view", &idx
)
9102 || argv_find(argv
, argc
, "vrf", &idx
))
9103 vrf
= argv
[++idx
]->arg
;
9104 if (argv_find(argv
, argc
, "ipv4", &idx
)
9105 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9106 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9107 if (argv_find(argv
, argc
, "unicast", &idx
)
9108 || argv_find(argv
, argc
, "multicast", &idx
))
9109 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9112 int uj
= use_json(argc
, argv
);
9114 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9116 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9120 argv_find(argv
, argc
, "large-community-list", &idx
);
9121 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9124 DEFUN (show_ip_bgp_large_community
,
9125 show_ip_bgp_large_community_cmd
,
9126 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9130 BGP_INSTANCE_HELP_STR
9132 BGP_SAFI_WITH_LABEL_HELP_STR
9133 "Display routes matching the large-communities\n"
9134 "List of large-community numbers\n"
9138 afi_t afi
= AFI_IP6
;
9139 safi_t safi
= SAFI_UNICAST
;
9142 if (argv_find(argv
, argc
, "ip", &idx
))
9144 if (argv_find(argv
, argc
, "view", &idx
)
9145 || argv_find(argv
, argc
, "vrf", &idx
))
9146 vrf
= argv
[++idx
]->arg
;
9147 if (argv_find(argv
, argc
, "ipv4", &idx
)
9148 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9149 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9150 if (argv_find(argv
, argc
, "unicast", &idx
)
9151 || argv_find(argv
, argc
, "multicast", &idx
))
9152 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9155 int uj
= use_json(argc
, argv
);
9157 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9159 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9163 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9164 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9166 return bgp_show(vty
, bgp
, afi
, safi
,
9167 bgp_show_type_lcommunity_all
, NULL
, uj
);
9170 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9174 /* BGP route print out function without JSON */
9177 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9178 <dampening <parameters>\
9183 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
9184 |community-list <(1-500)|WORD> [exact-match]\
9185 |A.B.C.D/M longer-prefixes\
9186 |X:X::X:X/M longer-prefixes\
9191 BGP_INSTANCE_HELP_STR
9193 BGP_SAFI_WITH_LABEL_HELP_STR
9194 "Display detailed information about dampening\n"
9195 "Display detail of configured dampening parameters\n"
9196 "Display routes matching the route-map\n"
9197 "A route-map to match on\n"
9198 "Display routes conforming to the prefix-list\n"
9199 "Prefix-list name\n"
9200 "Display routes conforming to the filter-list\n"
9201 "Regular expression access list name\n"
9202 "BGP RIB advertisement statistics\n"
9203 "Display routes matching the communities\n"
9205 "Do not send outside local AS (well-known community)\n"
9206 "Do not advertise to any peer (well-known community)\n"
9207 "Do not export to next AS (well-known community)\n"
9208 "Graceful shutdown (well-known community)\n"
9209 "Exact match of the communities\n"
9210 "Display routes matching the community-list\n"
9211 "community-list number\n"
9212 "community-list name\n"
9213 "Exact match of the communities\n"
9215 "Display route and more specific routes\n"
9217 "Display route and more specific routes\n")
9219 afi_t afi
= AFI_IP6
;
9220 safi_t safi
= SAFI_UNICAST
;
9221 int exact_match
= 0;
9222 struct bgp
*bgp
= NULL
;
9224 int idx_community_type
= 0;
9226 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9231 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9232 if (argv_find(argv
, argc
, "parameters", &idx
))
9233 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9236 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9237 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9238 safi
, bgp_show_type_prefix_list
);
9240 if (argv_find(argv
, argc
, "filter-list", &idx
))
9241 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9242 safi
, bgp_show_type_filter_list
);
9244 if (argv_find(argv
, argc
, "statistics", &idx
))
9245 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9247 if (argv_find(argv
, argc
, "route-map", &idx
))
9248 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9249 safi
, bgp_show_type_route_map
);
9251 if (argv_find(argv
, argc
, "community", &idx
)) {
9252 /* show a specific community */
9253 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
)
9254 || argv_find(argv
, argc
, "no-advertise",
9255 &idx_community_type
)
9256 || argv_find(argv
, argc
, "no-export", &idx_community_type
)
9257 || argv_find(argv
, argc
, "graceful-shutdown",
9258 &idx_community_type
)
9259 || argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9261 if (argv_find(argv
, argc
, "exact-match", &idx
))
9263 return bgp_show_community(vty
, bgp
,
9264 argv
[idx_community_type
]->arg
,
9265 exact_match
, afi
, safi
);
9269 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9270 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9271 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9273 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9274 exact_match
, afi
, safi
);
9277 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9278 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9279 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9281 bgp_show_type_prefix_longer
);
9286 /* BGP route print out function with JSON */
9287 DEFUN (show_ip_bgp_json
,
9288 show_ip_bgp_json_cmd
,
9289 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9292 |dampening <flap-statistics|dampened-paths>\
9298 BGP_INSTANCE_HELP_STR
9300 BGP_SAFI_WITH_LABEL_HELP_STR
9301 "Display only routes with non-natural netmasks\n"
9302 "Display detailed information about dampening\n"
9303 "Display flap statistics of routes\n"
9304 "Display paths suppressed due to dampening\n"
9305 "Display routes matching the communities\n"
9308 afi_t afi
= AFI_IP6
;
9309 safi_t safi
= SAFI_UNICAST
;
9310 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9311 struct bgp
*bgp
= NULL
;
9314 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9319 int uj
= use_json(argc
, argv
);
9323 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9324 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9327 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9328 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9329 return bgp_show(vty
, bgp
, afi
, safi
,
9330 bgp_show_type_dampend_paths
, NULL
, uj
);
9331 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9332 return bgp_show(vty
, bgp
, afi
, safi
,
9333 bgp_show_type_flap_statistics
, NULL
,
9337 if (argv_find(argv
, argc
, "community", &idx
)) {
9338 /* show all communities */
9339 return bgp_show(vty
, bgp
, afi
, safi
,
9340 bgp_show_type_community_all
, NULL
, uj
);
9342 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9345 DEFUN (show_ip_bgp_route
,
9346 show_ip_bgp_route_cmd
,
9347 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9348 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9352 BGP_INSTANCE_HELP_STR
9354 BGP_SAFI_WITH_LABEL_HELP_STR
9355 "Network in the BGP routing table to display\n"
9357 "Network in the BGP routing table to display\n"
9359 "Display only the bestpath\n"
9360 "Display only multipaths\n"
9363 int prefix_check
= 0;
9365 afi_t afi
= AFI_IP6
;
9366 safi_t safi
= SAFI_UNICAST
;
9367 char *prefix
= NULL
;
9368 struct bgp
*bgp
= NULL
;
9369 enum bgp_path_type path_type
;
9370 uint8_t uj
= use_json(argc
, argv
);
9374 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9381 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9385 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9386 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9387 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9389 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9390 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9393 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9394 && afi
!= AFI_IP6
) {
9396 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9399 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9402 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9406 prefix
= argv
[idx
]->arg
;
9408 /* [<bestpath|multipath>] */
9409 if (argv_find(argv
, argc
, "bestpath", &idx
))
9410 path_type
= BGP_PATH_BESTPATH
;
9411 else if (argv_find(argv
, argc
, "multipath", &idx
))
9412 path_type
= BGP_PATH_MULTIPATH
;
9414 path_type
= BGP_PATH_ALL
;
9416 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9420 DEFUN (show_ip_bgp_regexp
,
9421 show_ip_bgp_regexp_cmd
,
9422 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9426 BGP_INSTANCE_HELP_STR
9428 BGP_SAFI_WITH_LABEL_HELP_STR
9429 "Display routes matching the AS path regular expression\n"
9430 "A regular-expression to match the BGP AS paths\n")
9432 afi_t afi
= AFI_IP6
;
9433 safi_t safi
= SAFI_UNICAST
;
9434 struct bgp
*bgp
= NULL
;
9437 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9442 // get index of regex
9443 argv_find(argv
, argc
, "regexp", &idx
);
9446 char *regstr
= argv_concat(argv
, argc
, idx
);
9447 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9448 bgp_show_type_regexp
);
9449 XFREE(MTYPE_TMP
, regstr
);
9453 DEFUN (show_ip_bgp_instance_all
,
9454 show_ip_bgp_instance_all_cmd
,
9455 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9459 BGP_INSTANCE_ALL_HELP_STR
9461 BGP_SAFI_WITH_LABEL_HELP_STR
9465 safi_t safi
= SAFI_UNICAST
;
9466 struct bgp
*bgp
= NULL
;
9469 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9474 int uj
= use_json(argc
, argv
);
9478 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9482 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9483 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9488 regex
= bgp_regcomp(regstr
);
9490 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9494 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9495 bgp_regex_free(regex
);
9499 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9500 const char *prefix_list_str
, afi_t afi
,
9501 safi_t safi
, enum bgp_show_type type
)
9503 struct prefix_list
*plist
;
9505 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9506 if (plist
== NULL
) {
9507 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9512 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9515 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9516 const char *filter
, afi_t afi
, safi_t safi
,
9517 enum bgp_show_type type
)
9519 struct as_list
*as_list
;
9521 as_list
= as_list_lookup(filter
);
9522 if (as_list
== NULL
) {
9523 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9528 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9531 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9532 const char *rmap_str
, afi_t afi
, safi_t safi
,
9533 enum bgp_show_type type
)
9535 struct route_map
*rmap
;
9537 rmap
= route_map_lookup_by_name(rmap_str
);
9539 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9543 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9546 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9547 const char *comstr
, int exact
, afi_t afi
,
9550 struct community
*com
;
9553 com
= community_str2com(comstr
);
9555 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9559 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9560 (exact
? bgp_show_type_community_exact
9561 : bgp_show_type_community
),
9563 community_free(com
);
9568 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9569 const char *com
, int exact
, afi_t afi
,
9572 struct community_list
*list
;
9574 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9576 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9580 return bgp_show(vty
, bgp
, afi
, safi
,
9581 (exact
? bgp_show_type_community_list_exact
9582 : bgp_show_type_community_list
),
9586 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9587 const char *prefix
, afi_t afi
, safi_t safi
,
9588 enum bgp_show_type type
)
9595 ret
= str2prefix(prefix
, p
);
9597 vty_out(vty
, "%% Malformed Prefix\n");
9601 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9606 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9607 const char *ip_str
, uint8_t use_json
)
9613 /* Get peer sockunion. */
9614 ret
= str2sockunion(ip_str
, &su
);
9616 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9618 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9622 json_object
*json_no
= NULL
;
9623 json_no
= json_object_new_object();
9624 json_object_string_add(
9626 "malformedAddressOrName",
9628 vty_out(vty
, "%s\n",
9629 json_object_to_json_string_ext(
9631 JSON_C_TO_STRING_PRETTY
));
9632 json_object_free(json_no
);
9635 "%% Malformed address or name: %s\n",
9643 /* Peer structure lookup. */
9644 peer
= peer_lookup(bgp
, &su
);
9647 json_object
*json_no
= NULL
;
9648 json_no
= json_object_new_object();
9649 json_object_string_add(json_no
, "warning",
9650 "No such neighbor in this view/vrf");
9651 vty_out(vty
, "%s\n",
9652 json_object_to_json_string_ext(
9653 json_no
, JSON_C_TO_STRING_PRETTY
));
9654 json_object_free(json_no
);
9656 vty_out(vty
, "No such neighbor in this view/vrf\n");
9664 BGP_STATS_MAXBITLEN
= 0,
9668 BGP_STATS_UNAGGREGATEABLE
,
9669 BGP_STATS_MAX_AGGREGATEABLE
,
9670 BGP_STATS_AGGREGATES
,
9672 BGP_STATS_ASPATH_COUNT
,
9673 BGP_STATS_ASPATH_MAXHOPS
,
9674 BGP_STATS_ASPATH_TOTHOPS
,
9675 BGP_STATS_ASPATH_MAXSIZE
,
9676 BGP_STATS_ASPATH_TOTSIZE
,
9677 BGP_STATS_ASN_HIGHEST
,
9681 static const char *table_stats_strs
[] = {
9682 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9683 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9684 [BGP_STATS_RIB
] = "Total Advertisements",
9685 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9686 [BGP_STATS_MAX_AGGREGATEABLE
] =
9687 "Maximum aggregateable prefixes",
9688 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9689 [BGP_STATS_SPACE
] = "Address space advertised",
9690 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9691 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9692 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9693 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9694 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9695 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9696 [BGP_STATS_MAX
] = NULL
,
9699 struct bgp_table_stats
{
9700 struct bgp_table
*table
;
9701 unsigned long long counts
[BGP_STATS_MAX
];
9706 #define TALLY_SIGFIG 100000
9707 static unsigned long
9708 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9710 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9711 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9712 unsigned long ret
= newtot
/ count
;
9714 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9721 static int bgp_table_stats_walker(struct thread
*t
)
9723 struct bgp_node
*rn
;
9724 struct bgp_node
*top
;
9725 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9726 unsigned int space
= 0;
9728 if (!(top
= bgp_table_top(ts
->table
)))
9731 switch (top
->p
.family
) {
9733 space
= IPV4_MAX_BITLEN
;
9736 space
= IPV6_MAX_BITLEN
;
9740 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9742 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9743 struct bgp_info
*ri
;
9744 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9745 unsigned int rinum
= 0;
9753 ts
->counts
[BGP_STATS_PREFIXES
]++;
9754 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9757 ts
->counts
[BGP_STATS_AVGPLEN
]
9758 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9759 ts
->counts
[BGP_STATS_AVGPLEN
],
9763 /* check if the prefix is included by any other announcements */
9764 while (prn
&& !prn
->info
)
9765 prn
= bgp_node_parent_nolock(prn
);
9767 if (prn
== NULL
|| prn
== top
) {
9768 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9769 /* announced address space */
9772 pow(2.0, space
- rn
->p
.prefixlen
);
9773 } else if (prn
->info
)
9774 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9776 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9778 ts
->counts
[BGP_STATS_RIB
]++;
9781 && (CHECK_FLAG(ri
->attr
->flag
,
9783 BGP_ATTR_ATOMIC_AGGREGATE
))))
9784 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9787 if (ri
->attr
&& ri
->attr
->aspath
) {
9789 aspath_count_hops(ri
->attr
->aspath
);
9791 aspath_size(ri
->attr
->aspath
);
9792 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9794 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9796 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9797 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9800 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9801 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9804 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9805 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9807 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9808 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9809 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9811 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9812 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9813 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9816 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9817 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9825 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9828 struct bgp_table_stats ts
;
9831 if (!bgp
->rib
[afi
][safi
]) {
9832 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9837 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9839 /* labeled-unicast routes live in the unicast table */
9840 if (safi
== SAFI_LABELED_UNICAST
)
9841 safi
= SAFI_UNICAST
;
9843 memset(&ts
, 0, sizeof(ts
));
9844 ts
.table
= bgp
->rib
[afi
][safi
];
9845 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9847 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9848 if (!table_stats_strs
[i
])
9853 case BGP_STATS_ASPATH_AVGHOPS
:
9854 case BGP_STATS_ASPATH_AVGSIZE
:
9855 case BGP_STATS_AVGPLEN
:
9856 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9857 vty_out (vty
, "%12.2f",
9858 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9861 case BGP_STATS_ASPATH_TOTHOPS
:
9862 case BGP_STATS_ASPATH_TOTSIZE
:
9863 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9864 vty_out(vty
, "%12.2f",
9866 ? (float)ts
.counts
[i
]
9868 [BGP_STATS_ASPATH_COUNT
]
9871 case BGP_STATS_TOTPLEN
:
9872 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9873 vty_out(vty
, "%12.2f",
9875 ? (float)ts
.counts
[i
]
9877 [BGP_STATS_PREFIXES
]
9880 case BGP_STATS_SPACE
:
9881 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9882 vty_out(vty
, "%12g\n", ts
.total_space
);
9884 if (afi
== AFI_IP6
) {
9885 vty_out(vty
, "%30s: ", "/32 equivalent ");
9886 vty_out(vty
, "%12g\n",
9887 ts
.total_space
* pow(2.0, -128 + 32));
9888 vty_out(vty
, "%30s: ", "/48 equivalent ");
9889 vty_out(vty
, "%12g\n",
9890 ts
.total_space
* pow(2.0, -128 + 48));
9892 vty_out(vty
, "%30s: ", "% announced ");
9893 vty_out(vty
, "%12.2f\n",
9894 ts
.total_space
* 100. * pow(2.0, -32));
9895 vty_out(vty
, "%30s: ", "/8 equivalent ");
9896 vty_out(vty
, "%12.2f\n",
9897 ts
.total_space
* pow(2.0, -32 + 8));
9898 vty_out(vty
, "%30s: ", "/24 equivalent ");
9899 vty_out(vty
, "%12.2f\n",
9900 ts
.total_space
* pow(2.0, -32 + 24));
9904 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9905 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9922 PCOUNT_PFCNT
, /* the figure we display to users */
9926 static const char *pcount_strs
[] = {
9927 [PCOUNT_ADJ_IN
] = "Adj-in",
9928 [PCOUNT_DAMPED
] = "Damped",
9929 [PCOUNT_REMOVED
] = "Removed",
9930 [PCOUNT_HISTORY
] = "History",
9931 [PCOUNT_STALE
] = "Stale",
9932 [PCOUNT_VALID
] = "Valid",
9933 [PCOUNT_ALL
] = "All RIB",
9934 [PCOUNT_COUNTED
] = "PfxCt counted",
9935 [PCOUNT_PFCNT
] = "Useable",
9936 [PCOUNT_MAX
] = NULL
,
9939 struct peer_pcounts
{
9940 unsigned int count
[PCOUNT_MAX
];
9941 const struct peer
*peer
;
9942 const struct bgp_table
*table
;
9945 static int bgp_peer_count_walker(struct thread
*t
)
9947 struct bgp_node
*rn
;
9948 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9949 const struct peer
*peer
= pc
->peer
;
9951 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9952 struct bgp_adj_in
*ain
;
9953 struct bgp_info
*ri
;
9955 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9956 if (ain
->peer
== peer
)
9957 pc
->count
[PCOUNT_ADJ_IN
]++;
9959 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9960 char buf
[SU_ADDRSTRLEN
];
9962 if (ri
->peer
!= peer
)
9965 pc
->count
[PCOUNT_ALL
]++;
9967 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9968 pc
->count
[PCOUNT_DAMPED
]++;
9969 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9970 pc
->count
[PCOUNT_HISTORY
]++;
9971 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9972 pc
->count
[PCOUNT_REMOVED
]++;
9973 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9974 pc
->count
[PCOUNT_STALE
]++;
9975 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9976 pc
->count
[PCOUNT_VALID
]++;
9977 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9978 pc
->count
[PCOUNT_PFCNT
]++;
9980 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9981 pc
->count
[PCOUNT_COUNTED
]++;
9982 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9984 "%s [pcount] %s/%d is counted but flags 0x%x",
9986 inet_ntop(rn
->p
.family
,
9987 &rn
->p
.u
.prefix
, buf
,
9989 rn
->p
.prefixlen
, ri
->flags
);
9991 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9993 "%s [pcount] %s/%d not counted but flags 0x%x",
9995 inet_ntop(rn
->p
.family
,
9996 &rn
->p
.u
.prefix
, buf
,
9998 rn
->p
.prefixlen
, ri
->flags
);
10005 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10006 safi_t safi
, uint8_t use_json
)
10008 struct peer_pcounts pcounts
= {.peer
= peer
};
10010 json_object
*json
= NULL
;
10011 json_object
*json_loop
= NULL
;
10014 json
= json_object_new_object();
10015 json_loop
= json_object_new_object();
10018 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10019 || !peer
->bgp
->rib
[afi
][safi
]) {
10021 json_object_string_add(
10023 "No such neighbor or address family");
10024 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10025 json_object_free(json
);
10027 vty_out(vty
, "%% No such neighbor or address family\n");
10029 return CMD_WARNING
;
10032 memset(&pcounts
, 0, sizeof(pcounts
));
10033 pcounts
.peer
= peer
;
10034 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10036 /* in-place call via thread subsystem so as to record execution time
10037 * stats for the thread-walk (i.e. ensure this can't be blamed on
10038 * on just vty_read()).
10040 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10043 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10044 json_object_string_add(json
, "multiProtocol",
10045 afi_safi_print(afi
, safi
));
10046 json_object_int_add(json
, "pfxCounter",
10047 peer
->pcount
[afi
][safi
]);
10049 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10050 json_object_int_add(json_loop
, pcount_strs
[i
],
10053 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10055 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10056 json_object_string_add(json
, "pfxctDriftFor",
10058 json_object_string_add(
10059 json
, "recommended",
10060 "Please report this bug, with the above command output");
10062 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10063 json
, JSON_C_TO_STRING_PRETTY
));
10064 json_object_free(json
);
10068 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10069 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10070 peer
->hostname
, peer
->host
,
10071 afi_safi_print(afi
, safi
));
10073 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10074 afi_safi_print(afi
, safi
));
10077 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10078 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10080 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10081 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10084 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10085 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10087 "Please report this bug, with the above command output\n");
10091 return CMD_SUCCESS
;
10094 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10095 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10096 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10097 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10101 BGP_INSTANCE_HELP_STR
10104 "Detailed information on TCP and BGP neighbor connections\n"
10105 "Neighbor to display information about\n"
10106 "Neighbor to display information about\n"
10107 "Neighbor on BGP configured interface\n"
10108 "Display detailed prefix count information\n"
10111 afi_t afi
= AFI_IP6
;
10112 safi_t safi
= SAFI_UNICAST
;
10115 struct bgp
*bgp
= NULL
;
10117 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10120 return CMD_WARNING
;
10122 int uj
= use_json(argc
, argv
);
10126 argv_find(argv
, argc
, "neighbors", &idx
);
10127 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10129 return CMD_WARNING
;
10131 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10134 #ifdef KEEP_OLD_VPN_COMMANDS
10135 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10136 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10137 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10142 "Display information about all VPNv4 NLRIs\n"
10143 "Detailed information on TCP and BGP neighbor connections\n"
10144 "Neighbor to display information about\n"
10145 "Neighbor to display information about\n"
10146 "Neighbor on BGP configured interface\n"
10147 "Display detailed prefix count information\n"
10152 uint8_t uj
= use_json(argc
, argv
);
10154 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10156 return CMD_WARNING
;
10158 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10161 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10162 show_ip_bgp_vpn_all_route_prefix_cmd
,
10163 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10168 "Display information about all VPNv4 NLRIs\n"
10169 "Network in the BGP routing table to display\n"
10170 "Network in the BGP routing table to display\n"
10174 char *network
= NULL
;
10175 struct bgp
*bgp
= bgp_get_default();
10177 vty_out(vty
, "Can't find default instance\n");
10178 return CMD_WARNING
;
10181 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10182 network
= argv
[idx
]->arg
;
10183 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10184 network
= argv
[idx
]->arg
;
10186 vty_out(vty
, "Unable to figure out Network\n");
10187 return CMD_WARNING
;
10190 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10191 BGP_PATH_ALL
, use_json(argc
, argv
));
10193 #endif /* KEEP_OLD_VPN_COMMANDS */
10195 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10196 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10197 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10203 "Display information about all EVPN NLRIs\n"
10204 "Network in the BGP routing table to display\n"
10205 "Network in the BGP routing table to display\n"
10209 char *network
= NULL
;
10211 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10212 network
= argv
[idx
]->arg
;
10213 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10214 network
= argv
[idx
]->arg
;
10216 vty_out(vty
, "Unable to figure out Network\n");
10217 return CMD_WARNING
;
10219 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10220 BGP_PATH_ALL
, use_json(argc
, argv
));
10223 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10224 safi_t safi
, enum bgp_show_adj_route_type type
,
10225 const char *rmap_name
, uint8_t use_json
,
10228 struct bgp_table
*table
;
10229 struct bgp_adj_in
*ain
;
10230 struct bgp_adj_out
*adj
;
10231 unsigned long output_count
;
10232 unsigned long filtered_count
;
10233 struct bgp_node
*rn
;
10239 struct update_subgroup
*subgrp
;
10240 json_object
*json_scode
= NULL
;
10241 json_object
*json_ocode
= NULL
;
10242 json_object
*json_ar
= NULL
;
10243 struct peer_af
*paf
;
10246 json_scode
= json_object_new_object();
10247 json_ocode
= json_object_new_object();
10248 json_ar
= json_object_new_object();
10250 json_object_string_add(json_scode
, "suppressed", "s");
10251 json_object_string_add(json_scode
, "damped", "d");
10252 json_object_string_add(json_scode
, "history", "h");
10253 json_object_string_add(json_scode
, "valid", "*");
10254 json_object_string_add(json_scode
, "best", ">");
10255 json_object_string_add(json_scode
, "multipath", "=");
10256 json_object_string_add(json_scode
, "internal", "i");
10257 json_object_string_add(json_scode
, "ribFailure", "r");
10258 json_object_string_add(json_scode
, "stale", "S");
10259 json_object_string_add(json_scode
, "removed", "R");
10261 json_object_string_add(json_ocode
, "igp", "i");
10262 json_object_string_add(json_ocode
, "egp", "e");
10263 json_object_string_add(json_ocode
, "incomplete", "?");
10270 json_object_string_add(json
, "alert", "no BGP");
10271 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10272 json_object_free(json
);
10274 vty_out(vty
, "%% No bgp\n");
10278 table
= bgp
->rib
[afi
][safi
];
10280 output_count
= filtered_count
= 0;
10281 subgrp
= peer_subgroup(peer
, afi
, safi
);
10283 if (type
== bgp_show_adj_route_advertised
&& subgrp
10284 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10286 json_object_int_add(json
, "bgpTableVersion",
10288 json_object_string_add(json
, "bgpLocalRouterId",
10289 inet_ntoa(bgp
->router_id
));
10290 json_object_object_add(json
, "bgpStatusCodes",
10292 json_object_object_add(json
, "bgpOriginCodes",
10294 json_object_string_add(json
,
10295 "bgpOriginatingDefaultNetwork",
10298 vty_out(vty
, "BGP table version is %" PRIu64
10299 ", local router ID is %s, vrf id ",
10300 table
->version
, inet_ntoa(bgp
->router_id
));
10301 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10302 vty_out(vty
, "%s", VRFID_NONE_STR
);
10304 vty_out(vty
, "%u", bgp
->vrf_id
);
10305 vty_out(vty
, "\n");
10306 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10307 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10308 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10310 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
10315 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10316 if (type
== bgp_show_adj_route_received
10317 || type
== bgp_show_adj_route_filtered
) {
10318 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10319 if (ain
->peer
!= peer
|| !ain
->attr
)
10324 json_object_int_add(
10325 json
, "bgpTableVersion",
10327 json_object_string_add(
10329 "bgpLocalRouterId",
10332 json_object_object_add(
10333 json
, "bgpStatusCodes",
10335 json_object_object_add(
10336 json
, "bgpOriginCodes",
10340 "BGP table version is 0, local router ID is %s, vrf id ",
10343 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10349 vty_out(vty
, "\n");
10351 BGP_SHOW_SCODE_HEADER
);
10353 BGP_SHOW_NCODE_HEADER
);
10355 BGP_SHOW_OCODE_HEADER
);
10361 vty_out(vty
, BGP_SHOW_HEADER
);
10365 bgp_attr_dup(&attr
, ain
->attr
);
10366 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10367 afi
, safi
, rmap_name
);
10369 if (type
== bgp_show_adj_route_filtered
10370 && ret
!= RMAP_DENY
) {
10371 bgp_attr_undup(&attr
, ain
->attr
);
10375 if (type
== bgp_show_adj_route_received
10376 && ret
== RMAP_DENY
)
10379 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10380 use_json
, json_ar
);
10381 bgp_attr_undup(&attr
, ain
->attr
);
10384 } else if (type
== bgp_show_adj_route_advertised
) {
10385 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10386 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10387 if (paf
->peer
!= peer
|| !adj
->attr
)
10392 json_object_int_add(
10396 json_object_string_add(
10398 "bgpLocalRouterId",
10401 json_object_object_add(
10405 json_object_object_add(
10411 "BGP table version is %" PRIu64
10412 ", local router ID is %s, vrf id ",
10425 vty_out(vty
, "\n");
10427 BGP_SHOW_SCODE_HEADER
);
10429 BGP_SHOW_NCODE_HEADER
);
10431 BGP_SHOW_OCODE_HEADER
);
10442 bgp_attr_dup(&attr
, adj
->attr
);
10443 ret
= bgp_output_modifier(
10444 peer
, &rn
->p
, &attr
, afi
, safi
,
10447 if (ret
!= RMAP_DENY
) {
10448 route_vty_out_tmp(vty
, &rn
->p
,
10457 bgp_attr_undup(&attr
, adj
->attr
);
10463 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10464 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10465 json_object_int_add(json
, "filteredPrefixCounter",
10468 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10469 json
, JSON_C_TO_STRING_PRETTY
));
10470 json_object_free(json
);
10471 } else if (output_count
> 0) {
10472 if (filtered_count
> 0)
10474 "\nTotal number of prefixes %ld (%ld filtered)\n",
10475 output_count
, filtered_count
);
10477 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10482 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10483 safi_t safi
, enum bgp_show_adj_route_type type
,
10484 const char *rmap_name
, uint8_t use_json
)
10486 json_object
*json
= NULL
;
10489 json
= json_object_new_object();
10491 /* labeled-unicast routes live in the unicast table */
10492 if (safi
== SAFI_LABELED_UNICAST
)
10493 safi
= SAFI_UNICAST
;
10495 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10497 json_object_string_add(
10499 "No such neighbor or address family");
10500 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10501 json_object_free(json
);
10503 vty_out(vty
, "%% No such neighbor or address family\n");
10505 return CMD_WARNING
;
10508 if ((type
== bgp_show_adj_route_received
10509 || type
== bgp_show_adj_route_filtered
)
10510 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10511 PEER_FLAG_SOFT_RECONFIG
)) {
10513 json_object_string_add(
10515 "Inbound soft reconfiguration not enabled");
10516 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10517 json_object_free(json
);
10520 "%% Inbound soft reconfiguration not enabled\n");
10522 return CMD_WARNING
;
10525 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10527 return CMD_SUCCESS
;
10530 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10531 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10532 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10533 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10537 BGP_INSTANCE_HELP_STR
10539 BGP_SAFI_WITH_LABEL_HELP_STR
10540 "Detailed information on TCP and BGP neighbor connections\n"
10541 "Neighbor to display information about\n"
10542 "Neighbor to display information about\n"
10543 "Neighbor on BGP configured interface\n"
10544 "Display the routes advertised to a BGP neighbor\n"
10545 "Display the received routes from neighbor\n"
10546 "Display the filtered routes received from neighbor\n"
10547 "Route-map to modify the attributes\n"
10548 "Name of the route map\n"
10551 afi_t afi
= AFI_IP6
;
10552 safi_t safi
= SAFI_UNICAST
;
10553 char *rmap_name
= NULL
;
10554 char *peerstr
= NULL
;
10555 struct bgp
*bgp
= NULL
;
10557 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10560 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10563 return CMD_WARNING
;
10565 int uj
= use_json(argc
, argv
);
10570 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10571 argv_find(argv
, argc
, "neighbors", &idx
);
10572 peerstr
= argv
[++idx
]->arg
;
10574 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10576 return CMD_WARNING
;
10578 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10579 type
= bgp_show_adj_route_advertised
;
10580 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10581 type
= bgp_show_adj_route_received
;
10582 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10583 type
= bgp_show_adj_route_filtered
;
10585 if (argv_find(argv
, argc
, "route-map", &idx
))
10586 rmap_name
= argv
[++idx
]->arg
;
10588 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10591 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10592 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10593 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10599 "Address Family modifier\n"
10600 "Detailed information on TCP and BGP neighbor connections\n"
10601 "Neighbor to display information about\n"
10602 "Neighbor to display information about\n"
10603 "Neighbor on BGP configured interface\n"
10604 "Display information received from a BGP neighbor\n"
10605 "Display the prefixlist filter\n"
10608 afi_t afi
= AFI_IP6
;
10609 safi_t safi
= SAFI_UNICAST
;
10610 char *peerstr
= NULL
;
10613 union sockunion su
;
10619 /* show [ip] bgp */
10620 if (argv_find(argv
, argc
, "ip", &idx
))
10622 /* [<ipv4|ipv6> [unicast]] */
10623 if (argv_find(argv
, argc
, "ipv4", &idx
))
10625 if (argv_find(argv
, argc
, "ipv6", &idx
))
10627 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10628 argv_find(argv
, argc
, "neighbors", &idx
);
10629 peerstr
= argv
[++idx
]->arg
;
10631 uint8_t uj
= use_json(argc
, argv
);
10633 ret
= str2sockunion(peerstr
, &su
);
10635 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10638 vty_out(vty
, "{}\n");
10641 "%% Malformed address or name: %s\n",
10643 return CMD_WARNING
;
10646 peer
= peer_lookup(NULL
, &su
);
10649 vty_out(vty
, "{}\n");
10651 vty_out(vty
, "No peer\n");
10652 return CMD_WARNING
;
10656 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10657 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10660 vty_out(vty
, "Address Family: %s\n",
10661 afi_safi_print(afi
, safi
));
10662 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10665 vty_out(vty
, "{}\n");
10667 vty_out(vty
, "No functional output\n");
10670 return CMD_SUCCESS
;
10673 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10674 afi_t afi
, safi_t safi
,
10675 enum bgp_show_type type
, uint8_t use_json
)
10677 /* labeled-unicast routes live in the unicast table */
10678 if (safi
== SAFI_LABELED_UNICAST
)
10679 safi
= SAFI_UNICAST
;
10681 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10683 json_object
*json_no
= NULL
;
10684 json_no
= json_object_new_object();
10685 json_object_string_add(
10686 json_no
, "warning",
10687 "No such neighbor or address family");
10688 vty_out(vty
, "%s\n",
10689 json_object_to_json_string(json_no
));
10690 json_object_free(json_no
);
10692 vty_out(vty
, "%% No such neighbor or address family\n");
10693 return CMD_WARNING
;
10696 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10699 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10700 show_ip_bgp_flowspec_routes_detailed_cmd
,
10701 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10705 BGP_INSTANCE_HELP_STR
10708 "Detailed information on flowspec entries\n"
10711 afi_t afi
= AFI_IP
;
10712 safi_t safi
= SAFI_UNICAST
;
10713 struct bgp
*bgp
= NULL
;
10716 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10719 return CMD_WARNING
;
10721 return bgp_show(vty
, bgp
, afi
, safi
,
10722 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10725 DEFUN (show_ip_bgp_neighbor_routes
,
10726 show_ip_bgp_neighbor_routes_cmd
,
10727 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10728 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10732 BGP_INSTANCE_HELP_STR
10734 BGP_SAFI_WITH_LABEL_HELP_STR
10735 "Detailed information on TCP and BGP neighbor connections\n"
10736 "Neighbor to display information about\n"
10737 "Neighbor to display information about\n"
10738 "Neighbor on BGP configured interface\n"
10739 "Display flap statistics of the routes learned from neighbor\n"
10740 "Display the dampened routes received from neighbor\n"
10741 "Display routes learned from neighbor\n"
10744 char *peerstr
= NULL
;
10745 struct bgp
*bgp
= NULL
;
10746 afi_t afi
= AFI_IP6
;
10747 safi_t safi
= SAFI_UNICAST
;
10749 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10753 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10756 return CMD_WARNING
;
10758 int uj
= use_json(argc
, argv
);
10762 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10763 argv_find(argv
, argc
, "neighbors", &idx
);
10764 peerstr
= argv
[++idx
]->arg
;
10766 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10768 return CMD_WARNING
;
10770 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10771 sh_type
= bgp_show_type_flap_neighbor
;
10772 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10773 sh_type
= bgp_show_type_damp_neighbor
;
10774 else if (argv_find(argv
, argc
, "routes", &idx
))
10775 sh_type
= bgp_show_type_neighbor
;
10777 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10780 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10782 struct bgp_distance
{
10783 /* Distance value for the IP source prefix. */
10786 /* Name of the access-list to be matched. */
10790 DEFUN (show_bgp_afi_vpn_rd_route
,
10791 show_bgp_afi_vpn_rd_route_cmd
,
10792 "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]",
10796 "Address Family modifier\n"
10797 "Display information for a route distinguisher\n"
10798 "Route Distinguisher\n"
10799 "Network in the BGP routing table to display\n"
10800 "Network in the BGP routing table to display\n"
10804 struct prefix_rd prd
;
10805 afi_t afi
= AFI_MAX
;
10808 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10809 vty_out(vty
, "%% Malformed Address Family\n");
10810 return CMD_WARNING
;
10813 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10815 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10816 return CMD_WARNING
;
10819 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10820 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10823 static struct bgp_distance
*bgp_distance_new(void)
10825 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10828 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10830 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10833 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10834 const char *ip_str
, const char *access_list_str
)
10841 struct bgp_node
*rn
;
10842 struct bgp_distance
*bdistance
;
10844 afi
= bgp_node_afi(vty
);
10845 safi
= bgp_node_safi(vty
);
10847 ret
= str2prefix(ip_str
, &p
);
10849 vty_out(vty
, "Malformed prefix\n");
10850 return CMD_WARNING_CONFIG_FAILED
;
10853 distance
= atoi(distance_str
);
10855 /* Get BGP distance node. */
10856 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10858 bdistance
= rn
->info
;
10859 bgp_unlock_node(rn
);
10861 bdistance
= bgp_distance_new();
10862 rn
->info
= bdistance
;
10865 /* Set distance value. */
10866 bdistance
->distance
= distance
;
10868 /* Reset access-list configuration. */
10869 if (bdistance
->access_list
) {
10870 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10871 bdistance
->access_list
= NULL
;
10873 if (access_list_str
)
10874 bdistance
->access_list
=
10875 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10877 return CMD_SUCCESS
;
10880 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10881 const char *ip_str
, const char *access_list_str
)
10888 struct bgp_node
*rn
;
10889 struct bgp_distance
*bdistance
;
10891 afi
= bgp_node_afi(vty
);
10892 safi
= bgp_node_safi(vty
);
10894 ret
= str2prefix(ip_str
, &p
);
10896 vty_out(vty
, "Malformed prefix\n");
10897 return CMD_WARNING_CONFIG_FAILED
;
10900 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10901 (struct prefix
*)&p
);
10903 vty_out(vty
, "Can't find specified prefix\n");
10904 return CMD_WARNING_CONFIG_FAILED
;
10907 bdistance
= rn
->info
;
10908 distance
= atoi(distance_str
);
10910 if (bdistance
->distance
!= distance
) {
10911 vty_out(vty
, "Distance does not match configured\n");
10912 return CMD_WARNING_CONFIG_FAILED
;
10915 if (bdistance
->access_list
)
10916 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10917 bgp_distance_free(bdistance
);
10920 bgp_unlock_node(rn
);
10921 bgp_unlock_node(rn
);
10923 return CMD_SUCCESS
;
10926 /* Apply BGP information to distance method. */
10927 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10928 safi_t safi
, struct bgp
*bgp
)
10930 struct bgp_node
*rn
;
10933 struct bgp_distance
*bdistance
;
10934 struct access_list
*alist
;
10935 struct bgp_static
*bgp_static
;
10940 peer
= rinfo
->peer
;
10942 /* Check source address. */
10943 sockunion2hostprefix(&peer
->su
, &q
);
10944 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10946 bdistance
= rn
->info
;
10947 bgp_unlock_node(rn
);
10949 if (bdistance
->access_list
) {
10950 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10952 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10953 return bdistance
->distance
;
10955 return bdistance
->distance
;
10958 /* Backdoor check. */
10959 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10961 bgp_static
= rn
->info
;
10962 bgp_unlock_node(rn
);
10964 if (bgp_static
->backdoor
) {
10965 if (bgp
->distance_local
[afi
][safi
])
10966 return bgp
->distance_local
[afi
][safi
];
10968 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10972 if (peer
->sort
== BGP_PEER_EBGP
) {
10973 if (bgp
->distance_ebgp
[afi
][safi
])
10974 return bgp
->distance_ebgp
[afi
][safi
];
10975 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10977 if (bgp
->distance_ibgp
[afi
][safi
])
10978 return bgp
->distance_ibgp
[afi
][safi
];
10979 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10983 DEFUN (bgp_distance
,
10985 "distance bgp (1-255) (1-255) (1-255)",
10986 "Define an administrative distance\n"
10988 "Distance for routes external to the AS\n"
10989 "Distance for routes internal to the AS\n"
10990 "Distance for local routes\n")
10992 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10993 int idx_number
= 2;
10994 int idx_number_2
= 3;
10995 int idx_number_3
= 4;
10999 afi
= bgp_node_afi(vty
);
11000 safi
= bgp_node_safi(vty
);
11002 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11003 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11004 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11005 return CMD_SUCCESS
;
11008 DEFUN (no_bgp_distance
,
11009 no_bgp_distance_cmd
,
11010 "no distance bgp [(1-255) (1-255) (1-255)]",
11012 "Define an administrative distance\n"
11014 "Distance for routes external to the AS\n"
11015 "Distance for routes internal to the AS\n"
11016 "Distance for local routes\n")
11018 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11022 afi
= bgp_node_afi(vty
);
11023 safi
= bgp_node_safi(vty
);
11025 bgp
->distance_ebgp
[afi
][safi
] = 0;
11026 bgp
->distance_ibgp
[afi
][safi
] = 0;
11027 bgp
->distance_local
[afi
][safi
] = 0;
11028 return CMD_SUCCESS
;
11032 DEFUN (bgp_distance_source
,
11033 bgp_distance_source_cmd
,
11034 "distance (1-255) A.B.C.D/M",
11035 "Define an administrative distance\n"
11036 "Administrative distance\n"
11037 "IP source prefix\n")
11039 int idx_number
= 1;
11040 int idx_ipv4_prefixlen
= 2;
11041 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11042 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11043 return CMD_SUCCESS
;
11046 DEFUN (no_bgp_distance_source
,
11047 no_bgp_distance_source_cmd
,
11048 "no distance (1-255) A.B.C.D/M",
11050 "Define an administrative distance\n"
11051 "Administrative distance\n"
11052 "IP source prefix\n")
11054 int idx_number
= 2;
11055 int idx_ipv4_prefixlen
= 3;
11056 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11057 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11058 return CMD_SUCCESS
;
11061 DEFUN (bgp_distance_source_access_list
,
11062 bgp_distance_source_access_list_cmd
,
11063 "distance (1-255) A.B.C.D/M WORD",
11064 "Define an administrative distance\n"
11065 "Administrative distance\n"
11066 "IP source prefix\n"
11067 "Access list name\n")
11069 int idx_number
= 1;
11070 int idx_ipv4_prefixlen
= 2;
11072 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11073 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11074 return CMD_SUCCESS
;
11077 DEFUN (no_bgp_distance_source_access_list
,
11078 no_bgp_distance_source_access_list_cmd
,
11079 "no distance (1-255) A.B.C.D/M WORD",
11081 "Define an administrative distance\n"
11082 "Administrative distance\n"
11083 "IP source prefix\n"
11084 "Access list name\n")
11086 int idx_number
= 2;
11087 int idx_ipv4_prefixlen
= 3;
11089 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11090 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11091 return CMD_SUCCESS
;
11094 DEFUN (ipv6_bgp_distance_source
,
11095 ipv6_bgp_distance_source_cmd
,
11096 "distance (1-255) X:X::X:X/M",
11097 "Define an administrative distance\n"
11098 "Administrative distance\n"
11099 "IP source prefix\n")
11101 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11102 return CMD_SUCCESS
;
11105 DEFUN (no_ipv6_bgp_distance_source
,
11106 no_ipv6_bgp_distance_source_cmd
,
11107 "no distance (1-255) X:X::X:X/M",
11109 "Define an administrative distance\n"
11110 "Administrative distance\n"
11111 "IP source prefix\n")
11113 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11114 return CMD_SUCCESS
;
11117 DEFUN (ipv6_bgp_distance_source_access_list
,
11118 ipv6_bgp_distance_source_access_list_cmd
,
11119 "distance (1-255) X:X::X:X/M WORD",
11120 "Define an administrative distance\n"
11121 "Administrative distance\n"
11122 "IP source prefix\n"
11123 "Access list name\n")
11125 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11126 return CMD_SUCCESS
;
11129 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11130 no_ipv6_bgp_distance_source_access_list_cmd
,
11131 "no distance (1-255) X:X::X:X/M WORD",
11133 "Define an administrative distance\n"
11134 "Administrative distance\n"
11135 "IP source prefix\n"
11136 "Access list name\n")
11138 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11139 return CMD_SUCCESS
;
11142 DEFUN (bgp_damp_set
,
11144 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11145 "BGP Specific commands\n"
11146 "Enable route-flap dampening\n"
11147 "Half-life time for the penalty\n"
11148 "Value to start reusing a route\n"
11149 "Value to start suppressing a route\n"
11150 "Maximum duration to suppress a stable route\n")
11152 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11153 int idx_half_life
= 2;
11155 int idx_suppress
= 4;
11156 int idx_max_suppress
= 5;
11157 int half
= DEFAULT_HALF_LIFE
* 60;
11158 int reuse
= DEFAULT_REUSE
;
11159 int suppress
= DEFAULT_SUPPRESS
;
11160 int max
= 4 * half
;
11163 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11164 reuse
= atoi(argv
[idx_reuse
]->arg
);
11165 suppress
= atoi(argv
[idx_suppress
]->arg
);
11166 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11167 } else if (argc
== 3) {
11168 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11172 if (suppress
< reuse
) {
11174 "Suppress value cannot be less than reuse value \n");
11178 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11179 reuse
, suppress
, max
);
11182 DEFUN (bgp_damp_unset
,
11183 bgp_damp_unset_cmd
,
11184 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11186 "BGP Specific commands\n"
11187 "Enable route-flap dampening\n"
11188 "Half-life time for the penalty\n"
11189 "Value to start reusing a route\n"
11190 "Value to start suppressing a route\n"
11191 "Maximum duration to suppress a stable route\n")
11193 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11194 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11197 /* Display specified route of BGP table. */
11198 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11199 const char *ip_str
, afi_t afi
, safi_t safi
,
11200 struct prefix_rd
*prd
, int prefix_check
)
11203 struct prefix match
;
11204 struct bgp_node
*rn
;
11205 struct bgp_node
*rm
;
11206 struct bgp_info
*ri
;
11207 struct bgp_info
*ri_temp
;
11209 struct bgp_table
*table
;
11211 /* BGP structure lookup. */
11213 bgp
= bgp_lookup_by_name(view_name
);
11215 vty_out(vty
, "%% Can't find BGP instance %s\n",
11217 return CMD_WARNING
;
11220 bgp
= bgp_get_default();
11222 vty_out(vty
, "%% No BGP process is configured\n");
11223 return CMD_WARNING
;
11227 /* Check IP address argument. */
11228 ret
= str2prefix(ip_str
, &match
);
11230 vty_out(vty
, "%% address is malformed\n");
11231 return CMD_WARNING
;
11234 match
.family
= afi2family(afi
);
11236 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11237 || (safi
== SAFI_EVPN
)) {
11238 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11239 rn
= bgp_route_next(rn
)) {
11240 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11242 if ((table
= rn
->info
) == NULL
)
11244 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11248 || rm
->p
.prefixlen
== match
.prefixlen
) {
11251 if (ri
->extra
&& ri
->extra
->damp_info
) {
11252 ri_temp
= ri
->next
;
11253 bgp_damp_info_free(
11254 ri
->extra
->damp_info
,
11262 bgp_unlock_node(rm
);
11265 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11268 || rn
->p
.prefixlen
== match
.prefixlen
) {
11271 if (ri
->extra
&& ri
->extra
->damp_info
) {
11272 ri_temp
= ri
->next
;
11273 bgp_damp_info_free(
11274 ri
->extra
->damp_info
,
11282 bgp_unlock_node(rn
);
11286 return CMD_SUCCESS
;
11289 DEFUN (clear_ip_bgp_dampening
,
11290 clear_ip_bgp_dampening_cmd
,
11291 "clear ip bgp dampening",
11295 "Clear route flap dampening information\n")
11297 bgp_damp_info_clean();
11298 return CMD_SUCCESS
;
11301 DEFUN (clear_ip_bgp_dampening_prefix
,
11302 clear_ip_bgp_dampening_prefix_cmd
,
11303 "clear ip bgp dampening A.B.C.D/M",
11307 "Clear route flap dampening information\n"
11310 int idx_ipv4_prefixlen
= 4;
11311 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11312 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11315 DEFUN (clear_ip_bgp_dampening_address
,
11316 clear_ip_bgp_dampening_address_cmd
,
11317 "clear ip bgp dampening A.B.C.D",
11321 "Clear route flap dampening information\n"
11322 "Network to clear damping information\n")
11325 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11326 SAFI_UNICAST
, NULL
, 0);
11329 DEFUN (clear_ip_bgp_dampening_address_mask
,
11330 clear_ip_bgp_dampening_address_mask_cmd
,
11331 "clear ip bgp dampening A.B.C.D A.B.C.D",
11335 "Clear route flap dampening information\n"
11336 "Network to clear damping information\n"
11340 int idx_ipv4_2
= 5;
11342 char prefix_str
[BUFSIZ
];
11344 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11347 vty_out(vty
, "%% Inconsistent address and mask\n");
11348 return CMD_WARNING
;
11351 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11355 /* also used for encap safi */
11356 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11357 afi_t afi
, safi_t safi
)
11359 struct bgp_node
*prn
;
11360 struct bgp_node
*rn
;
11361 struct bgp_table
*table
;
11363 struct prefix_rd
*prd
;
11364 struct bgp_static
*bgp_static
;
11365 mpls_label_t label
;
11366 char buf
[SU_ADDRSTRLEN
];
11367 char rdbuf
[RD_ADDRSTRLEN
];
11369 /* Network configuration. */
11370 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11371 prn
= bgp_route_next(prn
)) {
11372 if ((table
= prn
->info
) == NULL
)
11375 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11376 if ((bgp_static
= rn
->info
) == NULL
)
11380 prd
= (struct prefix_rd
*)&prn
->p
;
11382 /* "network" configuration display. */
11383 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11384 label
= decode_label(&bgp_static
->label
);
11386 vty_out(vty
, " network %s/%d rd %s",
11387 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11389 p
->prefixlen
, rdbuf
);
11390 if (safi
== SAFI_MPLS_VPN
)
11391 vty_out(vty
, " label %u", label
);
11393 if (bgp_static
->rmap
.name
)
11394 vty_out(vty
, " route-map %s",
11395 bgp_static
->rmap
.name
);
11397 if (bgp_static
->backdoor
)
11398 vty_out(vty
, " backdoor");
11400 vty_out(vty
, "\n");
11405 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11406 afi_t afi
, safi_t safi
)
11408 struct bgp_node
*prn
;
11409 struct bgp_node
*rn
;
11410 struct bgp_table
*table
;
11412 struct prefix_rd
*prd
;
11413 struct bgp_static
*bgp_static
;
11414 char buf
[PREFIX_STRLEN
];
11415 char buf2
[SU_ADDRSTRLEN
];
11416 char rdbuf
[RD_ADDRSTRLEN
];
11418 /* Network configuration. */
11419 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11420 prn
= bgp_route_next(prn
)) {
11421 if ((table
= prn
->info
) == NULL
)
11424 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11425 if ((bgp_static
= rn
->info
) == NULL
)
11428 char *macrouter
= NULL
;
11431 if (bgp_static
->router_mac
)
11432 macrouter
= prefix_mac2str(
11433 bgp_static
->router_mac
, NULL
, 0);
11434 if (bgp_static
->eth_s_id
)
11435 esi
= esi2str(bgp_static
->eth_s_id
);
11437 prd
= (struct prefix_rd
*)&prn
->p
;
11439 /* "network" configuration display. */
11440 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11441 if (p
->u
.prefix_evpn
.route_type
== 5) {
11442 char local_buf
[PREFIX_STRLEN
];
11443 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11444 struct prefix_evpn
*)p
)
11448 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11449 local_buf
, PREFIX_STRLEN
);
11450 sprintf(buf
, "%s/%u", local_buf
,
11451 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11453 prefix2str(p
, buf
, sizeof(buf
));
11456 if (bgp_static
->gatewayIp
.family
== AF_INET
11457 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11458 inet_ntop(bgp_static
->gatewayIp
.family
,
11459 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11462 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11464 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11465 decode_label(&bgp_static
->label
), esi
, buf2
,
11469 XFREE(MTYPE_TMP
, macrouter
);
11471 XFREE(MTYPE_TMP
, esi
);
11476 /* Configuration of static route announcement and aggregate
11478 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11481 struct bgp_node
*rn
;
11483 struct bgp_static
*bgp_static
;
11484 struct bgp_aggregate
*bgp_aggregate
;
11485 char buf
[SU_ADDRSTRLEN
];
11487 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11488 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11492 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11493 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11497 /* Network configuration. */
11498 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11499 rn
= bgp_route_next(rn
)) {
11500 if ((bgp_static
= rn
->info
) == NULL
)
11505 /* "network" configuration display. */
11506 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11507 uint32_t destination
;
11508 struct in_addr netmask
;
11510 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11511 masklen2ip(p
->prefixlen
, &netmask
);
11512 vty_out(vty
, " network %s",
11513 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11516 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11517 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11518 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11519 || p
->u
.prefix4
.s_addr
== 0) {
11520 /* Natural mask is not display. */
11522 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11524 vty_out(vty
, " network %s/%d",
11525 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11530 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11531 vty_out(vty
, " label-index %u",
11532 bgp_static
->label_index
);
11534 if (bgp_static
->rmap
.name
)
11535 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11537 if (bgp_static
->backdoor
)
11538 vty_out(vty
, " backdoor");
11540 vty_out(vty
, "\n");
11543 /* Aggregate-address configuration. */
11544 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11545 rn
= bgp_route_next(rn
)) {
11546 if ((bgp_aggregate
= rn
->info
) == NULL
)
11551 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11552 struct in_addr netmask
;
11554 masklen2ip(p
->prefixlen
, &netmask
);
11555 vty_out(vty
, " aggregate-address %s %s",
11556 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11558 inet_ntoa(netmask
));
11560 vty_out(vty
, " aggregate-address %s/%d",
11561 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11566 if (bgp_aggregate
->as_set
)
11567 vty_out(vty
, " as-set");
11569 if (bgp_aggregate
->summary_only
)
11570 vty_out(vty
, " summary-only");
11572 vty_out(vty
, "\n");
11576 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11579 struct bgp_node
*rn
;
11580 struct bgp_distance
*bdistance
;
11582 /* Distance configuration. */
11583 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11584 && bgp
->distance_local
[afi
][safi
]
11585 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11586 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11587 || bgp
->distance_local
[afi
][safi
]
11588 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11589 vty_out(vty
, " distance bgp %d %d %d\n",
11590 bgp
->distance_ebgp
[afi
][safi
],
11591 bgp
->distance_ibgp
[afi
][safi
],
11592 bgp
->distance_local
[afi
][safi
]);
11595 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11596 rn
= bgp_route_next(rn
))
11597 if ((bdistance
= rn
->info
) != NULL
) {
11598 char buf
[PREFIX_STRLEN
];
11600 vty_out(vty
, " distance %d %s %s\n",
11601 bdistance
->distance
,
11602 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11603 bdistance
->access_list
? bdistance
->access_list
11608 /* Allocate routing table structure and install commands. */
11609 void bgp_route_init(void)
11614 /* Init BGP distance table. */
11615 FOREACH_AFI_SAFI (afi
, safi
)
11616 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11618 /* IPv4 BGP commands. */
11619 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11620 install_element(BGP_NODE
, &bgp_network_cmd
);
11621 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11623 install_element(BGP_NODE
, &aggregate_address_cmd
);
11624 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11625 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11626 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11628 /* IPv4 unicast configuration. */
11629 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11630 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11631 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11633 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11634 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11635 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11636 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11638 /* IPv4 multicast configuration. */
11639 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11640 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11641 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11642 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11643 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11644 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11645 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11647 /* IPv4 labeled-unicast configuration. */
11648 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11649 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11650 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11651 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11652 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11654 install_element(VIEW_NODE
,
11655 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11656 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11657 install_element(VIEW_NODE
,
11658 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11659 #ifdef KEEP_OLD_VPN_COMMANDS
11660 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11661 #endif /* KEEP_OLD_VPN_COMMANDS */
11662 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11663 install_element(VIEW_NODE
,
11664 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11666 /* BGP dampening clear commands */
11667 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11668 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11670 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11671 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11674 install_element(ENABLE_NODE
,
11675 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11676 #ifdef KEEP_OLD_VPN_COMMANDS
11677 install_element(ENABLE_NODE
,
11678 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11679 #endif /* KEEP_OLD_VPN_COMMANDS */
11681 /* New config IPv6 BGP commands. */
11682 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11683 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11684 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11686 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11687 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11689 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11691 install_element(BGP_NODE
, &bgp_distance_cmd
);
11692 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11693 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11694 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11695 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11696 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11697 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11698 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11699 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11700 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11701 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11702 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11703 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11704 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11705 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11706 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11707 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11708 install_element(BGP_IPV4M_NODE
,
11709 &no_bgp_distance_source_access_list_cmd
);
11710 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11711 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11712 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11713 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11714 install_element(BGP_IPV6_NODE
,
11715 &ipv6_bgp_distance_source_access_list_cmd
);
11716 install_element(BGP_IPV6_NODE
,
11717 &no_ipv6_bgp_distance_source_access_list_cmd
);
11718 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11719 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11720 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11721 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11722 install_element(BGP_IPV6M_NODE
,
11723 &ipv6_bgp_distance_source_access_list_cmd
);
11724 install_element(BGP_IPV6M_NODE
,
11725 &no_ipv6_bgp_distance_source_access_list_cmd
);
11727 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11728 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11729 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11730 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11732 /* IPv4 Multicast Mode */
11733 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11734 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11736 /* Large Communities */
11737 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11738 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11740 /* show bgp ipv4 flowspec detailed */
11741 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11745 void bgp_route_finish(void)
11750 FOREACH_AFI_SAFI (afi
, safi
) {
11751 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11752 bgp_distance_table
[afi
][safi
] = NULL
;