1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "sockunion.h"
37 #include "workqueue.h"
41 #include "lib_errors.h"
43 #include "bgpd/bgpd.h"
44 #include "bgpd/bgp_table.h"
45 #include "bgpd/bgp_route.h"
46 #include "bgpd/bgp_attr.h"
47 #include "bgpd/bgp_debug.h"
48 #include "bgpd/bgp_errors.h"
49 #include "bgpd/bgp_aspath.h"
50 #include "bgpd/bgp_regex.h"
51 #include "bgpd/bgp_community.h"
52 #include "bgpd/bgp_ecommunity.h"
53 #include "bgpd/bgp_lcommunity.h"
54 #include "bgpd/bgp_clist.h"
55 #include "bgpd/bgp_packet.h"
56 #include "bgpd/bgp_filter.h"
57 #include "bgpd/bgp_fsm.h"
58 #include "bgpd/bgp_mplsvpn.h"
59 #include "bgpd/bgp_nexthop.h"
60 #include "bgpd/bgp_damp.h"
61 #include "bgpd/bgp_advertise.h"
62 #include "bgpd/bgp_zebra.h"
63 #include "bgpd/bgp_vty.h"
64 #include "bgpd/bgp_mpath.h"
65 #include "bgpd/bgp_nht.h"
66 #include "bgpd/bgp_updgrp.h"
67 #include "bgpd/bgp_label.h"
70 #include "bgpd/rfapi/rfapi_backend.h"
71 #include "bgpd/rfapi/vnc_import_bgp.h"
72 #include "bgpd/rfapi/vnc_export_bgp.h"
74 #include "bgpd/bgp_encap_types.h"
75 #include "bgpd/bgp_encap_tlv.h"
76 #include "bgpd/bgp_evpn.h"
77 #include "bgpd/bgp_evpn_vty.h"
78 #include "bgpd/bgp_flowspec.h"
79 #include "bgpd/bgp_flowspec_util.h"
80 #include "bgpd/bgp_pbr.h"
82 #ifndef VTYSH_EXTRACT_PL
83 #include "bgpd/bgp_route_clippy.c"
86 /* Extern from bgp_dump.c */
87 extern const char *bgp_origin_str
[];
88 extern const char *bgp_origin_long_str
[];
91 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
92 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
93 static const struct message bgp_pmsi_tnltype_str
[] = {
94 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
95 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
96 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
97 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
98 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
99 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
100 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
101 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
105 #define VRFID_NONE_STR "-"
107 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
108 safi_t safi
, struct prefix
*p
,
109 struct prefix_rd
*prd
)
112 struct bgp_node
*prn
= NULL
;
118 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
119 || (safi
== SAFI_EVPN
)) {
120 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
122 if (prn
->info
== NULL
)
123 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
125 bgp_unlock_node(prn
);
129 rn
= bgp_node_get(table
, p
);
131 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
132 || (safi
== SAFI_EVPN
))
138 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
139 safi_t safi
, struct prefix
*p
,
140 struct prefix_rd
*prd
)
143 struct bgp_node
*prn
= NULL
;
148 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
149 || (safi
== SAFI_EVPN
)) {
150 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
154 if (prn
->info
== NULL
) {
155 bgp_unlock_node(prn
);
162 rn
= bgp_node_lookup(table
, p
);
167 /* Allocate bgp_info_extra */
168 static struct bgp_path_info_extra
*bgp_info_extra_new(void)
170 struct bgp_path_info_extra
*new;
171 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
172 sizeof(struct bgp_path_info_extra
));
173 new->label
[0] = MPLS_INVALID_LABEL
;
178 static void bgp_info_extra_free(struct bgp_path_info_extra
**extra
)
180 struct bgp_path_info_extra
*e
;
182 if (!extra
|| !*extra
)
187 bgp_damp_info_free(e
->damp_info
, 0);
191 struct bgp_path_info
*bi
= (struct bgp_path_info
*)e
->parent
;
194 /* FIXME: since multiple e may have the same e->parent
195 * and e->parent->net is holding a refcount for each
196 * of them, we need to do some fudging here.
198 * WARNING: if bi->net->lock drops to 0, bi may be
199 * freed as well (because bi->net was holding the
200 * last reference to bi) => write after free!
204 bi
= bgp_info_lock(bi
);
205 refcount
= bi
->net
->lock
- 1;
206 bgp_unlock_node((struct bgp_node
*)bi
->net
);
211 bgp_info_unlock(e
->parent
);
216 bgp_unlock(e
->bgp_orig
);
218 if ((*extra
)->bgp_fs_pbr
)
219 list_delete(&((*extra
)->bgp_fs_pbr
));
220 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
225 /* Get bgp_info extra information for the given bgp_info, lazy allocated
228 struct bgp_path_info_extra
*bgp_info_extra_get(struct bgp_path_info
*ri
)
231 ri
->extra
= bgp_info_extra_new();
235 /* Allocate new bgp info structure. */
236 struct bgp_path_info
*bgp_info_new(void)
238 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
241 /* Free bgp route information. */
242 static void bgp_info_free(struct bgp_path_info
*binfo
)
245 bgp_attr_unintern(&binfo
->attr
);
247 bgp_unlink_nexthop(binfo
);
248 bgp_info_extra_free(&binfo
->extra
);
249 bgp_info_mpath_free(&binfo
->mpath
);
251 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
253 XFREE(MTYPE_BGP_ROUTE
, binfo
);
256 struct bgp_path_info
*bgp_info_lock(struct bgp_path_info
*binfo
)
262 struct bgp_path_info
*bgp_info_unlock(struct bgp_path_info
*binfo
)
264 assert(binfo
&& binfo
->lock
> 0);
267 if (binfo
->lock
== 0) {
269 zlog_debug ("%s: unlocked and freeing", __func__
);
270 zlog_backtrace (LOG_DEBUG
);
272 bgp_info_free(binfo
);
277 if (binfo
->lock
== 1)
279 zlog_debug ("%s: unlocked to 1", __func__
);
280 zlog_backtrace (LOG_DEBUG
);
287 void bgp_info_add(struct bgp_node
*rn
, struct bgp_path_info
*ri
)
289 struct bgp_path_info
*top
;
301 peer_lock(ri
->peer
); /* bgp_info peer reference */
304 /* Do the actual removal of info from RIB, for use by bgp_process
305 completion callback *only* */
306 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*ri
)
309 ri
->next
->prev
= ri
->prev
;
311 ri
->prev
->next
= ri
->next
;
315 bgp_info_mpath_dequeue(ri
);
320 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*ri
)
322 bgp_info_set_flag(rn
, ri
, BGP_PATH_REMOVED
);
323 /* set of previous already took care of pcount */
324 UNSET_FLAG(ri
->flags
, BGP_PATH_VALID
);
327 /* undo the effects of a previous call to bgp_info_delete; typically
328 called when a route is deleted and then quickly re-added before the
329 deletion has been processed */
330 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*ri
)
332 bgp_info_unset_flag(rn
, ri
, BGP_PATH_REMOVED
);
333 /* unset of previous already took care of pcount */
334 SET_FLAG(ri
->flags
, BGP_PATH_VALID
);
337 /* Adjust pcount as required */
338 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*ri
)
340 struct bgp_table
*table
;
342 assert(rn
&& bgp_node_table(rn
));
343 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
345 table
= bgp_node_table(rn
);
347 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
350 if (!BGP_PATH_COUNTABLE(ri
)
351 && CHECK_FLAG(ri
->flags
, BGP_PATH_COUNTED
)) {
353 UNSET_FLAG(ri
->flags
, BGP_PATH_COUNTED
);
355 /* slight hack, but more robust against errors. */
356 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
357 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
359 flog_err(EC_LIB_DEVELOPMENT
,
360 "Asked to decrement 0 prefix count for peer");
361 } else if (BGP_PATH_COUNTABLE(ri
)
362 && !CHECK_FLAG(ri
->flags
, BGP_PATH_COUNTED
)) {
363 SET_FLAG(ri
->flags
, BGP_PATH_COUNTED
);
364 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
368 static int bgp_label_index_differs(struct bgp_path_info
*ri1
,
369 struct bgp_path_info
*ri2
)
371 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
374 /* Set/unset bgp_info flags, adjusting any other state as needed.
375 * This is here primarily to keep prefix-count in check.
377 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*ri
,
380 SET_FLAG(ri
->flags
, flag
);
382 /* early bath if we know it's not a flag that changes countability state
384 if (!CHECK_FLAG(flag
,
385 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
388 bgp_pcount_adjust(rn
, ri
);
391 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*ri
,
394 UNSET_FLAG(ri
->flags
, flag
);
396 /* early bath if we know it's not a flag that changes countability state
398 if (!CHECK_FLAG(flag
,
399 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
402 bgp_pcount_adjust(rn
, ri
);
405 /* Get MED value. If MED value is missing and "bgp bestpath
406 missing-as-worst" is specified, treat it as the worst value. */
407 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
409 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
412 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
419 void bgp_info_path_with_addpath_rx_str(struct bgp_path_info
*ri
, char *buf
)
421 if (ri
->addpath_rx_id
)
422 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
425 sprintf(buf
, "path %s", ri
->peer
->host
);
428 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
430 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
431 struct bgp_path_info
*exist
, int *paths_eq
,
432 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
433 char *pfx_buf
, afi_t afi
, safi_t safi
)
435 struct attr
*newattr
, *existattr
;
436 bgp_peer_sort_t new_sort
;
437 bgp_peer_sort_t exist_sort
;
443 uint32_t exist_weight
;
444 uint32_t newm
, existm
;
445 struct in_addr new_id
;
446 struct in_addr exist_id
;
449 int internal_as_route
;
452 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
453 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
455 uint32_t exist_mm_seq
;
462 zlog_debug("%s: new is NULL", pfx_buf
);
467 bgp_info_path_with_addpath_rx_str(new, new_buf
);
471 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
477 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
478 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
479 pfx_buf
, new_buf
, new->flags
, exist_buf
,
484 existattr
= exist
->attr
;
486 /* For EVPN routes, we cannot just go by local vs remote, we have to
487 * look at the MAC mobility sequence number, if present.
489 if (safi
== SAFI_EVPN
) {
490 /* This is an error condition described in RFC 7432 Section
492 * states that in this scenario "the PE MUST alert the operator"
494 * does not state what other action to take. In order to provide
496 * consistency in this scenario we are going to prefer the path
500 if (newattr
->sticky
!= existattr
->sticky
) {
502 prefix2str(&new->net
->p
, pfx_buf
,
504 * PREFIX2STR_BUFFER
);
505 bgp_info_path_with_addpath_rx_str(new, new_buf
);
506 bgp_info_path_with_addpath_rx_str(exist
,
510 if (newattr
->sticky
&& !existattr
->sticky
) {
513 "%s: %s wins over %s due to sticky MAC flag",
514 pfx_buf
, new_buf
, exist_buf
);
518 if (!newattr
->sticky
&& existattr
->sticky
) {
521 "%s: %s loses to %s due to sticky MAC flag",
522 pfx_buf
, new_buf
, exist_buf
);
527 new_mm_seq
= mac_mobility_seqnum(newattr
);
528 exist_mm_seq
= mac_mobility_seqnum(existattr
);
530 if (new_mm_seq
> exist_mm_seq
) {
533 "%s: %s wins over %s due to MM seq %u > %u",
534 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
539 if (new_mm_seq
< exist_mm_seq
) {
542 "%s: %s loses to %s due to MM seq %u < %u",
543 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
549 /* 1. Weight check. */
550 new_weight
= newattr
->weight
;
551 exist_weight
= existattr
->weight
;
553 if (new_weight
> exist_weight
) {
555 zlog_debug("%s: %s wins over %s due to weight %d > %d",
556 pfx_buf
, new_buf
, exist_buf
, new_weight
,
561 if (new_weight
< exist_weight
) {
563 zlog_debug("%s: %s loses to %s due to weight %d < %d",
564 pfx_buf
, new_buf
, exist_buf
, new_weight
,
569 /* 2. Local preference check. */
570 new_pref
= exist_pref
= bgp
->default_local_pref
;
572 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
573 new_pref
= newattr
->local_pref
;
574 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
575 exist_pref
= existattr
->local_pref
;
577 if (new_pref
> exist_pref
) {
580 "%s: %s wins over %s due to localpref %d > %d",
581 pfx_buf
, new_buf
, exist_buf
, new_pref
,
586 if (new_pref
< exist_pref
) {
589 "%s: %s loses to %s due to localpref %d < %d",
590 pfx_buf
, new_buf
, exist_buf
, new_pref
,
595 /* 3. Local route check. We prefer:
597 * - BGP_ROUTE_AGGREGATE
598 * - BGP_ROUTE_REDISTRIBUTE
600 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
601 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
604 "%s: %s wins over %s due to preferred BGP_ROUTE type",
605 pfx_buf
, new_buf
, exist_buf
);
609 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
610 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
613 "%s: %s loses to %s due to preferred BGP_ROUTE type",
614 pfx_buf
, new_buf
, exist_buf
);
618 /* 4. AS path length check. */
619 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
620 int exist_hops
= aspath_count_hops(existattr
->aspath
);
621 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
623 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
626 aspath_hops
= aspath_count_hops(newattr
->aspath
);
627 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
629 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
632 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
633 pfx_buf
, new_buf
, exist_buf
,
635 (exist_hops
+ exist_confeds
));
639 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
642 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
643 pfx_buf
, new_buf
, exist_buf
,
645 (exist_hops
+ exist_confeds
));
649 int newhops
= aspath_count_hops(newattr
->aspath
);
651 if (newhops
< exist_hops
) {
654 "%s: %s wins over %s due to aspath hopcount %d < %d",
655 pfx_buf
, new_buf
, exist_buf
,
656 newhops
, exist_hops
);
660 if (newhops
> exist_hops
) {
663 "%s: %s loses to %s due to aspath hopcount %d > %d",
664 pfx_buf
, new_buf
, exist_buf
,
665 newhops
, exist_hops
);
671 /* 5. Origin check. */
672 if (newattr
->origin
< existattr
->origin
) {
674 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
675 pfx_buf
, new_buf
, exist_buf
,
676 bgp_origin_long_str
[newattr
->origin
],
677 bgp_origin_long_str
[existattr
->origin
]);
681 if (newattr
->origin
> existattr
->origin
) {
683 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
684 pfx_buf
, new_buf
, exist_buf
,
685 bgp_origin_long_str
[newattr
->origin
],
686 bgp_origin_long_str
[existattr
->origin
]);
691 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
692 && aspath_count_hops(existattr
->aspath
) == 0);
693 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
694 && aspath_count_confeds(existattr
->aspath
) > 0
695 && aspath_count_hops(newattr
->aspath
) == 0
696 && aspath_count_hops(existattr
->aspath
) == 0);
698 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
699 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
700 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
701 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
702 || internal_as_route
) {
703 new_med
= bgp_med_value(new->attr
, bgp
);
704 exist_med
= bgp_med_value(exist
->attr
, bgp
);
706 if (new_med
< exist_med
) {
709 "%s: %s wins over %s due to MED %d < %d",
710 pfx_buf
, new_buf
, exist_buf
, new_med
,
715 if (new_med
> exist_med
) {
718 "%s: %s loses to %s due to MED %d > %d",
719 pfx_buf
, new_buf
, exist_buf
, new_med
,
725 /* 7. Peer type check. */
726 new_sort
= new->peer
->sort
;
727 exist_sort
= exist
->peer
->sort
;
729 if (new_sort
== BGP_PEER_EBGP
730 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
733 "%s: %s wins over %s due to eBGP peer > iBGP peer",
734 pfx_buf
, new_buf
, exist_buf
);
738 if (exist_sort
== BGP_PEER_EBGP
739 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
742 "%s: %s loses to %s due to iBGP peer < eBGP peer",
743 pfx_buf
, new_buf
, exist_buf
);
747 /* 8. IGP metric check. */
751 newm
= new->extra
->igpmetric
;
753 existm
= exist
->extra
->igpmetric
;
758 "%s: %s wins over %s due to IGP metric %d < %d",
759 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
766 "%s: %s loses to %s due to IGP metric %d > %d",
767 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
771 /* 9. Same IGP metric. Compare the cluster list length as
772 representative of IGP hops metric. Rewrite the metric value
773 pair (newm, existm) with the cluster list length. Prefer the
774 path with smaller cluster list length. */
775 if (newm
== existm
) {
776 if (peer_sort(new->peer
) == BGP_PEER_IBGP
777 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
778 && (mpath_cfg
== NULL
780 mpath_cfg
->ibgp_flags
,
781 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
782 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
783 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
788 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
789 pfx_buf
, new_buf
, exist_buf
,
797 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
798 pfx_buf
, new_buf
, exist_buf
,
805 /* 10. confed-external vs. confed-internal */
806 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
807 if (new_sort
== BGP_PEER_CONFED
808 && exist_sort
== BGP_PEER_IBGP
) {
811 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
812 pfx_buf
, new_buf
, exist_buf
);
816 if (exist_sort
== BGP_PEER_CONFED
817 && new_sort
== BGP_PEER_IBGP
) {
820 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
821 pfx_buf
, new_buf
, exist_buf
);
826 /* 11. Maximum path check. */
827 if (newm
== existm
) {
828 /* If one path has a label but the other does not, do not treat
829 * them as equals for multipath
831 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
833 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
836 "%s: %s and %s cannot be multipath, one has a label while the other does not",
837 pfx_buf
, new_buf
, exist_buf
);
838 } else if (bgp_flag_check(bgp
,
839 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
842 * For the two paths, all comparison steps till IGP
844 * have succeeded - including AS_PATH hop count. Since
846 * bestpath as-path multipath-relax' knob is on, we
848 * an exact match of AS_PATH. Thus, mark the paths are
850 * That will trigger both these paths to get into the
858 "%s: %s and %s are equal via multipath-relax",
859 pfx_buf
, new_buf
, exist_buf
);
860 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
861 if (aspath_cmp(new->attr
->aspath
,
862 exist
->attr
->aspath
)) {
867 "%s: %s and %s are equal via matching aspaths",
868 pfx_buf
, new_buf
, exist_buf
);
870 } else if (new->peer
->as
== exist
->peer
->as
) {
875 "%s: %s and %s are equal via same remote-as",
876 pfx_buf
, new_buf
, exist_buf
);
880 * TODO: If unequal cost ibgp multipath is enabled we can
881 * mark the paths as equal here instead of returning
886 "%s: %s wins over %s after IGP metric comparison",
887 pfx_buf
, new_buf
, exist_buf
);
890 "%s: %s loses to %s after IGP metric comparison",
891 pfx_buf
, new_buf
, exist_buf
);
896 /* 12. If both paths are external, prefer the path that was received
897 first (the oldest one). This step minimizes route-flap, since a
898 newer path won't displace an older one, even if it was the
899 preferred route based on the additional decision criteria below. */
900 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
901 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
902 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
905 "%s: %s wins over %s due to oldest external",
906 pfx_buf
, new_buf
, exist_buf
);
910 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
913 "%s: %s loses to %s due to oldest external",
914 pfx_buf
, new_buf
, exist_buf
);
919 /* 13. Router-ID comparision. */
920 /* If one of the paths is "stale", the corresponding peer router-id will
921 * be 0 and would always win over the other path. If originator id is
922 * used for the comparision, it will decide which path is better.
924 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
925 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
927 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
928 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
929 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
931 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
933 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
936 "%s: %s wins over %s due to Router-ID comparison",
937 pfx_buf
, new_buf
, exist_buf
);
941 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
944 "%s: %s loses to %s due to Router-ID comparison",
945 pfx_buf
, new_buf
, exist_buf
);
949 /* 14. Cluster length comparision. */
950 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
951 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
953 if (new_cluster
< exist_cluster
) {
956 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
957 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
962 if (new_cluster
> exist_cluster
) {
965 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
966 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
971 /* 15. Neighbor address comparision. */
972 /* Do this only if neither path is "stale" as stale paths do not have
973 * valid peer information (as the connection may or may not be up).
975 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
978 "%s: %s wins over %s due to latter path being STALE",
979 pfx_buf
, new_buf
, exist_buf
);
983 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
986 "%s: %s loses to %s due to former path being STALE",
987 pfx_buf
, new_buf
, exist_buf
);
991 /* locally configured routes to advertise do not have su_remote */
992 if (new->peer
->su_remote
== NULL
)
994 if (exist
->peer
->su_remote
== NULL
)
997 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1002 "%s: %s loses to %s due to Neighor IP comparison",
1003 pfx_buf
, new_buf
, exist_buf
);
1010 "%s: %s wins over %s due to Neighor IP comparison",
1011 pfx_buf
, new_buf
, exist_buf
);
1016 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1017 pfx_buf
, new_buf
, exist_buf
);
1022 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1023 * is preferred, or 0 if they are the same (usually will only occur if
1024 * multipath is enabled
1025 * This version is compatible with */
1026 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1027 struct bgp_path_info
*exist
, char *pfx_buf
,
1028 afi_t afi
, safi_t safi
)
1032 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
1046 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1047 struct attr
*attr
, afi_t afi
,
1050 struct bgp_filter
*filter
;
1052 filter
= &peer
->filter
[afi
][safi
];
1054 #define FILTER_EXIST_WARN(F, f, filter) \
1055 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1056 zlog_debug("%s: Could not find configured input %s-list %s!", \
1057 peer->host, #f, F##_IN_NAME(filter));
1059 if (DISTRIBUTE_IN_NAME(filter
)) {
1060 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1062 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1066 if (PREFIX_LIST_IN_NAME(filter
)) {
1067 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1069 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1073 if (FILTER_LIST_IN_NAME(filter
)) {
1074 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1076 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1081 return FILTER_PERMIT
;
1082 #undef FILTER_EXIST_WARN
1085 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1086 struct attr
*attr
, afi_t afi
,
1089 struct bgp_filter
*filter
;
1091 filter
= &peer
->filter
[afi
][safi
];
1093 #define FILTER_EXIST_WARN(F, f, filter) \
1094 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1095 zlog_debug("%s: Could not find configured output %s-list %s!", \
1096 peer->host, #f, F##_OUT_NAME(filter));
1098 if (DISTRIBUTE_OUT_NAME(filter
)) {
1099 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1101 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1105 if (PREFIX_LIST_OUT_NAME(filter
)) {
1106 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1108 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1113 if (FILTER_LIST_OUT_NAME(filter
)) {
1114 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1116 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1121 return FILTER_PERMIT
;
1122 #undef FILTER_EXIST_WARN
1125 /* If community attribute includes no_export then return 1. */
1126 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1128 if (attr
->community
) {
1129 /* NO_ADVERTISE check. */
1130 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1133 /* NO_EXPORT check. */
1134 if (peer
->sort
== BGP_PEER_EBGP
1135 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1138 /* NO_EXPORT_SUBCONFED check. */
1139 if (peer
->sort
== BGP_PEER_EBGP
1140 || peer
->sort
== BGP_PEER_CONFED
)
1141 if (community_include(attr
->community
,
1142 COMMUNITY_NO_EXPORT_SUBCONFED
))
1148 /* Route reflection loop check. */
1149 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1151 struct in_addr cluster_id
;
1153 if (attr
->cluster
) {
1154 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1155 cluster_id
= peer
->bgp
->cluster_id
;
1157 cluster_id
= peer
->bgp
->router_id
;
1159 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1165 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1166 struct attr
*attr
, afi_t afi
, safi_t safi
,
1167 const char *rmap_name
)
1169 struct bgp_filter
*filter
;
1170 struct bgp_path_info info
;
1171 route_map_result_t ret
;
1172 struct route_map
*rmap
= NULL
;
1174 filter
= &peer
->filter
[afi
][safi
];
1176 /* Apply default weight value. */
1177 if (peer
->weight
[afi
][safi
])
1178 attr
->weight
= peer
->weight
[afi
][safi
];
1181 rmap
= route_map_lookup_by_name(rmap_name
);
1186 if (ROUTE_MAP_IN_NAME(filter
)) {
1187 rmap
= ROUTE_MAP_IN(filter
);
1194 /* Route map apply. */
1196 memset(&info
, 0, sizeof(struct bgp_path_info
));
1197 /* Duplicate current value to new strucutre for modification. */
1201 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1203 /* Apply BGP route map to the attribute. */
1204 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1206 peer
->rmap_type
= 0;
1208 if (ret
== RMAP_DENYMATCH
)
1214 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1215 struct attr
*attr
, afi_t afi
, safi_t safi
,
1216 const char *rmap_name
)
1218 struct bgp_path_info info
;
1219 route_map_result_t ret
;
1220 struct route_map
*rmap
= NULL
;
1224 * So if we get to this point and have no rmap_name
1225 * we want to just show the output as it currently
1231 /* Apply default weight value. */
1232 if (peer
->weight
[afi
][safi
])
1233 attr
->weight
= peer
->weight
[afi
][safi
];
1235 rmap
= route_map_lookup_by_name(rmap_name
);
1238 * If we have a route map name and we do not find
1239 * the routemap that means we have an implicit
1245 memset(&info
, 0, sizeof(struct bgp_path_info
));
1246 /* Route map apply. */
1247 /* Duplicate current value to new strucutre for modification. */
1251 rmap_type
= peer
->rmap_type
;
1252 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1254 /* Apply BGP route map to the attribute. */
1255 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1257 peer
->rmap_type
= rmap_type
;
1259 if (ret
== RMAP_DENYMATCH
)
1261 * caller has multiple error paths with bgp_attr_flush()
1268 /* If this is an EBGP peer with remove-private-AS */
1269 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1270 struct peer
*peer
, struct attr
*attr
)
1272 if (peer
->sort
== BGP_PEER_EBGP
1273 && (peer_af_flag_check(peer
, afi
, safi
,
1274 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1275 || peer_af_flag_check(peer
, afi
, safi
,
1276 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1277 || peer_af_flag_check(peer
, afi
, safi
,
1278 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1279 || peer_af_flag_check(peer
, afi
, safi
,
1280 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1281 // Take action on the entire aspath
1282 if (peer_af_flag_check(peer
, afi
, safi
,
1283 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1284 || peer_af_flag_check(peer
, afi
, safi
,
1285 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1286 if (peer_af_flag_check(
1288 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1289 attr
->aspath
= aspath_replace_private_asns(
1290 attr
->aspath
, bgp
->as
);
1292 // The entire aspath consists of private ASNs so create
1294 else if (aspath_private_as_check(attr
->aspath
))
1295 attr
->aspath
= aspath_empty_get();
1297 // There are some public and some private ASNs, remove
1300 attr
->aspath
= aspath_remove_private_asns(
1304 // 'all' was not specified so the entire aspath must be private
1306 // for us to do anything
1307 else if (aspath_private_as_check(attr
->aspath
)) {
1308 if (peer_af_flag_check(
1310 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1311 attr
->aspath
= aspath_replace_private_asns(
1312 attr
->aspath
, bgp
->as
);
1314 attr
->aspath
= aspath_empty_get();
1319 /* If this is an EBGP peer with as-override */
1320 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1321 struct peer
*peer
, struct attr
*attr
)
1323 if (peer
->sort
== BGP_PEER_EBGP
1324 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1325 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1326 attr
->aspath
= aspath_replace_specific_asn(
1327 attr
->aspath
, peer
->as
, bgp
->as
);
1331 void bgp_attr_add_gshut_community(struct attr
*attr
)
1333 struct community
*old
;
1334 struct community
*new;
1335 struct community
*merge
;
1336 struct community
*gshut
;
1338 old
= attr
->community
;
1339 gshut
= community_str2com("graceful-shutdown");
1344 merge
= community_merge(community_dup(old
), gshut
);
1346 if (old
->refcnt
== 0)
1347 community_free(old
);
1349 new = community_uniq_sort(merge
);
1350 community_free(merge
);
1352 new = community_dup(gshut
);
1355 community_free(gshut
);
1356 attr
->community
= new;
1357 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1359 /* When we add the graceful-shutdown community we must also
1360 * lower the local-preference */
1361 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1362 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1366 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1368 if (family
== AF_INET
) {
1369 attr
->nexthop
.s_addr
= 0;
1370 attr
->mp_nexthop_global_in
.s_addr
= 0;
1372 if (family
== AF_INET6
)
1373 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1374 if (family
== AF_EVPN
)
1375 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1378 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*ri
,
1379 struct update_subgroup
*subgrp
, struct prefix
*p
,
1382 struct bgp_filter
*filter
;
1385 struct peer
*onlypeer
;
1387 struct attr
*riattr
;
1388 char buf
[PREFIX_STRLEN
];
1394 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1396 if (DISABLE_BGP_ANNOUNCE
)
1399 afi
= SUBGRP_AFI(subgrp
);
1400 safi
= SUBGRP_SAFI(subgrp
);
1401 peer
= SUBGRP_PEER(subgrp
);
1403 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1404 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1407 filter
= &peer
->filter
[afi
][safi
];
1408 bgp
= SUBGRP_INST(subgrp
);
1409 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1412 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1413 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1414 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1417 * direct and direct_ext type routes originate internally even
1418 * though they can have peer pointers that reference other
1421 prefix2str(p
, buf
, PREFIX_STRLEN
);
1422 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1428 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1429 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1430 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1431 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1433 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1438 /* With addpath we may be asked to TX all kinds of paths so make sure
1440 if (!CHECK_FLAG(ri
->flags
, BGP_PATH_VALID
)
1441 || CHECK_FLAG(ri
->flags
, BGP_PATH_HISTORY
)
1442 || CHECK_FLAG(ri
->flags
, BGP_PATH_REMOVED
)) {
1446 /* If this is not the bestpath then check to see if there is an enabled
1448 * feature that requires us to advertise it */
1449 if (!CHECK_FLAG(ri
->flags
, BGP_PATH_SELECTED
)) {
1450 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1455 /* Aggregate-address suppress check. */
1456 if (ri
->extra
&& ri
->extra
->suppress
)
1457 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1462 * If we are doing VRF 2 VRF leaking via the import
1463 * statement, we want to prevent the route going
1464 * off box as that the RT and RD created are localy
1465 * significant and globaly useless.
1467 if (safi
== SAFI_MPLS_VPN
&& ri
->extra
&& ri
->extra
->num_labels
1468 && ri
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1471 /* If it's labeled safi, make sure the route has a valid label. */
1472 if (safi
== SAFI_LABELED_UNICAST
) {
1473 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1474 if (!bgp_is_valid_label(&label
)) {
1475 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1476 zlog_debug("u%" PRIu64
":s%" PRIu64
1477 " %s/%d is filtered - no label (%p)",
1478 subgrp
->update_group
->id
, subgrp
->id
,
1479 inet_ntop(p
->family
, &p
->u
.prefix
,
1480 buf
, SU_ADDRSTRLEN
),
1481 p
->prefixlen
, &label
);
1486 /* Do not send back route to sender. */
1487 if (onlypeer
&& from
== onlypeer
) {
1491 /* Do not send the default route in the BGP table if the neighbor is
1492 * configured for default-originate */
1493 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1494 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1495 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1497 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1501 /* Transparency check. */
1502 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1503 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1508 /* If community is not disabled check the no-export and local. */
1509 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1510 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1512 "subgrpannouncecheck: community filter check fail");
1516 /* If the attribute has originator-id and it is same as remote
1518 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1519 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1520 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1522 "%s [Update:SEND] %s originator-id is same as "
1525 prefix2str(p
, buf
, sizeof(buf
)));
1529 /* ORF prefix-list filter check */
1530 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1531 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1532 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1533 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1534 if (peer
->orf_plist
[afi
][safi
]) {
1535 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1537 if (bgp_debug_update(NULL
, p
,
1538 subgrp
->update_group
, 0))
1540 "%s [Update:SEND] %s is filtered via ORF",
1548 /* Output filter check. */
1549 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1550 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1551 zlog_debug("%s [Update:SEND] %s is filtered",
1552 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1556 #ifdef BGP_SEND_ASPATH_CHECK
1557 /* AS path loop check. */
1558 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1559 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1561 "%s [Update:SEND] suppress announcement to peer AS %u "
1562 "that is part of AS path.",
1563 onlypeer
->host
, onlypeer
->as
);
1566 #endif /* BGP_SEND_ASPATH_CHECK */
1568 /* If we're a CONFED we need to loop check the CONFED ID too */
1569 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1570 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1571 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1573 "%s [Update:SEND] suppress announcement to peer AS %u"
1575 peer
->host
, bgp
->confed_id
);
1580 /* Route-Reflect check. */
1581 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1586 /* IBGP reflection check. */
1587 if (reflect
&& !samepeer_safe
) {
1588 /* A route from a Client peer. */
1589 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1590 PEER_FLAG_REFLECTOR_CLIENT
)) {
1591 /* Reflect to all the Non-Client peers and also to the
1592 Client peers other than the originator. Originator
1594 is already done. So there is noting to do. */
1595 /* no bgp client-to-client reflection check. */
1596 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1597 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1598 PEER_FLAG_REFLECTOR_CLIENT
))
1601 /* A route from a Non-client peer. Reflect to all other
1603 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1604 PEER_FLAG_REFLECTOR_CLIENT
))
1609 /* For modify attribute, copy it to temporary structure. */
1610 bgp_attr_dup(attr
, riattr
);
1612 /* If local-preference is not set. */
1613 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1614 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1615 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1616 attr
->local_pref
= bgp
->default_local_pref
;
1619 /* If originator-id is not set and the route is to be reflected,
1620 set the originator id */
1622 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1623 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1624 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1627 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1629 if (peer
->sort
== BGP_PEER_EBGP
1630 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1631 if (from
!= bgp
->peer_self
&& !transparent
1632 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1633 PEER_FLAG_MED_UNCHANGED
))
1635 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1638 /* Since the nexthop attribute can vary per peer, it is not explicitly
1640 * in announce check, only certain flags and length (or number of
1642 * -- for IPv6/MP_REACH) are set here in order to guide the update
1644 * code in setting the nexthop(s) on a per peer basis in
1646 * Typically, the source nexthop in the attribute is preserved but in
1648 * scenarios where we know it will always be overwritten, we reset the
1649 * nexthop to "0" in an attempt to achieve better Update packing. An
1650 * example of this is when a prefix from each of 2 IBGP peers needs to
1652 * announced to an EBGP peer (and they have the same attributes barring
1656 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1658 #define NEXTHOP_IS_V6 \
1659 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1660 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1661 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1662 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1664 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1666 * the peer (group) is configured to receive link-local nexthop
1668 * and it is available in the prefix OR we're not reflecting the route
1670 * the peer (group) to whom we're going to announce is on a shared
1672 * and this is either a self-originated route or the peer is EBGP.
1674 if (NEXTHOP_IS_V6
) {
1675 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1676 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1677 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1678 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1679 || (!reflect
&& peer
->shared_network
1680 && (from
== bgp
->peer_self
1681 || peer
->sort
== BGP_PEER_EBGP
))) {
1682 attr
->mp_nexthop_len
=
1683 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1686 /* Clear off link-local nexthop in source, whenever it is not
1688 * ensure more prefixes share the same attribute for
1691 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1692 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1693 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1696 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1697 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1699 /* Route map & unsuppress-map apply. */
1700 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1701 struct bgp_path_info info
;
1702 struct bgp_path_info_extra dummy_info_extra
;
1703 struct attr dummy_attr
;
1705 memset(&info
, 0, sizeof(struct bgp_path_info
));
1710 memcpy(&dummy_info_extra
, ri
->extra
,
1711 sizeof(struct bgp_path_info_extra
));
1712 info
.extra
= &dummy_info_extra
;
1715 /* don't confuse inbound and outbound setting */
1716 RESET_FLAG(attr
->rmap_change_flags
);
1719 * The route reflector is not allowed to modify the attributes
1720 * of the reflected IBGP routes unless explicitly allowed.
1722 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1723 && !bgp_flag_check(bgp
,
1724 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1725 bgp_attr_dup(&dummy_attr
, attr
);
1726 info
.attr
= &dummy_attr
;
1729 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1731 if (ri
->extra
&& ri
->extra
->suppress
)
1732 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1735 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1738 peer
->rmap_type
= 0;
1740 if (ret
== RMAP_DENYMATCH
) {
1741 bgp_attr_flush(attr
);
1746 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1747 if (peer
->sort
== BGP_PEER_IBGP
1748 || peer
->sort
== BGP_PEER_CONFED
) {
1749 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1750 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1752 bgp_attr_add_gshut_community(attr
);
1756 /* After route-map has been applied, we check to see if the nexthop to
1757 * be carried in the attribute (that is used for the announcement) can
1758 * be cleared off or not. We do this in all cases where we would be
1759 * setting the nexthop to "ourselves". For IPv6, we only need to
1761 * the global nexthop here; the link-local nexthop would have been
1763 * already, and if not, it is required by the update formation code.
1764 * Also see earlier comments in this function.
1767 * If route-map has performed some operation on the nexthop or the peer
1768 * configuration says to pass it unchanged, we cannot reset the nexthop
1769 * here, so only attempt to do it if these aren't true. Note that the
1770 * route-map handler itself might have cleared the nexthop, if for
1772 * it is configured as 'peer-address'.
1774 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1775 riattr
->rmap_change_flags
)
1777 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1778 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1779 /* We can reset the nexthop, if setting (or forcing) it to
1781 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1782 PEER_FLAG_NEXTHOP_SELF
)
1783 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1784 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1786 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1787 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1788 subgroup_announce_reset_nhop(
1789 (peer_cap_enhe(peer
, afi
, safi
)
1793 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1794 /* Can also reset the nexthop if announcing to EBGP, but
1796 * no peer in the subgroup is on a shared subnet.
1797 * Note: 3rd party nexthop currently implemented for
1800 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1802 subgroup_announce_reset_nhop(
1803 (peer_cap_enhe(peer
, afi
, safi
)
1807 } else if (CHECK_FLAG(ri
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1809 * This flag is used for leaked vpn-vrf routes
1811 int family
= p
->family
;
1813 if (peer_cap_enhe(peer
, afi
, safi
))
1816 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1818 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1819 __func__
, family2str(family
));
1820 subgroup_announce_reset_nhop(family
, attr
);
1823 /* If IPv6/MP and nexthop does not have any override and happens
1825 * be a link-local address, reset it so that we don't pass along
1827 * source's link-local IPv6 address to recipients who may not be
1829 * the same interface.
1831 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1832 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1833 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1840 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1841 struct bgp_maxpaths_cfg
*mpath_cfg
,
1842 struct bgp_path_info_pair
*result
, afi_t afi
,
1845 struct bgp_path_info
*new_select
;
1846 struct bgp_path_info
*old_select
;
1847 struct bgp_path_info
*ri
;
1848 struct bgp_path_info
*ri1
;
1849 struct bgp_path_info
*ri2
;
1850 struct bgp_path_info
*nextri
= NULL
;
1851 int paths_eq
, do_mpath
, debug
;
1852 struct list mp_list
;
1853 char pfx_buf
[PREFIX2STR_BUFFER
];
1854 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1856 bgp_mp_list_init(&mp_list
);
1858 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1860 debug
= bgp_debug_bestpath(&rn
->p
);
1863 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1865 /* bgp deterministic-med */
1867 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1869 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1870 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1871 bgp_info_unset_flag(rn
, ri1
, BGP_PATH_DMED_SELECTED
);
1873 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1874 if (CHECK_FLAG(ri1
->flags
, BGP_PATH_DMED_CHECK
))
1876 if (BGP_PATH_HOLDDOWN(ri1
))
1878 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1879 if (ri1
->peer
->status
!= Established
)
1884 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1885 if (CHECK_FLAG(ri2
->flags
,
1886 BGP_PATH_DMED_CHECK
))
1888 if (BGP_PATH_HOLDDOWN(ri2
))
1891 && ri2
->peer
!= bgp
->peer_self
1894 PEER_STATUS_NSF_WAIT
))
1895 if (ri2
->peer
->status
1899 if (aspath_cmp_left(ri1
->attr
->aspath
,
1901 || aspath_cmp_left_confed(
1903 ri2
->attr
->aspath
)) {
1904 if (bgp_info_cmp(bgp
, ri2
,
1910 bgp_info_unset_flag(
1912 BGP_PATH_DMED_SELECTED
);
1918 BGP_PATH_DMED_CHECK
);
1922 bgp_info_set_flag(rn
, new_select
, BGP_PATH_DMED_CHECK
);
1923 bgp_info_set_flag(rn
, new_select
,
1924 BGP_PATH_DMED_SELECTED
);
1927 bgp_info_path_with_addpath_rx_str(new_select
,
1929 zlog_debug("%s: %s is the bestpath from AS %u",
1931 aspath_get_first_as(
1932 new_select
->attr
->aspath
));
1937 /* Check old selected route and new selected route. */
1940 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1942 if (CHECK_FLAG(ri
->flags
, BGP_PATH_SELECTED
))
1945 if (BGP_PATH_HOLDDOWN(ri
)) {
1946 /* reap REMOVED routes, if needs be
1947 * selected route must stay for a while longer though
1949 if (CHECK_FLAG(ri
->flags
, BGP_PATH_REMOVED
)
1950 && (ri
!= old_select
))
1951 bgp_info_reap(rn
, ri
);
1954 zlog_debug("%s: ri %p in holddown", __func__
,
1960 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1961 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1962 if (ri
->peer
->status
!= Established
) {
1966 "%s: ri %p non self peer %s not estab state",
1967 __func__
, ri
, ri
->peer
->host
);
1972 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1973 && (!CHECK_FLAG(ri
->flags
, BGP_PATH_DMED_SELECTED
))) {
1974 bgp_info_unset_flag(rn
, ri
, BGP_PATH_DMED_CHECK
);
1976 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1980 bgp_info_unset_flag(rn
, ri
, BGP_PATH_DMED_CHECK
);
1982 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1983 debug
, pfx_buf
, afi
, safi
)) {
1988 /* Now that we know which path is the bestpath see if any of the other
1990 * qualify as multipaths
1994 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1996 sprintf(path_buf
, "NONE");
1998 "%s: After path selection, newbest is %s oldbest was %s",
2000 old_select
? old_select
->peer
->host
: "NONE");
2003 if (do_mpath
&& new_select
) {
2004 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
2008 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
2010 if (ri
== new_select
) {
2013 "%s: %s is the bestpath, add to the multipath list",
2015 bgp_mp_list_add(&mp_list
, ri
);
2019 if (BGP_PATH_HOLDDOWN(ri
))
2022 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
2023 && !CHECK_FLAG(ri
->peer
->sflags
,
2024 PEER_STATUS_NSF_WAIT
))
2025 if (ri
->peer
->status
!= Established
)
2028 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
2031 "%s: %s has the same nexthop as the bestpath, skip it",
2036 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
2037 debug
, pfx_buf
, afi
, safi
);
2042 "%s: %s is equivalent to the bestpath, add to the multipath list",
2044 bgp_mp_list_add(&mp_list
, ri
);
2049 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
2050 bgp_info_mpath_aggregate_update(new_select
, old_select
);
2051 bgp_mp_list_clear(&mp_list
);
2053 result
->old
= old_select
;
2054 result
->new = new_select
;
2060 * A new route/change in bestpath of an existing route. Evaluate the path
2061 * for advertisement to the subgroup.
2063 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2064 struct bgp_path_info
*selected
,
2065 struct bgp_node
*rn
,
2066 uint32_t addpath_tx_id
)
2069 struct peer
*onlypeer
;
2075 afi
= SUBGRP_AFI(subgrp
);
2076 safi
= SUBGRP_SAFI(subgrp
);
2077 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2080 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2081 char buf_prefix
[PREFIX_STRLEN
];
2082 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2083 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2087 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2088 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2089 PEER_STATUS_ORF_WAIT_REFRESH
))
2092 memset(&attr
, 0, sizeof(struct attr
));
2093 /* It's initialized in bgp_announce_check() */
2095 /* Announcement to the subgroup. If the route is filtered withdraw it.
2098 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2099 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2101 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2102 selected
->addpath_tx_id
);
2105 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2107 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2114 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2115 * This is called at the end of route processing.
2117 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2119 struct bgp_path_info
*ri
;
2121 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2122 if (BGP_PATH_HOLDDOWN(ri
))
2124 UNSET_FLAG(ri
->flags
, BGP_PATH_IGP_CHANGED
);
2125 UNSET_FLAG(ri
->flags
, BGP_PATH_ATTR_CHANGED
);
2130 * Has the route changed from the RIB's perspective? This is invoked only
2131 * if the route selection returns the same best route as earlier - to
2132 * determine if we need to update zebra or not.
2134 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2135 struct bgp_path_info
*selected
)
2137 struct bgp_path_info
*mpinfo
;
2139 /* If this is multipath, check all selected paths for any nexthop
2140 * change or attribute change. Some attribute changes (e.g., community)
2141 * aren't of relevance to the RIB, but we'll update zebra to ensure
2142 * we handle the case of BGP nexthop change. This is the behavior
2143 * when the best path has an attribute change anyway.
2145 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2146 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2150 * If this is multipath, check all selected paths for any nexthop change
2152 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2153 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2154 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2155 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2159 /* Nothing has changed from the RIB's perspective. */
2163 struct bgp_process_queue
{
2165 STAILQ_HEAD(, bgp_node
) pqueue
;
2166 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2168 unsigned int queued
;
2172 * old_select = The old best path
2173 * new_select = the new best path
2175 * if (!old_select && new_select)
2176 * We are sending new information on.
2178 * if (old_select && new_select) {
2179 * if (new_select != old_select)
2180 * We have a new best path send a change
2182 * We've received a update with new attributes that needs
2186 * if (old_select && !new_select)
2187 * We have no eligible route that we can announce or the rn
2190 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2191 afi_t afi
, safi_t safi
)
2193 struct bgp_path_info
*new_select
;
2194 struct bgp_path_info
*old_select
;
2195 struct bgp_path_info_pair old_and_new
;
2196 char pfx_buf
[PREFIX2STR_BUFFER
];
2199 /* Is it end of initial update? (after startup) */
2201 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2202 sizeof(bgp
->update_delay_zebra_resume_time
));
2204 bgp
->main_zebra_update_hold
= 0;
2205 FOREACH_AFI_SAFI (afi
, safi
) {
2206 if (bgp_fibupd_safi(safi
))
2207 bgp_zebra_announce_table(bgp
, afi
, safi
);
2209 bgp
->main_peers_update_hold
= 0;
2211 bgp_start_routeadv(bgp
);
2215 struct prefix
*p
= &rn
->p
;
2217 debug
= bgp_debug_bestpath(&rn
->p
);
2219 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2220 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2221 afi2str(afi
), safi2str(safi
));
2224 /* Best path selection. */
2225 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2227 old_select
= old_and_new
.old
;
2228 new_select
= old_and_new
.new;
2230 /* Do we need to allocate or free labels?
2231 * Right now, since we only deal with per-prefix labels, it is not
2232 * necessary to do this upon changes to best path except if the label
2235 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2238 || bgp_label_index_differs(new_select
, old_select
)
2239 || new_select
->sub_type
!= old_select
->sub_type
) {
2240 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2241 && new_select
->attr
->flag
2243 BGP_ATTR_PREFIX_SID
)
2244 && new_select
->attr
->label_index
2245 != BGP_INVALID_LABEL_INDEX
) {
2248 BGP_NODE_REGISTERED_FOR_LABEL
))
2249 bgp_unregister_for_label(rn
);
2250 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2252 bgp_set_valid_label(&rn
->local_label
);
2254 bgp_register_for_label(rn
, new_select
);
2256 } else if (CHECK_FLAG(rn
->flags
,
2257 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2258 bgp_unregister_for_label(rn
);
2260 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2261 bgp_unregister_for_label(rn
);
2265 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2267 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2268 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2269 old_select
, new_select
);
2272 /* If best route remains the same and this is not due to user-initiated
2273 * clear, see exactly what needs to be done.
2275 if (old_select
&& old_select
== new_select
2276 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2277 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2278 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2279 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2281 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2282 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2284 if (bgp_fibupd_safi(safi
)
2285 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2287 if (new_select
->type
== ZEBRA_ROUTE_BGP
2288 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2289 || new_select
->sub_type
2290 == BGP_ROUTE_IMPORTED
))
2292 bgp_zebra_announce(rn
, p
, old_select
,
2296 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2297 bgp_zebra_clear_route_change_flags(rn
);
2299 /* If there is a change of interest to peers, reannounce the
2301 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2302 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2303 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2305 /* unicast routes must also be annouced to
2306 * labeled-unicast update-groups */
2307 if (safi
== SAFI_UNICAST
)
2308 group_announce_route(bgp
, afi
,
2309 SAFI_LABELED_UNICAST
, rn
,
2312 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2313 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2316 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2320 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2322 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2324 /* bestpath has changed; bump version */
2325 if (old_select
|| new_select
) {
2326 bgp_bump_version(rn
);
2328 if (!bgp
->t_rmap_def_originate_eval
) {
2332 update_group_refresh_default_originate_route_map
,
2333 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2334 &bgp
->t_rmap_def_originate_eval
);
2339 bgp_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2342 zlog_debug("%s: setting SELECTED flag", __func__
);
2343 bgp_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2344 bgp_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2345 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2349 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2350 if (old_select
!= new_select
) {
2352 vnc_import_bgp_exterior_del_route(bgp
, p
,
2354 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2357 vnc_import_bgp_exterior_add_route(bgp
, p
,
2359 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2365 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2367 /* unicast routes must also be annouced to labeled-unicast update-groups
2369 if (safi
== SAFI_UNICAST
)
2370 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2374 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2375 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2376 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2377 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2378 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2379 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2381 /* if this is an evpn imported type-5 prefix,
2382 * we need to withdraw the route first to clear
2383 * the nh neigh and the RMAC entry.
2386 is_route_parent_evpn(old_select
))
2387 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2389 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2391 /* Withdraw the route from the kernel. */
2392 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2393 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2394 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2395 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2397 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2401 /* advertise/withdraw type-5 routes */
2402 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2403 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2404 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2406 /* apply the route-map */
2407 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2410 ret
= route_map_apply(
2411 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2412 &rn
->p
, RMAP_BGP
, new_select
);
2413 if (ret
== RMAP_MATCH
)
2414 bgp_evpn_advertise_type5_route(
2415 bgp
, &rn
->p
, new_select
->attr
,
2418 bgp_evpn_advertise_type5_route(bgp
,
2424 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2425 (!old_select
->extra
|| !old_select
->extra
->parent
))
2426 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2429 /* Clear any route change flags. */
2430 bgp_zebra_clear_route_change_flags(rn
);
2432 /* Reap old select bgp_info, if it has been removed */
2433 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2434 bgp_info_reap(rn
, old_select
);
2436 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2440 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2442 struct bgp_process_queue
*pqnode
= data
;
2443 struct bgp
*bgp
= pqnode
->bgp
;
2444 struct bgp_table
*table
;
2445 struct bgp_node
*rn
;
2448 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2449 bgp_process_main_one(bgp
, NULL
, 0, 0);
2450 /* should always have dedicated wq call */
2451 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2455 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2456 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2457 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2458 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2459 table
= bgp_node_table(rn
);
2460 /* note, new RNs may be added as part of processing */
2461 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2463 bgp_unlock_node(rn
);
2464 bgp_table_unlock(table
);
2470 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2472 struct bgp_process_queue
*pqnode
= data
;
2474 bgp_unlock(pqnode
->bgp
);
2476 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2479 void bgp_process_queue_init(void)
2481 if (!bm
->process_main_queue
)
2482 bm
->process_main_queue
=
2483 work_queue_new(bm
->master
, "process_main_queue");
2485 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2486 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2487 bm
->process_main_queue
->spec
.max_retries
= 0;
2488 bm
->process_main_queue
->spec
.hold
= 50;
2489 /* Use a higher yield value of 50ms for main queue processing */
2490 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2493 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2495 struct bgp_process_queue
*pqnode
;
2497 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2498 sizeof(struct bgp_process_queue
));
2500 /* unlocked in bgp_processq_del */
2501 pqnode
->bgp
= bgp_lock(bgp
);
2502 STAILQ_INIT(&pqnode
->pqueue
);
2507 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2509 #define ARBITRARY_PROCESS_QLEN 10000
2510 struct work_queue
*wq
= bm
->process_main_queue
;
2511 struct bgp_process_queue
*pqnode
;
2512 int pqnode_reuse
= 0;
2514 /* already scheduled for processing? */
2515 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2521 /* Add route nodes to an existing work queue item until reaching the
2522 limit only if is from the same BGP view and it's not an EOIU marker
2524 if (work_queue_item_count(wq
)) {
2525 struct work_queue_item
*item
= work_queue_last_item(wq
);
2526 pqnode
= item
->data
;
2528 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2529 || pqnode
->bgp
!= bgp
2530 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2531 pqnode
= bgp_processq_alloc(bgp
);
2535 pqnode
= bgp_processq_alloc(bgp
);
2536 /* all unlocked in bgp_process_wq */
2537 bgp_table_lock(bgp_node_table(rn
));
2539 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2542 /* can't be enqueued twice */
2543 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2544 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2548 work_queue_add(wq
, pqnode
);
2553 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2555 struct bgp_process_queue
*pqnode
;
2557 if (bm
->process_main_queue
== NULL
)
2560 pqnode
= bgp_processq_alloc(bgp
);
2562 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2563 work_queue_add(bm
->process_main_queue
, pqnode
);
2566 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2570 peer
= THREAD_ARG(thread
);
2571 peer
->t_pmax_restart
= NULL
;
2573 if (bgp_debug_neighbor_events(peer
))
2575 "%s Maximum-prefix restart timer expired, restore peering",
2578 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2579 zlog_debug("%s: %s peer_clear failed",
2580 __PRETTY_FUNCTION__
, peer
->host
);
2585 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2589 iana_safi_t pkt_safi
;
2591 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2594 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2595 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2596 PEER_STATUS_PREFIX_LIMIT
)
2601 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2603 afi_safi_print(afi
, safi
), peer
->host
,
2604 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2605 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2607 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2608 PEER_FLAG_MAX_PREFIX_WARNING
))
2611 /* Convert AFI, SAFI to values for packet. */
2612 pkt_afi
= afi_int2iana(afi
);
2613 pkt_safi
= safi_int2iana(safi
);
2617 ndata
[0] = (pkt_afi
>> 8);
2619 ndata
[2] = pkt_safi
;
2620 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2621 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2622 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2623 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2625 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2626 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2627 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2631 /* Dynamic peers will just close their connection. */
2632 if (peer_dynamic_neighbor(peer
))
2635 /* restart timer start */
2636 if (peer
->pmax_restart
[afi
][safi
]) {
2637 peer
->v_pmax_restart
=
2638 peer
->pmax_restart
[afi
][safi
] * 60;
2640 if (bgp_debug_neighbor_events(peer
))
2642 "%s Maximum-prefix restart timer started for %d secs",
2643 peer
->host
, peer
->v_pmax_restart
);
2645 BGP_TIMER_ON(peer
->t_pmax_restart
,
2646 bgp_maximum_prefix_restart_timer
,
2647 peer
->v_pmax_restart
);
2652 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2653 PEER_STATUS_PREFIX_LIMIT
);
2655 if (peer
->pcount
[afi
][safi
]
2656 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2657 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2658 PEER_STATUS_PREFIX_THRESHOLD
)
2663 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2664 afi_safi_print(afi
, safi
), peer
->host
,
2665 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2666 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2667 PEER_STATUS_PREFIX_THRESHOLD
);
2669 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2670 PEER_STATUS_PREFIX_THRESHOLD
);
2674 /* Unconditionally remove the route from the RIB, without taking
2675 * damping into consideration (eg, because the session went down)
2677 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*ri
,
2678 struct peer
*peer
, afi_t afi
, safi_t safi
)
2680 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2682 if (!CHECK_FLAG(ri
->flags
, BGP_PATH_HISTORY
))
2683 bgp_info_delete(rn
, ri
); /* keep historical info */
2685 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2688 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*ri
,
2689 struct peer
*peer
, afi_t afi
, safi_t safi
,
2690 struct prefix_rd
*prd
)
2692 /* apply dampening, if result is suppressed, we'll be retaining
2693 * the bgp_info in the RIB for historical reference.
2695 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2696 && peer
->sort
== BGP_PEER_EBGP
)
2697 if ((bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2698 == BGP_DAMP_SUPPRESSED
) {
2699 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2705 if (safi
== SAFI_MPLS_VPN
) {
2706 struct bgp_node
*prn
= NULL
;
2707 struct bgp_table
*table
= NULL
;
2709 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2710 (struct prefix
*)prd
);
2712 table
= (struct bgp_table
*)(prn
->info
);
2714 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2715 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2717 bgp_unlock_node(prn
);
2719 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2720 if (CHECK_FLAG(ri
->flags
, BGP_PATH_SELECTED
)) {
2722 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2723 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2729 /* If this is an EVPN route, process for un-import. */
2730 if (safi
== SAFI_EVPN
)
2731 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2733 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2736 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2737 struct peer
*peer
, struct attr
*attr
,
2738 struct bgp_node
*rn
)
2740 struct bgp_path_info
*new;
2742 /* Make new BGP info. */
2743 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2745 new->instance
= instance
;
2746 new->sub_type
= sub_type
;
2749 new->uptime
= bgp_clock();
2751 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2755 static void overlay_index_update(struct attr
*attr
,
2756 struct eth_segment_id
*eth_s_id
,
2757 union gw_addr
*gw_ip
)
2762 if (eth_s_id
== NULL
) {
2763 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2764 sizeof(struct eth_segment_id
));
2766 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2767 sizeof(struct eth_segment_id
));
2769 if (gw_ip
== NULL
) {
2770 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2772 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2773 sizeof(union gw_addr
));
2777 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*info
,
2778 struct eth_segment_id
*eth_s_id
,
2779 union gw_addr
*gw_ip
)
2781 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2782 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2784 struct eth_segment_id esi
;
2788 if (afi
!= AFI_L2VPN
)
2791 memset(&temp
, 0, sizeof(temp
));
2792 info_eth_s_id
= &temp
.esi
;
2793 info_gw_ip
= &temp
.ip
;
2795 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2798 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2799 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2802 if (gw_ip
== NULL
) {
2803 memset(&temp
, 0, sizeof(temp
));
2804 info_gw_ip_remote
= &temp
.ip
;
2806 info_gw_ip_remote
= gw_ip
;
2808 if (eth_s_id
== NULL
) {
2809 memset(&temp
, 0, sizeof(temp
));
2810 info_eth_s_id_remote
= &temp
.esi
;
2812 info_eth_s_id_remote
= eth_s_id
;
2814 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2817 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2818 sizeof(struct eth_segment_id
));
2821 /* Check if received nexthop is valid or not. */
2822 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2827 /* Only validated for unicast and multicast currently. */
2828 /* Also valid for EVPN where the nexthop is an IP address. */
2829 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2832 /* If NEXT_HOP is present, validate it. */
2833 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2834 if (attr
->nexthop
.s_addr
== 0
2835 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2836 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2840 /* If MP_NEXTHOP is present, validate it. */
2841 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2842 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2843 * it is not an IPv6 link-local address.
2845 if (attr
->mp_nexthop_len
) {
2846 switch (attr
->mp_nexthop_len
) {
2847 case BGP_ATTR_NHLEN_IPV4
:
2848 case BGP_ATTR_NHLEN_VPNV4
:
2849 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2850 || IPV4_CLASS_DE(ntohl(
2851 attr
->mp_nexthop_global_in
.s_addr
))
2852 || bgp_nexthop_self(bgp
,
2853 attr
->mp_nexthop_global_in
));
2856 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2857 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2858 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2859 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2860 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2861 || IN6_IS_ADDR_MULTICAST(
2862 &attr
->mp_nexthop_global
));
2874 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2875 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2876 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2877 uint32_t num_labels
, int soft_reconfig
,
2878 struct bgp_route_evpn
*evpn
)
2881 int aspath_loop_count
= 0;
2882 struct bgp_node
*rn
;
2884 struct attr new_attr
;
2885 struct attr
*attr_new
;
2886 struct bgp_path_info
*ri
;
2887 struct bgp_path_info
*new;
2888 struct bgp_path_info_extra
*extra
;
2890 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2892 int do_loop_check
= 1;
2893 int has_valid_label
= 0;
2895 int vnc_implicit_withdraw
= 0;
2899 memset(&new_attr
, 0, sizeof(struct attr
));
2900 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2901 new_attr
.label
= MPLS_INVALID_LABEL
;
2904 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2905 /* TODO: Check to see if we can get rid of "is_valid_label" */
2906 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2907 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2909 has_valid_label
= bgp_is_valid_label(label
);
2911 /* When peer's soft reconfiguration enabled. Record input packet in
2914 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2915 && peer
!= bgp
->peer_self
)
2916 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2918 /* Check previously received route. */
2919 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2920 if (ri
->peer
== peer
&& ri
->type
== type
2921 && ri
->sub_type
== sub_type
2922 && ri
->addpath_rx_id
== addpath_id
)
2925 /* AS path local-as loop check. */
2926 if (peer
->change_local_as
) {
2927 if (peer
->allowas_in
[afi
][safi
])
2928 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2929 else if (!CHECK_FLAG(peer
->flags
,
2930 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2931 aspath_loop_count
= 1;
2933 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2934 > aspath_loop_count
) {
2935 reason
= "as-path contains our own AS;";
2940 /* If the peer is configured for "allowas-in origin" and the last ASN in
2942 * as-path is our ASN then we do not need to call aspath_loop_check
2944 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2945 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2948 /* AS path loop check. */
2949 if (do_loop_check
) {
2950 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2951 > peer
->allowas_in
[afi
][safi
]
2952 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2953 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2954 > peer
->allowas_in
[afi
][safi
])) {
2955 reason
= "as-path contains our own AS;";
2960 /* Route reflector originator ID check. */
2961 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2962 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2963 reason
= "originator is us;";
2967 /* Route reflector cluster ID check. */
2968 if (bgp_cluster_filter(peer
, attr
)) {
2969 reason
= "reflected from the same cluster;";
2973 /* Apply incoming filter. */
2974 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2979 bgp_attr_dup(&new_attr
, attr
);
2981 /* Apply incoming route-map.
2982 * NB: new_attr may now contain newly allocated values from route-map
2984 * commands, so we need bgp_attr_flush in the error paths, until we
2986 * the attr (which takes over the memory references) */
2987 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2989 reason
= "route-map;";
2990 bgp_attr_flush(&new_attr
);
2994 if (peer
->sort
== BGP_PEER_EBGP
) {
2996 /* If we receive the graceful-shutdown community from an eBGP
2997 * peer we must lower local-preference */
2998 if (new_attr
.community
2999 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3000 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3001 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3003 /* If graceful-shutdown is configured then add the GSHUT
3004 * community to all paths received from eBGP peers */
3005 } else if (bgp_flag_check(peer
->bgp
,
3006 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3007 bgp_attr_add_gshut_community(&new_attr
);
3011 /* next hop check. */
3012 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3013 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3014 reason
= "martian or self next-hop;";
3015 bgp_attr_flush(&new_attr
);
3019 attr_new
= bgp_attr_intern(&new_attr
);
3021 /* If the update is implicit withdraw. */
3023 ri
->uptime
= bgp_clock();
3024 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
3026 /* Same attribute comes in. */
3027 if (!CHECK_FLAG(ri
->flags
, BGP_PATH_REMOVED
)
3028 && attrhash_cmp(ri
->attr
, attr_new
)
3029 && (!has_valid_label
3030 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
3031 num_labels
* sizeof(mpls_label_t
))
3033 && (overlay_index_equal(
3034 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3035 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3036 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3037 BGP_CONFIG_DAMPENING
)
3038 && peer
->sort
== BGP_PEER_EBGP
3039 && CHECK_FLAG(ri
->flags
, BGP_PATH_HISTORY
)) {
3040 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3041 bgp_debug_rdpfxpath2str(
3042 afi
, safi
, prd
, p
, label
,
3043 num_labels
, addpath_id
? 1 : 0,
3044 addpath_id
, pfx_buf
,
3046 zlog_debug("%s rcvd %s", peer
->host
,
3050 if (bgp_damp_update(ri
, rn
, afi
, safi
)
3051 != BGP_DAMP_SUPPRESSED
) {
3052 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
3054 bgp_process(bgp
, rn
, afi
, safi
);
3056 } else /* Duplicate - odd */
3058 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3059 if (!peer
->rcvd_attr_printed
) {
3061 "%s rcvd UPDATE w/ attr: %s",
3063 peer
->rcvd_attr_str
);
3064 peer
->rcvd_attr_printed
= 1;
3067 bgp_debug_rdpfxpath2str(
3068 afi
, safi
, prd
, p
, label
,
3069 num_labels
, addpath_id
? 1 : 0,
3070 addpath_id
, pfx_buf
,
3073 "%s rcvd %s...duplicate ignored",
3074 peer
->host
, pfx_buf
);
3077 /* graceful restart STALE flag unset. */
3078 if (CHECK_FLAG(ri
->flags
, BGP_PATH_STALE
)) {
3079 bgp_info_unset_flag(rn
, ri
,
3081 bgp_process(bgp
, rn
, afi
, safi
);
3085 bgp_unlock_node(rn
);
3086 bgp_attr_unintern(&attr_new
);
3091 /* Withdraw/Announce before we fully processed the withdraw */
3092 if (CHECK_FLAG(ri
->flags
, BGP_PATH_REMOVED
)) {
3093 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3094 bgp_debug_rdpfxpath2str(
3095 afi
, safi
, prd
, p
, label
, num_labels
,
3096 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3099 "%s rcvd %s, flapped quicker than processing",
3100 peer
->host
, pfx_buf
);
3103 bgp_info_restore(rn
, ri
);
3106 /* Received Logging. */
3107 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3108 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3109 num_labels
, addpath_id
? 1 : 0,
3110 addpath_id
, pfx_buf
,
3112 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3115 /* graceful restart STALE flag unset. */
3116 if (CHECK_FLAG(ri
->flags
, BGP_PATH_STALE
))
3117 bgp_info_unset_flag(rn
, ri
, BGP_PATH_STALE
);
3119 /* The attribute is changed. */
3120 bgp_info_set_flag(rn
, ri
, BGP_PATH_ATTR_CHANGED
);
3122 /* implicit withdraw, decrement aggregate and pcount here.
3123 * only if update is accepted, they'll increment below.
3125 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3127 /* Update bgp route dampening information. */
3128 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3129 && peer
->sort
== BGP_PEER_EBGP
) {
3130 /* This is implicit withdraw so we should update
3133 if (!CHECK_FLAG(ri
->flags
, BGP_PATH_HISTORY
))
3134 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3137 if (safi
== SAFI_MPLS_VPN
) {
3138 struct bgp_node
*prn
= NULL
;
3139 struct bgp_table
*table
= NULL
;
3141 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3142 (struct prefix
*)prd
);
3144 table
= (struct bgp_table
*)(prn
->info
);
3146 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3147 bgp
, prd
, table
, p
, ri
);
3149 bgp_unlock_node(prn
);
3151 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3152 && (safi
== SAFI_UNICAST
)) {
3153 if (CHECK_FLAG(ri
->flags
, BGP_PATH_SELECTED
)) {
3155 * Implicit withdraw case.
3157 ++vnc_implicit_withdraw
;
3158 vnc_import_bgp_del_route(bgp
, p
, ri
);
3159 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3164 /* Special handling for EVPN update of an existing route. If the
3165 * extended community attribute has changed, we need to
3167 * the route using its existing extended community. It will be
3168 * subsequently processed for import with the new extended
3171 if (safi
== SAFI_EVPN
&& !same_attr
) {
3173 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3175 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3178 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3179 attr_new
->ecommunity
);
3181 if (bgp_debug_update(peer
, p
, NULL
, 1))
3183 "Change in EXT-COMM, existing %s new %s",
3185 ri
->attr
->ecommunity
),
3187 attr_new
->ecommunity
));
3188 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3194 /* Update to new attribute. */
3195 bgp_attr_unintern(&ri
->attr
);
3196 ri
->attr
= attr_new
;
3198 /* Update MPLS label */
3199 if (has_valid_label
) {
3200 extra
= bgp_info_extra_get(ri
);
3201 memcpy(&extra
->label
, label
,
3202 num_labels
* sizeof(mpls_label_t
));
3203 extra
->num_labels
= num_labels
;
3204 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3205 bgp_set_valid_label(&extra
->label
[0]);
3209 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3210 && (safi
== SAFI_UNICAST
)) {
3211 if (vnc_implicit_withdraw
) {
3213 * Add back the route with its new attributes
3215 * The route is still selected, until the route
3217 * queued by bgp_process actually runs. We have
3219 * update to the VNC side immediately to avoid
3221 * configuration changes (e.g., route-map
3223 * trigger re-importation of the entire RIB.
3225 vnc_import_bgp_add_route(bgp
, p
, ri
);
3226 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3230 /* Update Overlay Index */
3231 if (afi
== AFI_L2VPN
) {
3232 overlay_index_update(
3233 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3234 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3237 /* Update bgp route dampening information. */
3238 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3239 && peer
->sort
== BGP_PEER_EBGP
) {
3240 /* Now we do normal update dampening. */
3241 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3242 if (ret
== BGP_DAMP_SUPPRESSED
) {
3243 bgp_unlock_node(rn
);
3248 /* Nexthop reachability check - for unicast and
3249 * labeled-unicast.. */
3250 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3251 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3252 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3253 && !CHECK_FLAG(peer
->flags
,
3254 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3256 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3261 struct bgp
*bgp_nexthop
= bgp
;
3263 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3264 bgp_nexthop
= ri
->extra
->bgp_orig
;
3266 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3267 ri
, NULL
, connected
)
3268 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3269 bgp_info_set_flag(rn
, ri
, BGP_PATH_VALID
);
3271 if (BGP_DEBUG(nht
, NHT
)) {
3272 char buf1
[INET6_ADDRSTRLEN
];
3274 (const void *)&attr_new
3276 buf1
, INET6_ADDRSTRLEN
);
3277 zlog_debug("%s(%s): NH unresolved",
3278 __FUNCTION__
, buf1
);
3280 bgp_info_unset_flag(rn
, ri
, BGP_PATH_VALID
);
3283 bgp_info_set_flag(rn
, ri
, BGP_PATH_VALID
);
3286 if (safi
== SAFI_MPLS_VPN
) {
3287 struct bgp_node
*prn
= NULL
;
3288 struct bgp_table
*table
= NULL
;
3290 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3291 (struct prefix
*)prd
);
3293 table
= (struct bgp_table
*)(prn
->info
);
3295 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3296 bgp
, prd
, table
, p
, ri
);
3298 bgp_unlock_node(prn
);
3302 /* If this is an EVPN route and some attribute has changed,
3304 * route for import. If the extended community has changed, we
3306 * have done the un-import earlier and the import would result
3308 * route getting injected into appropriate L2 VNIs. If it is
3310 * some other attribute change, the import will result in
3312 * the attributes for the route in the VNI(s).
3314 if (safi
== SAFI_EVPN
&& !same_attr
)
3315 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3317 /* Process change. */
3318 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3320 bgp_process(bgp
, rn
, afi
, safi
);
3321 bgp_unlock_node(rn
);
3323 if (SAFI_UNICAST
== safi
3324 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3325 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3327 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3329 if ((SAFI_MPLS_VPN
== safi
)
3330 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3332 vpn_leak_to_vrf_update(bgp
, ri
);
3336 if (SAFI_MPLS_VPN
== safi
) {
3337 mpls_label_t label_decoded
= decode_label(label
);
3339 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3340 type
, sub_type
, &label_decoded
);
3342 if (SAFI_ENCAP
== safi
) {
3343 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3344 type
, sub_type
, NULL
);
3349 } // End of implicit withdraw
3351 /* Received Logging. */
3352 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3353 if (!peer
->rcvd_attr_printed
) {
3354 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3355 peer
->rcvd_attr_str
);
3356 peer
->rcvd_attr_printed
= 1;
3359 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3360 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3362 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3365 /* Make new BGP info. */
3366 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3368 /* Update MPLS label */
3369 if (has_valid_label
) {
3370 extra
= bgp_info_extra_get(new);
3371 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3372 extra
->num_labels
= num_labels
;
3373 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3374 bgp_set_valid_label(&extra
->label
[0]);
3377 /* Update Overlay Index */
3378 if (afi
== AFI_L2VPN
) {
3379 overlay_index_update(new->attr
,
3380 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3381 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3383 /* Nexthop reachability check. */
3384 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3385 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3386 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3387 && !CHECK_FLAG(peer
->flags
,
3388 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3389 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3394 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3395 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3396 bgp_info_set_flag(rn
, new, BGP_PATH_VALID
);
3398 if (BGP_DEBUG(nht
, NHT
)) {
3399 char buf1
[INET6_ADDRSTRLEN
];
3401 (const void *)&attr_new
->nexthop
,
3402 buf1
, INET6_ADDRSTRLEN
);
3403 zlog_debug("%s(%s): NH unresolved",
3404 __FUNCTION__
, buf1
);
3406 bgp_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3409 bgp_info_set_flag(rn
, new, BGP_PATH_VALID
);
3412 new->addpath_rx_id
= addpath_id
;
3414 /* Increment prefix */
3415 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3417 /* Register new BGP information. */
3418 bgp_info_add(rn
, new);
3420 /* route_node_get lock */
3421 bgp_unlock_node(rn
);
3424 if (safi
== SAFI_MPLS_VPN
) {
3425 struct bgp_node
*prn
= NULL
;
3426 struct bgp_table
*table
= NULL
;
3428 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3430 table
= (struct bgp_table
*)(prn
->info
);
3432 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3433 bgp
, prd
, table
, p
, new);
3435 bgp_unlock_node(prn
);
3439 /* If maximum prefix count is configured and current prefix
3441 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3444 /* If this is an EVPN route, process for import. */
3445 if (safi
== SAFI_EVPN
)
3446 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3448 /* Process change. */
3449 bgp_process(bgp
, rn
, afi
, safi
);
3451 if (SAFI_UNICAST
== safi
3452 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3453 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3454 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3456 if ((SAFI_MPLS_VPN
== safi
)
3457 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3459 vpn_leak_to_vrf_update(bgp
, new);
3462 if (SAFI_MPLS_VPN
== safi
) {
3463 mpls_label_t label_decoded
= decode_label(label
);
3465 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3466 sub_type
, &label_decoded
);
3468 if (SAFI_ENCAP
== safi
) {
3469 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3476 /* This BGP update is filtered. Log the reason then update BGP
3479 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3480 if (!peer
->rcvd_attr_printed
) {
3481 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3482 peer
->rcvd_attr_str
);
3483 peer
->rcvd_attr_printed
= 1;
3486 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3487 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3489 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3490 peer
->host
, pfx_buf
, reason
);
3494 /* If this is an EVPN route, un-import it as it is now filtered.
3496 if (safi
== SAFI_EVPN
)
3497 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3499 if (SAFI_UNICAST
== safi
3500 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3501 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3503 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3505 if ((SAFI_MPLS_VPN
== safi
)
3506 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3508 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3511 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3514 bgp_unlock_node(rn
);
3518 * Filtered update is treated as an implicit withdrawal (see
3520 * a few lines above)
3522 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3523 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3531 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3532 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3533 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3534 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3537 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3538 struct bgp_node
*rn
;
3539 struct bgp_path_info
*ri
;
3542 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3543 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3551 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3553 /* If peer is soft reconfiguration enabled. Record input packet for
3554 * further calculation.
3556 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3557 * routes that are filtered. This tanks out Quagga RS pretty badly due
3559 * the iteration over all RS clients.
3560 * Since we need to remove the entry from adj_in anyway, do that first
3562 * if there was no entry, we don't need to do anything more.
3564 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3565 && peer
!= bgp
->peer_self
)
3566 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3567 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3568 bgp_debug_rdpfxpath2str(
3569 afi
, safi
, prd
, p
, label
, num_labels
,
3570 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3573 "%s withdrawing route %s not in adj-in",
3574 peer
->host
, pfx_buf
);
3576 bgp_unlock_node(rn
);
3580 /* Lookup withdrawn route. */
3581 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3582 if (ri
->peer
== peer
&& ri
->type
== type
3583 && ri
->sub_type
== sub_type
3584 && ri
->addpath_rx_id
== addpath_id
)
3588 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3589 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3590 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3592 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3596 /* Withdraw specified route from routing table. */
3597 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_PATH_HISTORY
)) {
3598 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3599 if (SAFI_UNICAST
== safi
3600 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3601 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3602 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3604 if ((SAFI_MPLS_VPN
== safi
)
3605 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3607 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3609 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3610 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3611 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3613 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3616 /* Unlock bgp_node_get() lock. */
3617 bgp_unlock_node(rn
);
3622 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3625 struct update_subgroup
*subgrp
;
3626 subgrp
= peer_subgroup(peer
, afi
, safi
);
3627 subgroup_default_originate(subgrp
, withdraw
);
3632 * bgp_stop_announce_route_timer
3634 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3636 if (!paf
->t_announce_route
)
3639 THREAD_TIMER_OFF(paf
->t_announce_route
);
3643 * bgp_announce_route_timer_expired
3645 * Callback that is invoked when the route announcement timer for a
3648 static int bgp_announce_route_timer_expired(struct thread
*t
)
3650 struct peer_af
*paf
;
3653 paf
= THREAD_ARG(t
);
3656 if (peer
->status
!= Established
)
3659 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3662 peer_af_announce_route(paf
, 1);
3667 * bgp_announce_route
3669 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3671 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3673 struct peer_af
*paf
;
3674 struct update_subgroup
*subgrp
;
3676 paf
= peer_af_find(peer
, afi
, safi
);
3679 subgrp
= PAF_SUBGRP(paf
);
3682 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3683 * or a refresh has already been triggered.
3685 if (!subgrp
|| paf
->t_announce_route
)
3689 * Start a timer to stagger/delay the announce. This serves
3690 * two purposes - announcement can potentially be combined for
3691 * multiple peers and the announcement doesn't happen in the
3694 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3695 (subgrp
->peer_count
== 1)
3696 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3697 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3698 &paf
->t_announce_route
);
3702 * Announce routes from all AF tables to a peer.
3704 * This should ONLY be called when there is a need to refresh the
3705 * routes to the peer based on a policy change for this peer alone
3706 * or a route refresh request received from the peer.
3707 * The operation will result in splitting the peer from its existing
3708 * subgroups and putting it in new subgroups.
3710 void bgp_announce_route_all(struct peer
*peer
)
3715 FOREACH_AFI_SAFI (afi
, safi
)
3716 bgp_announce_route(peer
, afi
, safi
);
3719 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3720 struct bgp_table
*table
,
3721 struct prefix_rd
*prd
)
3724 struct bgp_node
*rn
;
3725 struct bgp_adj_in
*ain
;
3728 table
= peer
->bgp
->rib
[afi
][safi
];
3730 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3731 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3732 if (ain
->peer
!= peer
)
3735 struct bgp_path_info
*ri
= rn
->info
;
3736 uint32_t num_labels
= 0;
3737 mpls_label_t
*label_pnt
= NULL
;
3739 if (ri
&& ri
->extra
)
3740 num_labels
= ri
->extra
->num_labels
;
3742 label_pnt
= &ri
->extra
->label
[0];
3744 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3745 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3746 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3747 num_labels
, 1, NULL
);
3750 bgp_unlock_node(rn
);
3756 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3758 struct bgp_node
*rn
;
3759 struct bgp_table
*table
;
3761 if (peer
->status
!= Established
)
3764 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3765 && (safi
!= SAFI_EVPN
))
3766 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3768 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3769 rn
= bgp_route_next(rn
))
3770 if ((table
= rn
->info
) != NULL
) {
3771 struct prefix_rd prd
;
3772 prd
.family
= AF_UNSPEC
;
3774 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3776 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3782 struct bgp_clear_node_queue
{
3783 struct bgp_node
*rn
;
3786 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3788 struct bgp_clear_node_queue
*cnq
= data
;
3789 struct bgp_node
*rn
= cnq
->rn
;
3790 struct peer
*peer
= wq
->spec
.data
;
3791 struct bgp_path_info
*ri
;
3793 afi_t afi
= bgp_node_table(rn
)->afi
;
3794 safi_t safi
= bgp_node_table(rn
)->safi
;
3799 /* It is possible that we have multiple paths for a prefix from a peer
3800 * if that peer is using AddPath.
3802 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3803 if (ri
->peer
!= peer
)
3806 /* graceful restart STALE flag set. */
3807 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3808 && peer
->nsf
[afi
][safi
]
3809 && !CHECK_FLAG(ri
->flags
, BGP_PATH_STALE
)
3810 && !CHECK_FLAG(ri
->flags
, BGP_PATH_UNUSEABLE
))
3811 bgp_info_set_flag(rn
, ri
, BGP_PATH_STALE
);
3813 /* If this is an EVPN route, process for
3815 if (safi
== SAFI_EVPN
)
3816 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3818 /* Handle withdraw for VRF route-leaking and L3VPN */
3819 if (SAFI_UNICAST
== safi
3820 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3821 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3822 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3825 if (SAFI_MPLS_VPN
== safi
&&
3826 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3827 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3830 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3836 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3838 struct bgp_clear_node_queue
*cnq
= data
;
3839 struct bgp_node
*rn
= cnq
->rn
;
3840 struct bgp_table
*table
= bgp_node_table(rn
);
3842 bgp_unlock_node(rn
);
3843 bgp_table_unlock(table
);
3844 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3847 static void bgp_clear_node_complete(struct work_queue
*wq
)
3849 struct peer
*peer
= wq
->spec
.data
;
3851 /* Tickle FSM to start moving again */
3852 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3854 peer_unlock(peer
); /* bgp_clear_route */
3857 static void bgp_clear_node_queue_init(struct peer
*peer
)
3859 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3861 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3862 #undef CLEAR_QUEUE_NAME_LEN
3864 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3865 peer
->clear_node_queue
->spec
.hold
= 10;
3866 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3867 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3868 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3869 peer
->clear_node_queue
->spec
.max_retries
= 0;
3871 /* we only 'lock' this peer reference when the queue is actually active
3873 peer
->clear_node_queue
->spec
.data
= peer
;
3876 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3877 struct bgp_table
*table
)
3879 struct bgp_node
*rn
;
3880 int force
= bm
->process_main_queue
? 0 : 1;
3883 table
= peer
->bgp
->rib
[afi
][safi
];
3885 /* If still no table => afi/safi isn't configured at all or smth. */
3889 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3890 struct bgp_path_info
*ri
, *next
;
3891 struct bgp_adj_in
*ain
;
3892 struct bgp_adj_in
*ain_next
;
3894 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3895 * queued for every clearing peer, regardless of whether it is
3896 * relevant to the peer at hand.
3898 * Overview: There are 3 different indices which need to be
3899 * scrubbed, potentially, when a peer is removed:
3901 * 1 peer's routes visible via the RIB (ie accepted routes)
3902 * 2 peer's routes visible by the (optional) peer's adj-in index
3903 * 3 other routes visible by the peer's adj-out index
3905 * 3 there is no hurry in scrubbing, once the struct peer is
3906 * removed from bgp->peer, we could just GC such deleted peer's
3907 * adj-outs at our leisure.
3909 * 1 and 2 must be 'scrubbed' in some way, at least made
3910 * invisible via RIB index before peer session is allowed to be
3911 * brought back up. So one needs to know when such a 'search' is
3916 * - there'd be a single global queue or a single RIB walker
3917 * - rather than tracking which route_nodes still need to be
3918 * examined on a peer basis, we'd track which peers still
3921 * Given that our per-peer prefix-counts now should be reliable,
3922 * this may actually be achievable. It doesn't seem to be a huge
3923 * problem at this time,
3925 * It is possible that we have multiple paths for a prefix from
3927 * if that peer is using AddPath.
3931 ain_next
= ain
->next
;
3933 if (ain
->peer
== peer
) {
3934 bgp_adj_in_remove(rn
, ain
);
3935 bgp_unlock_node(rn
);
3941 for (ri
= rn
->info
; ri
; ri
= next
) {
3943 if (ri
->peer
!= peer
)
3947 bgp_info_reap(rn
, ri
);
3949 struct bgp_clear_node_queue
*cnq
;
3951 /* both unlocked in bgp_clear_node_queue_del */
3952 bgp_table_lock(bgp_node_table(rn
));
3955 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3956 sizeof(struct bgp_clear_node_queue
));
3958 work_queue_add(peer
->clear_node_queue
, cnq
);
3966 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3968 struct bgp_node
*rn
;
3969 struct bgp_table
*table
;
3971 if (peer
->clear_node_queue
== NULL
)
3972 bgp_clear_node_queue_init(peer
);
3974 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3975 * Idle until it receives a Clearing_Completed event. This protects
3976 * against peers which flap faster than we can we clear, which could
3979 * a) race with routes from the new session being installed before
3980 * clear_route_node visits the node (to delete the route of that
3982 * b) resource exhaustion, clear_route_node likely leads to an entry
3983 * on the process_main queue. Fast-flapping could cause that queue
3987 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3988 * the unlock will happen upon work-queue completion; other wise, the
3989 * unlock happens at the end of this function.
3991 if (!peer
->clear_node_queue
->thread
)
3994 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3995 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3997 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3998 rn
= bgp_route_next(rn
))
3999 if ((table
= rn
->info
) != NULL
)
4000 bgp_clear_route_table(peer
, afi
, safi
, table
);
4002 /* unlock if no nodes got added to the clear-node-queue. */
4003 if (!peer
->clear_node_queue
->thread
)
4007 void bgp_clear_route_all(struct peer
*peer
)
4012 FOREACH_AFI_SAFI (afi
, safi
)
4013 bgp_clear_route(peer
, afi
, safi
);
4016 rfapiProcessPeerDown(peer
);
4020 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4022 struct bgp_table
*table
;
4023 struct bgp_node
*rn
;
4024 struct bgp_adj_in
*ain
;
4025 struct bgp_adj_in
*ain_next
;
4027 table
= peer
->bgp
->rib
[afi
][safi
];
4029 /* It is possible that we have multiple paths for a prefix from a peer
4030 * if that peer is using AddPath.
4032 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4036 ain_next
= ain
->next
;
4038 if (ain
->peer
== peer
) {
4039 bgp_adj_in_remove(rn
, ain
);
4040 bgp_unlock_node(rn
);
4048 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4050 struct bgp_node
*rn
;
4051 struct bgp_path_info
*ri
;
4052 struct bgp_table
*table
;
4054 if (safi
== SAFI_MPLS_VPN
) {
4055 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4056 rn
= bgp_route_next(rn
)) {
4057 struct bgp_node
*rm
;
4059 /* look for neighbor in tables */
4060 if ((table
= rn
->info
) == NULL
)
4063 for (rm
= bgp_table_top(table
); rm
;
4064 rm
= bgp_route_next(rm
))
4065 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4066 if (ri
->peer
!= peer
)
4068 if (!CHECK_FLAG(ri
->flags
,
4072 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4077 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4078 rn
= bgp_route_next(rn
))
4079 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4080 if (ri
->peer
!= peer
)
4082 if (!CHECK_FLAG(ri
->flags
, BGP_PATH_STALE
))
4084 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4090 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4093 struct bgp_node
*rn
;
4094 struct bgp_path_info
*ri
;
4095 struct bgp_path_info
*next
;
4097 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4098 for (ri
= rn
->info
; ri
; ri
= next
) {
4100 if (CHECK_FLAG(ri
->flags
, BGP_PATH_SELECTED
)
4101 && ri
->type
== ZEBRA_ROUTE_BGP
4102 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4103 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4104 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4106 if (bgp_fibupd_safi(safi
))
4107 bgp_zebra_withdraw(&rn
->p
, ri
,
4109 bgp_info_reap(rn
, ri
);
4114 /* Delete all kernel routes. */
4115 void bgp_cleanup_routes(struct bgp
*bgp
)
4118 struct bgp_node
*rn
;
4120 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4121 if (afi
== AFI_L2VPN
)
4123 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4126 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4128 if (afi
!= AFI_L2VPN
) {
4130 safi
= SAFI_MPLS_VPN
;
4131 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4132 rn
= bgp_route_next(rn
)) {
4134 bgp_cleanup_table(bgp
,
4135 (struct bgp_table
*)(rn
->info
),
4137 bgp_table_finish((struct bgp_table
**)&(
4140 bgp_unlock_node(rn
);
4144 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4145 rn
= bgp_route_next(rn
)) {
4147 bgp_cleanup_table(bgp
,
4148 (struct bgp_table
*)(rn
->info
),
4150 bgp_table_finish((struct bgp_table
**)&(
4153 bgp_unlock_node(rn
);
4158 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4159 rn
= bgp_route_next(rn
)) {
4161 bgp_cleanup_table(bgp
,
4162 (struct bgp_table
*)(rn
->info
),
4164 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4166 bgp_unlock_node(rn
);
4171 void bgp_reset(void)
4174 bgp_zclient_reset();
4175 access_list_reset();
4176 prefix_list_reset();
4179 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4181 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4182 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4183 PEER_CAP_ADDPATH_AF_TX_RCV
));
4186 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4188 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4189 struct bgp_nlri
*packet
)
4198 int addpath_encoded
;
4199 uint32_t addpath_id
;
4202 lim
= pnt
+ packet
->length
;
4204 safi
= packet
->safi
;
4206 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4208 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4209 syntactic validity. If the field is syntactically incorrect,
4210 then the Error Subcode is set to Invalid Network Field. */
4211 for (; pnt
< lim
; pnt
+= psize
) {
4212 /* Clear prefix structure. */
4213 memset(&p
, 0, sizeof(struct prefix
));
4215 if (addpath_encoded
) {
4217 /* When packet overflow occurs return immediately. */
4218 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4221 addpath_id
= ntohl(*((uint32_t *)pnt
));
4222 pnt
+= BGP_ADDPATH_ID_LEN
;
4225 /* Fetch prefix length. */
4226 p
.prefixlen
= *pnt
++;
4227 /* afi/safi validity already verified by caller,
4228 * bgp_update_receive */
4229 p
.family
= afi2family(afi
);
4231 /* Prefix length check. */
4232 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4235 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4236 peer
->host
, p
.prefixlen
, packet
->afi
);
4240 /* Packet size overflow check. */
4241 psize
= PSIZE(p
.prefixlen
);
4243 /* When packet overflow occur return immediately. */
4244 if (pnt
+ psize
> lim
) {
4247 "%s [Error] Update packet error (prefix length %d overflows packet)",
4248 peer
->host
, p
.prefixlen
);
4252 /* Defensive coding, double-check the psize fits in a struct
4254 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4257 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4258 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4262 /* Fetch prefix from NLRI packet. */
4263 memcpy(p
.u
.val
, pnt
, psize
);
4265 /* Check address. */
4266 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4267 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4268 /* From RFC4271 Section 6.3:
4270 * If a prefix in the NLRI field is semantically
4272 * (e.g., an unexpected multicast IP address),
4274 * be logged locally, and the prefix SHOULD be
4279 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4280 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4285 /* Check address. */
4286 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4287 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4292 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4294 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4299 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4304 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4306 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4313 /* Normal process. */
4315 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4316 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4317 NULL
, NULL
, 0, 0, NULL
);
4319 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4320 safi
, ZEBRA_ROUTE_BGP
,
4321 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4324 /* Address family configuration mismatch or maximum-prefix count
4330 /* Packet length consistency check. */
4334 "%s [Error] Update packet error (prefix length mismatch with total length)",
4342 static struct bgp_static
*bgp_static_new(void)
4344 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4347 static void bgp_static_free(struct bgp_static
*bgp_static
)
4349 if (bgp_static
->rmap
.name
)
4350 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4351 if (bgp_static
->eth_s_id
)
4352 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4353 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4356 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4357 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4359 struct bgp_node
*rn
;
4360 struct bgp_path_info
*ri
;
4361 struct bgp_path_info
*new;
4362 struct bgp_path_info info
;
4364 struct attr
*attr_new
;
4367 int vnc_implicit_withdraw
= 0;
4374 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4376 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4378 attr
.nexthop
= bgp_static
->igpnexthop
;
4379 attr
.med
= bgp_static
->igpmetric
;
4380 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4382 if (bgp_static
->atomic
)
4383 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4385 /* Store label index, if required. */
4386 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4387 attr
.label_index
= bgp_static
->label_index
;
4388 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4391 /* Apply route-map. */
4392 if (bgp_static
->rmap
.name
) {
4393 struct attr attr_tmp
= attr
;
4395 memset(&info
, 0, sizeof(struct bgp_path_info
));
4396 info
.peer
= bgp
->peer_self
;
4397 info
.attr
= &attr_tmp
;
4399 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4401 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4403 bgp
->peer_self
->rmap_type
= 0;
4405 if (ret
== RMAP_DENYMATCH
) {
4406 /* Free uninterned attribute. */
4407 bgp_attr_flush(&attr_tmp
);
4409 /* Unintern original. */
4410 aspath_unintern(&attr
.aspath
);
4411 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4415 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4416 bgp_attr_add_gshut_community(&attr_tmp
);
4418 attr_new
= bgp_attr_intern(&attr_tmp
);
4421 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4422 bgp_attr_add_gshut_community(&attr
);
4424 attr_new
= bgp_attr_intern(&attr
);
4427 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4428 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4429 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4433 if (attrhash_cmp(ri
->attr
, attr_new
)
4434 && !CHECK_FLAG(ri
->flags
, BGP_PATH_REMOVED
)
4435 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4436 bgp_unlock_node(rn
);
4437 bgp_attr_unintern(&attr_new
);
4438 aspath_unintern(&attr
.aspath
);
4441 /* The attribute is changed. */
4442 bgp_info_set_flag(rn
, ri
, BGP_PATH_ATTR_CHANGED
);
4444 /* Rewrite BGP route information. */
4445 if (CHECK_FLAG(ri
->flags
, BGP_PATH_REMOVED
))
4446 bgp_info_restore(rn
, ri
);
4448 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4450 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4451 && (safi
== SAFI_UNICAST
)) {
4452 if (CHECK_FLAG(ri
->flags
, BGP_PATH_SELECTED
)) {
4454 * Implicit withdraw case.
4455 * We have to do this before ri is
4458 ++vnc_implicit_withdraw
;
4459 vnc_import_bgp_del_route(bgp
, p
, ri
);
4460 vnc_import_bgp_exterior_del_route(
4465 bgp_attr_unintern(&ri
->attr
);
4466 ri
->attr
= attr_new
;
4467 ri
->uptime
= bgp_clock();
4469 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4470 && (safi
== SAFI_UNICAST
)) {
4471 if (vnc_implicit_withdraw
) {
4472 vnc_import_bgp_add_route(bgp
, p
, ri
);
4473 vnc_import_bgp_exterior_add_route(
4479 /* Nexthop reachability check. */
4480 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4481 && (safi
== SAFI_UNICAST
4482 || safi
== SAFI_LABELED_UNICAST
)) {
4484 struct bgp
*bgp_nexthop
= bgp
;
4486 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4487 bgp_nexthop
= ri
->extra
->bgp_orig
;
4489 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4491 bgp_info_set_flag(rn
, ri
,
4494 if (BGP_DEBUG(nht
, NHT
)) {
4495 char buf1
[INET6_ADDRSTRLEN
];
4496 inet_ntop(p
->family
,
4500 "%s(%s): Route not in table, not advertising",
4501 __FUNCTION__
, buf1
);
4503 bgp_info_unset_flag(rn
, ri
,
4507 /* Delete the NHT structure if any, if we're
4509 * enabling/disabling import check. We
4510 * deregister the route
4511 * from NHT to avoid overloading NHT and the
4512 * process interaction
4514 bgp_unlink_nexthop(ri
);
4515 bgp_info_set_flag(rn
, ri
, BGP_PATH_VALID
);
4517 /* Process change. */
4518 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4519 bgp_process(bgp
, rn
, afi
, safi
);
4521 if (SAFI_UNICAST
== safi
4522 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4524 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4525 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4529 bgp_unlock_node(rn
);
4530 aspath_unintern(&attr
.aspath
);
4535 /* Make new BGP info. */
4536 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4538 /* Nexthop reachability check. */
4539 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4540 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4541 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4542 bgp_info_set_flag(rn
, new, BGP_PATH_VALID
);
4544 if (BGP_DEBUG(nht
, NHT
)) {
4545 char buf1
[INET6_ADDRSTRLEN
];
4546 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4549 "%s(%s): Route not in table, not advertising",
4550 __FUNCTION__
, buf1
);
4552 bgp_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4555 /* Delete the NHT structure if any, if we're toggling between
4556 * enabling/disabling import check. We deregister the route
4557 * from NHT to avoid overloading NHT and the process interaction
4559 bgp_unlink_nexthop(new);
4561 bgp_info_set_flag(rn
, new, BGP_PATH_VALID
);
4564 /* Aggregate address increment. */
4565 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4567 /* Register new BGP information. */
4568 bgp_info_add(rn
, new);
4570 /* route_node_get lock */
4571 bgp_unlock_node(rn
);
4573 /* Process change. */
4574 bgp_process(bgp
, rn
, afi
, safi
);
4576 if (SAFI_UNICAST
== safi
4577 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4578 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4579 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4582 /* Unintern original. */
4583 aspath_unintern(&attr
.aspath
);
4586 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4589 struct bgp_node
*rn
;
4590 struct bgp_path_info
*ri
;
4592 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4594 /* Check selected route and self inserted route. */
4595 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4596 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4597 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4600 /* Withdraw static BGP route from routing table. */
4602 if (SAFI_UNICAST
== safi
4603 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4604 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4605 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4607 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4608 bgp_unlink_nexthop(ri
);
4609 bgp_info_delete(rn
, ri
);
4610 bgp_process(bgp
, rn
, afi
, safi
);
4613 /* Unlock bgp_node_lookup. */
4614 bgp_unlock_node(rn
);
4618 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4620 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4621 afi_t afi
, safi_t safi
,
4622 struct prefix_rd
*prd
)
4624 struct bgp_node
*rn
;
4625 struct bgp_path_info
*ri
;
4627 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4629 /* Check selected route and self inserted route. */
4630 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4631 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4632 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4635 /* Withdraw static BGP route from routing table. */
4638 rfapiProcessWithdraw(
4639 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4640 1); /* Kill, since it is an administrative change */
4642 if (SAFI_MPLS_VPN
== safi
4643 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4644 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4646 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4647 bgp_info_delete(rn
, ri
);
4648 bgp_process(bgp
, rn
, afi
, safi
);
4651 /* Unlock bgp_node_lookup. */
4652 bgp_unlock_node(rn
);
4655 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4656 struct bgp_static
*bgp_static
, afi_t afi
,
4659 struct bgp_node
*rn
;
4660 struct bgp_path_info
*new;
4661 struct attr
*attr_new
;
4662 struct attr attr
= {0};
4663 struct bgp_path_info
*ri
;
4665 mpls_label_t label
= 0;
4667 uint32_t num_labels
= 0;
4672 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4674 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4677 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4679 attr
.nexthop
= bgp_static
->igpnexthop
;
4680 attr
.med
= bgp_static
->igpmetric
;
4681 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4683 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4684 || (safi
== SAFI_ENCAP
)) {
4685 if (afi
== AFI_IP
) {
4686 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4687 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4690 if (afi
== AFI_L2VPN
) {
4691 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4693 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4694 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4695 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4696 sizeof(struct in6_addr
));
4697 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4698 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4699 struct bgp_encap_type_vxlan bet
;
4700 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4701 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4702 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4704 if (bgp_static
->router_mac
) {
4705 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4708 /* Apply route-map. */
4709 if (bgp_static
->rmap
.name
) {
4710 struct attr attr_tmp
= attr
;
4711 struct bgp_path_info info
;
4714 info
.peer
= bgp
->peer_self
;
4715 info
.attr
= &attr_tmp
;
4717 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4719 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4721 bgp
->peer_self
->rmap_type
= 0;
4723 if (ret
== RMAP_DENYMATCH
) {
4724 /* Free uninterned attribute. */
4725 bgp_attr_flush(&attr_tmp
);
4727 /* Unintern original. */
4728 aspath_unintern(&attr
.aspath
);
4729 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4734 attr_new
= bgp_attr_intern(&attr_tmp
);
4736 attr_new
= bgp_attr_intern(&attr
);
4739 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4740 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4741 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4745 memset(&add
, 0, sizeof(union gw_addr
));
4746 if (attrhash_cmp(ri
->attr
, attr_new
)
4747 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4748 && !CHECK_FLAG(ri
->flags
, BGP_PATH_REMOVED
)) {
4749 bgp_unlock_node(rn
);
4750 bgp_attr_unintern(&attr_new
);
4751 aspath_unintern(&attr
.aspath
);
4754 /* The attribute is changed. */
4755 bgp_info_set_flag(rn
, ri
, BGP_PATH_ATTR_CHANGED
);
4757 /* Rewrite BGP route information. */
4758 if (CHECK_FLAG(ri
->flags
, BGP_PATH_REMOVED
))
4759 bgp_info_restore(rn
, ri
);
4761 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4762 bgp_attr_unintern(&ri
->attr
);
4763 ri
->attr
= attr_new
;
4764 ri
->uptime
= bgp_clock();
4767 label
= decode_label(&ri
->extra
->label
[0]);
4770 /* Process change. */
4771 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4772 bgp_process(bgp
, rn
, afi
, safi
);
4774 if (SAFI_MPLS_VPN
== safi
4775 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4776 vpn_leak_to_vrf_update(bgp
, ri
);
4779 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4780 ri
->attr
, afi
, safi
, ri
->type
,
4781 ri
->sub_type
, &label
);
4783 bgp_unlock_node(rn
);
4784 aspath_unintern(&attr
.aspath
);
4790 /* Make new BGP info. */
4791 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4793 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4794 new->extra
= bgp_info_extra_new();
4796 new->extra
->label
[0] = bgp_static
->label
;
4797 new->extra
->num_labels
= num_labels
;
4800 label
= decode_label(&bgp_static
->label
);
4803 /* Aggregate address increment. */
4804 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4806 /* Register new BGP information. */
4807 bgp_info_add(rn
, new);
4808 /* route_node_get lock */
4809 bgp_unlock_node(rn
);
4811 /* Process change. */
4812 bgp_process(bgp
, rn
, afi
, safi
);
4814 if (SAFI_MPLS_VPN
== safi
4815 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4816 vpn_leak_to_vrf_update(bgp
, new);
4819 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4820 safi
, new->type
, new->sub_type
, &label
);
4823 /* Unintern original. */
4824 aspath_unintern(&attr
.aspath
);
4827 /* Configure static BGP network. When user don't run zebra, static
4828 route should be installed as valid. */
4829 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4830 const char *ip_str
, afi_t afi
, safi_t safi
,
4831 const char *rmap
, int backdoor
, uint32_t label_index
)
4833 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4836 struct bgp_static
*bgp_static
;
4837 struct bgp_node
*rn
;
4838 uint8_t need_update
= 0;
4840 /* Convert IP prefix string to struct prefix. */
4841 ret
= str2prefix(ip_str
, &p
);
4843 vty_out(vty
, "%% Malformed prefix\n");
4844 return CMD_WARNING_CONFIG_FAILED
;
4846 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4847 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4848 return CMD_WARNING_CONFIG_FAILED
;
4855 /* Set BGP static route configuration. */
4856 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4859 vty_out(vty
, "%% Can't find static route specified\n");
4860 return CMD_WARNING_CONFIG_FAILED
;
4863 bgp_static
= bgp_static_get_node_info(rn
);
4865 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4866 && (label_index
!= bgp_static
->label_index
)) {
4868 "%% label-index doesn't match static route\n");
4869 return CMD_WARNING_CONFIG_FAILED
;
4872 if ((rmap
&& bgp_static
->rmap
.name
)
4873 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4875 "%% route-map name doesn't match static route\n");
4876 return CMD_WARNING_CONFIG_FAILED
;
4879 /* Update BGP RIB. */
4880 if (!bgp_static
->backdoor
)
4881 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4883 /* Clear configuration. */
4884 bgp_static_free(bgp_static
);
4885 bgp_static_set_node_info(rn
, NULL
);
4886 bgp_unlock_node(rn
);
4887 bgp_unlock_node(rn
);
4890 /* Set BGP static route configuration. */
4891 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4893 bgp_static
= bgp_static_get_node_info(rn
);
4895 /* Configuration change. */
4896 /* Label index cannot be changed. */
4897 if (bgp_static
->label_index
!= label_index
) {
4898 vty_out(vty
, "%% cannot change label-index\n");
4899 return CMD_WARNING_CONFIG_FAILED
;
4902 /* Check previous routes are installed into BGP. */
4903 if (bgp_static
->valid
4904 && bgp_static
->backdoor
!= backdoor
)
4907 bgp_static
->backdoor
= backdoor
;
4910 if (bgp_static
->rmap
.name
)
4911 XFREE(MTYPE_ROUTE_MAP_NAME
,
4912 bgp_static
->rmap
.name
);
4913 bgp_static
->rmap
.name
=
4914 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4915 bgp_static
->rmap
.map
=
4916 route_map_lookup_by_name(rmap
);
4918 if (bgp_static
->rmap
.name
)
4919 XFREE(MTYPE_ROUTE_MAP_NAME
,
4920 bgp_static
->rmap
.name
);
4921 bgp_static
->rmap
.name
= NULL
;
4922 bgp_static
->rmap
.map
= NULL
;
4923 bgp_static
->valid
= 0;
4925 bgp_unlock_node(rn
);
4927 /* New configuration. */
4928 bgp_static
= bgp_static_new();
4929 bgp_static
->backdoor
= backdoor
;
4930 bgp_static
->valid
= 0;
4931 bgp_static
->igpmetric
= 0;
4932 bgp_static
->igpnexthop
.s_addr
= 0;
4933 bgp_static
->label_index
= label_index
;
4936 if (bgp_static
->rmap
.name
)
4937 XFREE(MTYPE_ROUTE_MAP_NAME
,
4938 bgp_static
->rmap
.name
);
4939 bgp_static
->rmap
.name
=
4940 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4941 bgp_static
->rmap
.map
=
4942 route_map_lookup_by_name(rmap
);
4944 bgp_static_set_node_info(rn
, bgp_static
);
4947 bgp_static
->valid
= 1;
4949 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4951 if (!bgp_static
->backdoor
)
4952 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4958 void bgp_static_add(struct bgp
*bgp
)
4962 struct bgp_node
*rn
;
4963 struct bgp_node
*rm
;
4964 struct bgp_table
*table
;
4965 struct bgp_static
*bgp_static
;
4967 FOREACH_AFI_SAFI (afi
, safi
)
4968 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4969 rn
= bgp_route_next(rn
)) {
4970 if (rn
->info
== NULL
)
4973 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4974 || (safi
== SAFI_EVPN
)) {
4977 for (rm
= bgp_table_top(table
); rm
;
4978 rm
= bgp_route_next(rm
)) {
4980 bgp_static_get_node_info(rm
);
4981 bgp_static_update_safi(bgp
, &rm
->p
,
4986 bgp_static_update(bgp
, &rn
->p
,
4987 bgp_static_get_node_info(rn
),
4993 /* Called from bgp_delete(). Delete all static routes from the BGP
4995 void bgp_static_delete(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 FOREACH_AFI_SAFI (afi
, safi
)
5005 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5006 rn
= bgp_route_next(rn
)) {
5007 if (rn
->info
== NULL
)
5010 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5011 || (safi
== SAFI_EVPN
)) {
5014 for (rm
= bgp_table_top(table
); rm
;
5015 rm
= bgp_route_next(rm
)) {
5017 bgp_static_get_node_info(rm
);
5018 bgp_static_withdraw_safi(
5019 bgp
, &rm
->p
, AFI_IP
, safi
,
5020 (struct prefix_rd
*)&rn
->p
);
5021 bgp_static_free(bgp_static
);
5022 bgp_static_set_node_info(rn
, NULL
);
5023 bgp_unlock_node(rn
);
5026 bgp_static
= bgp_static_get_node_info(rn
);
5027 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5028 bgp_static_free(bgp_static
);
5029 bgp_static_set_node_info(rn
, NULL
);
5030 bgp_unlock_node(rn
);
5035 void bgp_static_redo_import_check(struct bgp
*bgp
)
5039 struct bgp_node
*rn
;
5040 struct bgp_node
*rm
;
5041 struct bgp_table
*table
;
5042 struct bgp_static
*bgp_static
;
5044 /* Use this flag to force reprocessing of the route */
5045 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5046 FOREACH_AFI_SAFI (afi
, safi
) {
5047 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5048 rn
= bgp_route_next(rn
)) {
5049 if (rn
->info
== NULL
)
5052 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5053 || (safi
== SAFI_EVPN
)) {
5056 for (rm
= bgp_table_top(table
); rm
;
5057 rm
= bgp_route_next(rm
)) {
5059 bgp_static_get_node_info(rm
);
5060 bgp_static_update_safi(bgp
, &rm
->p
,
5065 bgp_static
= bgp_static_get_node_info(rn
);
5066 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5071 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5074 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5077 struct bgp_table
*table
;
5078 struct bgp_node
*rn
;
5079 struct bgp_path_info
*ri
;
5081 table
= bgp
->rib
[afi
][safi
];
5082 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5083 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5084 if (ri
->peer
== bgp
->peer_self
5085 && ((ri
->type
== ZEBRA_ROUTE_BGP
5086 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5087 || (ri
->type
!= ZEBRA_ROUTE_BGP
5089 == BGP_ROUTE_REDISTRIBUTE
))) {
5090 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5092 bgp_unlink_nexthop(ri
);
5093 bgp_info_delete(rn
, ri
);
5094 bgp_process(bgp
, rn
, afi
, safi
);
5101 * Purge all networks and redistributed routes from routing table.
5102 * Invoked upon the instance going down.
5104 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5109 FOREACH_AFI_SAFI (afi
, safi
)
5110 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5115 * Currently this is used to set static routes for VPN and ENCAP.
5116 * I think it can probably be factored with bgp_static_set.
5118 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5119 const char *ip_str
, const char *rd_str
,
5120 const char *label_str
, const char *rmap_str
,
5121 int evpn_type
, const char *esi
, const char *gwip
,
5122 const char *ethtag
, const char *routermac
)
5124 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5127 struct prefix_rd prd
;
5128 struct bgp_node
*prn
;
5129 struct bgp_node
*rn
;
5130 struct bgp_table
*table
;
5131 struct bgp_static
*bgp_static
;
5132 mpls_label_t label
= MPLS_INVALID_LABEL
;
5133 struct prefix gw_ip
;
5135 /* validate ip prefix */
5136 ret
= str2prefix(ip_str
, &p
);
5138 vty_out(vty
, "%% Malformed prefix\n");
5139 return CMD_WARNING_CONFIG_FAILED
;
5142 if ((afi
== AFI_L2VPN
)
5143 && (bgp_build_evpn_prefix(evpn_type
,
5144 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5145 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5146 return CMD_WARNING_CONFIG_FAILED
;
5149 ret
= str2prefix_rd(rd_str
, &prd
);
5151 vty_out(vty
, "%% Malformed rd\n");
5152 return CMD_WARNING_CONFIG_FAILED
;
5156 unsigned long label_val
;
5157 label_val
= strtoul(label_str
, NULL
, 10);
5158 encode_label(label_val
, &label
);
5161 if (safi
== SAFI_EVPN
) {
5162 if (esi
&& str2esi(esi
, NULL
) == 0) {
5163 vty_out(vty
, "%% Malformed ESI\n");
5164 return CMD_WARNING_CONFIG_FAILED
;
5166 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5167 vty_out(vty
, "%% Malformed Router MAC\n");
5168 return CMD_WARNING_CONFIG_FAILED
;
5171 memset(&gw_ip
, 0, sizeof(struct prefix
));
5172 ret
= str2prefix(gwip
, &gw_ip
);
5174 vty_out(vty
, "%% Malformed GatewayIp\n");
5175 return CMD_WARNING_CONFIG_FAILED
;
5177 if ((gw_ip
.family
== AF_INET
5178 && is_evpn_prefix_ipaddr_v6(
5179 (struct prefix_evpn
*)&p
))
5180 || (gw_ip
.family
== AF_INET6
5181 && is_evpn_prefix_ipaddr_v4(
5182 (struct prefix_evpn
*)&p
))) {
5184 "%% GatewayIp family differs with IP prefix\n");
5185 return CMD_WARNING_CONFIG_FAILED
;
5189 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5190 if (prn
->info
== NULL
)
5191 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5193 bgp_unlock_node(prn
);
5196 rn
= bgp_node_get(table
, &p
);
5199 vty_out(vty
, "%% Same network configuration exists\n");
5200 bgp_unlock_node(rn
);
5202 /* New configuration. */
5203 bgp_static
= bgp_static_new();
5204 bgp_static
->backdoor
= 0;
5205 bgp_static
->valid
= 0;
5206 bgp_static
->igpmetric
= 0;
5207 bgp_static
->igpnexthop
.s_addr
= 0;
5208 bgp_static
->label
= label
;
5209 bgp_static
->prd
= prd
;
5212 if (bgp_static
->rmap
.name
)
5213 XFREE(MTYPE_ROUTE_MAP_NAME
,
5214 bgp_static
->rmap
.name
);
5215 bgp_static
->rmap
.name
=
5216 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5217 bgp_static
->rmap
.map
=
5218 route_map_lookup_by_name(rmap_str
);
5221 if (safi
== SAFI_EVPN
) {
5223 bgp_static
->eth_s_id
=
5225 sizeof(struct eth_segment_id
));
5226 str2esi(esi
, bgp_static
->eth_s_id
);
5229 bgp_static
->router_mac
=
5230 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5231 (void)prefix_str2mac(routermac
,
5232 bgp_static
->router_mac
);
5235 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5237 bgp_static_set_node_info(rn
, bgp_static
);
5239 bgp_static
->valid
= 1;
5240 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5246 /* Configure static BGP network. */
5247 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5248 const char *ip_str
, const char *rd_str
,
5249 const char *label_str
, int evpn_type
, const char *esi
,
5250 const char *gwip
, const char *ethtag
)
5252 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5255 struct prefix_rd prd
;
5256 struct bgp_node
*prn
;
5257 struct bgp_node
*rn
;
5258 struct bgp_table
*table
;
5259 struct bgp_static
*bgp_static
;
5260 mpls_label_t label
= MPLS_INVALID_LABEL
;
5262 /* Convert IP prefix string to struct prefix. */
5263 ret
= str2prefix(ip_str
, &p
);
5265 vty_out(vty
, "%% Malformed prefix\n");
5266 return CMD_WARNING_CONFIG_FAILED
;
5269 if ((afi
== AFI_L2VPN
)
5270 && (bgp_build_evpn_prefix(evpn_type
,
5271 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5272 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5273 return CMD_WARNING_CONFIG_FAILED
;
5275 ret
= str2prefix_rd(rd_str
, &prd
);
5277 vty_out(vty
, "%% Malformed rd\n");
5278 return CMD_WARNING_CONFIG_FAILED
;
5282 unsigned long label_val
;
5283 label_val
= strtoul(label_str
, NULL
, 10);
5284 encode_label(label_val
, &label
);
5287 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5288 if (prn
->info
== NULL
)
5289 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5291 bgp_unlock_node(prn
);
5294 rn
= bgp_node_lookup(table
, &p
);
5297 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5299 bgp_static
= bgp_static_get_node_info(rn
);
5300 bgp_static_free(bgp_static
);
5301 bgp_static_set_node_info(rn
, NULL
);
5302 bgp_unlock_node(rn
);
5303 bgp_unlock_node(rn
);
5305 vty_out(vty
, "%% Can't find the route\n");
5310 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5311 const char *rmap_name
)
5313 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5314 struct bgp_rmap
*rmap
;
5316 rmap
= &bgp
->table_map
[afi
][safi
];
5319 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5320 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5321 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5324 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5329 if (bgp_fibupd_safi(safi
))
5330 bgp_zebra_announce_table(bgp
, afi
, safi
);
5335 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5336 const char *rmap_name
)
5338 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5339 struct bgp_rmap
*rmap
;
5341 rmap
= &bgp
->table_map
[afi
][safi
];
5343 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5347 if (bgp_fibupd_safi(safi
))
5348 bgp_zebra_announce_table(bgp
, afi
, safi
);
5353 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5356 if (bgp
->table_map
[afi
][safi
].name
) {
5357 vty_out(vty
, " table-map %s\n",
5358 bgp
->table_map
[afi
][safi
].name
);
5362 DEFUN (bgp_table_map
,
5365 "BGP table to RIB route download filter\n"
5366 "Name of the route map\n")
5369 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5370 argv
[idx_word
]->arg
);
5372 DEFUN (no_bgp_table_map
,
5373 no_bgp_table_map_cmd
,
5374 "no table-map WORD",
5376 "BGP table to RIB route download filter\n"
5377 "Name of the route map\n")
5380 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5381 argv
[idx_word
]->arg
);
5387 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5388 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5389 backdoor$backdoor}]",
5391 "Specify a network to announce via BGP\n"
5396 "Route-map to modify the attributes\n"
5397 "Name of the route map\n"
5398 "Label index to associate with the prefix\n"
5399 "Label index value\n"
5400 "Specify a BGP backdoor route\n")
5402 char addr_prefix_str
[BUFSIZ
];
5407 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5410 vty_out(vty
, "%% Inconsistent address and mask\n");
5411 return CMD_WARNING_CONFIG_FAILED
;
5415 return bgp_static_set(
5416 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5417 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5418 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5421 DEFPY(ipv6_bgp_network
,
5422 ipv6_bgp_network_cmd
,
5423 "[no] network X:X::X:X/M$prefix \
5424 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5426 "Specify a network to announce via BGP\n"
5428 "Route-map to modify the attributes\n"
5429 "Name of the route map\n"
5430 "Label index to associate with the prefix\n"
5431 "Label index value\n")
5433 return bgp_static_set(
5434 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5435 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5438 /* Aggreagete address:
5440 advertise-map Set condition to advertise attribute
5441 as-set Generate AS set path information
5442 attribute-map Set attributes of aggregate
5443 route-map Set parameters of aggregate
5444 summary-only Filter more specific routes from updates
5445 suppress-map Conditionally filter more specific routes from updates
5448 struct bgp_aggregate
{
5449 /* Summary-only flag. */
5450 uint8_t summary_only
;
5452 /* AS set generation. */
5455 /* Route-map for aggregated route. */
5456 struct route_map
*map
;
5458 /* Suppress-count. */
5459 unsigned long count
;
5461 /* SAFI configuration. */
5465 static struct bgp_aggregate
*bgp_aggregate_new(void)
5467 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5470 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5472 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5475 static int bgp_aggregate_info_same(struct bgp_path_info
*ri
, uint8_t origin
,
5476 struct aspath
*aspath
,
5477 struct community
*comm
)
5479 static struct aspath
*ae
= NULL
;
5482 ae
= aspath_empty();
5487 if (origin
!= ri
->attr
->origin
)
5490 if (!aspath_cmp(ri
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5493 if (!community_cmp(ri
->attr
->community
, comm
))
5496 if (!CHECK_FLAG(ri
->flags
, BGP_PATH_VALID
))
5502 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5503 struct prefix
*p
, uint8_t origin
,
5504 struct aspath
*aspath
,
5505 struct community
*community
,
5506 uint8_t atomic_aggregate
,
5507 struct bgp_aggregate
*aggregate
)
5509 struct bgp_node
*rn
;
5510 struct bgp_table
*table
;
5511 struct bgp_path_info
*ri
, *new;
5513 table
= bgp
->rib
[afi
][safi
];
5515 rn
= bgp_node_get(table
, p
);
5517 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5518 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5519 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5522 if (aggregate
->count
> 0) {
5524 * If the aggregate information has not changed
5525 * no need to re-install it again.
5527 if (bgp_aggregate_info_same(rn
->info
, origin
, aspath
,
5529 bgp_unlock_node(rn
);
5532 aspath_free(aspath
);
5534 community_free(community
);
5540 * Mark the old as unusable
5543 bgp_info_delete(rn
, ri
);
5546 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5547 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5548 community
, aggregate
->as_set
,
5551 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5553 bgp_info_add(rn
, new);
5554 bgp_process(bgp
, rn
, afi
, safi
);
5556 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5557 if (ri
->peer
== bgp
->peer_self
5558 && ri
->type
== ZEBRA_ROUTE_BGP
5559 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5562 /* Withdraw static BGP route from routing table. */
5564 bgp_info_delete(rn
, ri
);
5565 bgp_process(bgp
, rn
, afi
, safi
);
5569 bgp_unlock_node(rn
);
5572 /* Update an aggregate as routes are added/removed from the BGP table */
5573 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5574 struct bgp_path_info
*rinew
, afi_t afi
,
5575 safi_t safi
, struct bgp_path_info
*del
,
5576 struct bgp_aggregate
*aggregate
)
5578 struct bgp_table
*table
;
5579 struct bgp_node
*top
;
5580 struct bgp_node
*rn
;
5582 struct aspath
*aspath
= NULL
;
5583 struct aspath
*asmerge
= NULL
;
5584 struct community
*community
= NULL
;
5585 struct community
*commerge
= NULL
;
5586 struct bgp_path_info
*ri
;
5587 unsigned long match
= 0;
5588 uint8_t atomic_aggregate
= 0;
5590 /* ORIGIN attribute: If at least one route among routes that are
5591 aggregated has ORIGIN with the value INCOMPLETE, then the
5592 aggregated route must have the ORIGIN attribute with the value
5593 INCOMPLETE. Otherwise, if at least one route among routes that
5594 are aggregated has ORIGIN with the value EGP, then the aggregated
5595 route must have the origin attribute with the value EGP. In all
5596 other case the value of the ORIGIN attribute of the aggregated
5597 route is INTERNAL. */
5598 origin
= BGP_ORIGIN_IGP
;
5600 table
= bgp
->rib
[afi
][safi
];
5602 top
= bgp_node_get(table
, p
);
5603 for (rn
= bgp_node_get(table
, p
); rn
;
5604 rn
= bgp_route_next_until(rn
, top
)) {
5605 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5610 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5611 if (BGP_PATH_HOLDDOWN(ri
))
5614 if (del
&& ri
== del
)
5618 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5619 atomic_aggregate
= 1;
5621 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5625 * summary-only aggregate route suppress
5626 * aggregated route announcements.
5628 if (aggregate
->summary_only
) {
5629 (bgp_info_extra_get(ri
))->suppress
++;
5630 bgp_info_set_flag(rn
, ri
,
5631 BGP_PATH_ATTR_CHANGED
);
5638 * If at least one route among routes that are
5639 * aggregated has ORIGIN with the value INCOMPLETE,
5640 * then the aggregated route MUST have the ORIGIN
5641 * attribute with the value INCOMPLETE. Otherwise, if
5642 * at least one route among routes that are aggregated
5643 * has ORIGIN with the value EGP, then the aggregated
5644 * route MUST have the ORIGIN attribute with the value
5647 if (origin
< ri
->attr
->origin
)
5648 origin
= ri
->attr
->origin
;
5650 if (!aggregate
->as_set
)
5654 * as-set aggregate route generate origin, as path,
5655 * and community aggregation.
5658 asmerge
= aspath_aggregate(aspath
,
5660 aspath_free(aspath
);
5663 aspath
= aspath_dup(ri
->attr
->aspath
);
5665 if (!ri
->attr
->community
)
5669 commerge
= community_merge(community
,
5670 ri
->attr
->community
);
5671 community
= community_uniq_sort(commerge
);
5672 community_free(commerge
);
5674 community
= community_dup(ri
->attr
->community
);
5677 bgp_process(bgp
, rn
, afi
, safi
);
5679 bgp_unlock_node(top
);
5684 if (aggregate
->summary_only
)
5685 (bgp_info_extra_get(rinew
))->suppress
++;
5687 if (origin
< rinew
->attr
->origin
)
5688 origin
= rinew
->attr
->origin
;
5690 if (aggregate
->as_set
) {
5692 asmerge
= aspath_aggregate(aspath
,
5693 rinew
->attr
->aspath
);
5694 aspath_free(aspath
);
5697 aspath
= aspath_dup(rinew
->attr
->aspath
);
5699 if (rinew
->attr
->community
) {
5701 commerge
= community_merge(
5703 rinew
->attr
->community
);
5705 community_uniq_sort(commerge
);
5706 community_free(commerge
);
5708 community
= community_dup(
5709 rinew
->attr
->community
);
5714 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5715 atomic_aggregate
, aggregate
);
5717 if (aggregate
->count
== 0) {
5719 aspath_free(aspath
);
5721 community_free(community
);
5725 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5726 safi_t safi
, struct bgp_aggregate
*aggregate
)
5728 struct bgp_table
*table
;
5729 struct bgp_node
*top
;
5730 struct bgp_node
*rn
;
5731 struct bgp_path_info
*ri
;
5732 unsigned long match
;
5734 table
= bgp
->rib
[afi
][safi
];
5736 /* If routes exists below this node, generate aggregate routes. */
5737 top
= bgp_node_get(table
, p
);
5738 for (rn
= bgp_node_get(table
, p
); rn
;
5739 rn
= bgp_route_next_until(rn
, top
)) {
5740 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5744 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5745 if (BGP_PATH_HOLDDOWN(ri
))
5748 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5751 if (aggregate
->summary_only
&& ri
->extra
) {
5752 ri
->extra
->suppress
--;
5754 if (ri
->extra
->suppress
== 0) {
5756 rn
, ri
, BGP_PATH_ATTR_CHANGED
);
5763 /* If this node was suppressed, process the change. */
5765 bgp_process(bgp
, rn
, afi
, safi
);
5767 bgp_unlock_node(top
);
5770 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5771 struct bgp_path_info
*ri
, afi_t afi
, safi_t safi
)
5773 struct bgp_node
*child
;
5774 struct bgp_node
*rn
;
5775 struct bgp_aggregate
*aggregate
;
5776 struct bgp_table
*table
;
5778 table
= bgp
->aggregate
[afi
][safi
];
5780 /* No aggregates configured. */
5781 if (bgp_table_top_nolock(table
) == NULL
)
5784 if (p
->prefixlen
== 0)
5787 if (BGP_PATH_HOLDDOWN(ri
))
5790 child
= bgp_node_get(table
, p
);
5792 /* Aggregate address configuration check. */
5793 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5794 aggregate
= bgp_aggregate_get_node_info(rn
);
5795 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5796 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5797 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5801 bgp_unlock_node(child
);
5804 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5805 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
5807 struct bgp_node
*child
;
5808 struct bgp_node
*rn
;
5809 struct bgp_aggregate
*aggregate
;
5810 struct bgp_table
*table
;
5812 table
= bgp
->aggregate
[afi
][safi
];
5814 /* No aggregates configured. */
5815 if (bgp_table_top_nolock(table
) == NULL
)
5818 if (p
->prefixlen
== 0)
5821 child
= bgp_node_get(table
, p
);
5823 /* Aggregate address configuration check. */
5824 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5825 aggregate
= bgp_aggregate_get_node_info(rn
);
5826 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5827 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5828 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5832 bgp_unlock_node(child
);
5835 /* Aggregate route attribute. */
5836 #define AGGREGATE_SUMMARY_ONLY 1
5837 #define AGGREGATE_AS_SET 1
5839 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5840 afi_t afi
, safi_t safi
)
5842 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5845 struct bgp_node
*rn
;
5846 struct bgp_aggregate
*aggregate
;
5848 /* Convert string to prefix structure. */
5849 ret
= str2prefix(prefix_str
, &p
);
5851 vty_out(vty
, "Malformed prefix\n");
5852 return CMD_WARNING_CONFIG_FAILED
;
5856 /* Old configuration check. */
5857 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5860 "%% There is no aggregate-address configuration.\n");
5861 return CMD_WARNING_CONFIG_FAILED
;
5864 aggregate
= bgp_aggregate_get_node_info(rn
);
5865 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5866 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
, 0, aggregate
);
5868 /* Unlock aggregate address configuration. */
5869 bgp_aggregate_set_node_info(rn
, NULL
);
5870 bgp_aggregate_free(aggregate
);
5871 bgp_unlock_node(rn
);
5872 bgp_unlock_node(rn
);
5877 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5878 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5880 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5883 struct bgp_node
*rn
;
5884 struct bgp_aggregate
*aggregate
;
5886 /* Convert string to prefix structure. */
5887 ret
= str2prefix(prefix_str
, &p
);
5889 vty_out(vty
, "Malformed prefix\n");
5890 return CMD_WARNING_CONFIG_FAILED
;
5894 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5895 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5896 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5898 return CMD_WARNING_CONFIG_FAILED
;
5901 /* Old configuration check. */
5902 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5905 vty_out(vty
, "There is already same aggregate network.\n");
5906 /* try to remove the old entry */
5907 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5909 vty_out(vty
, "Error deleting aggregate.\n");
5910 bgp_unlock_node(rn
);
5911 return CMD_WARNING_CONFIG_FAILED
;
5915 /* Make aggregate address structure. */
5916 aggregate
= bgp_aggregate_new();
5917 aggregate
->summary_only
= summary_only
;
5918 aggregate
->as_set
= as_set
;
5919 aggregate
->safi
= safi
;
5920 bgp_aggregate_set_node_info(rn
, aggregate
);
5922 /* Aggregate address insert into BGP routing table. */
5923 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
5928 DEFUN (aggregate_address
,
5929 aggregate_address_cmd
,
5930 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5931 "Configure BGP aggregate entries\n"
5932 "Aggregate prefix\n"
5933 "Generate AS set path information\n"
5934 "Filter more specific routes from updates\n"
5935 "Filter more specific routes from updates\n"
5936 "Generate AS set path information\n")
5939 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5940 char *prefix
= argv
[idx
]->arg
;
5942 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5944 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5945 ? AGGREGATE_SUMMARY_ONLY
5948 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5949 summary_only
, as_set
);
5952 DEFUN (aggregate_address_mask
,
5953 aggregate_address_mask_cmd
,
5954 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5955 "Configure BGP aggregate entries\n"
5956 "Aggregate address\n"
5958 "Generate AS set path information\n"
5959 "Filter more specific routes from updates\n"
5960 "Filter more specific routes from updates\n"
5961 "Generate AS set path information\n")
5964 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5965 char *prefix
= argv
[idx
]->arg
;
5966 char *mask
= argv
[idx
+ 1]->arg
;
5968 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5970 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5971 ? AGGREGATE_SUMMARY_ONLY
5974 char prefix_str
[BUFSIZ
];
5975 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5978 vty_out(vty
, "%% Inconsistent address and mask\n");
5979 return CMD_WARNING_CONFIG_FAILED
;
5982 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5983 summary_only
, as_set
);
5986 DEFUN (no_aggregate_address
,
5987 no_aggregate_address_cmd
,
5988 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5990 "Configure BGP aggregate entries\n"
5991 "Aggregate prefix\n"
5992 "Generate AS set path information\n"
5993 "Filter more specific routes from updates\n"
5994 "Filter more specific routes from updates\n"
5995 "Generate AS set path information\n")
5998 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5999 char *prefix
= argv
[idx
]->arg
;
6000 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6003 DEFUN (no_aggregate_address_mask
,
6004 no_aggregate_address_mask_cmd
,
6005 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6007 "Configure BGP aggregate entries\n"
6008 "Aggregate address\n"
6010 "Generate AS set path information\n"
6011 "Filter more specific routes from updates\n"
6012 "Filter more specific routes from updates\n"
6013 "Generate AS set path information\n")
6016 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6017 char *prefix
= argv
[idx
]->arg
;
6018 char *mask
= argv
[idx
+ 1]->arg
;
6020 char prefix_str
[BUFSIZ
];
6021 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6024 vty_out(vty
, "%% Inconsistent address and mask\n");
6025 return CMD_WARNING_CONFIG_FAILED
;
6028 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6031 DEFUN (ipv6_aggregate_address
,
6032 ipv6_aggregate_address_cmd
,
6033 "aggregate-address X:X::X:X/M [summary-only]",
6034 "Configure BGP aggregate entries\n"
6035 "Aggregate prefix\n"
6036 "Filter more specific routes from updates\n")
6039 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6040 char *prefix
= argv
[idx
]->arg
;
6041 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6042 ? AGGREGATE_SUMMARY_ONLY
6044 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6048 DEFUN (no_ipv6_aggregate_address
,
6049 no_ipv6_aggregate_address_cmd
,
6050 "no aggregate-address X:X::X:X/M [summary-only]",
6052 "Configure BGP aggregate entries\n"
6053 "Aggregate prefix\n"
6054 "Filter more specific routes from updates\n")
6057 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6058 char *prefix
= argv
[idx
]->arg
;
6059 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6062 /* Redistribute route treatment. */
6063 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6064 const union g_addr
*nexthop
, ifindex_t ifindex
,
6065 enum nexthop_types_t nhtype
, uint32_t metric
,
6066 uint8_t type
, unsigned short instance
,
6069 struct bgp_path_info
*new;
6070 struct bgp_path_info
*bi
;
6071 struct bgp_path_info info
;
6072 struct bgp_node
*bn
;
6074 struct attr
*new_attr
;
6077 struct bgp_redist
*red
;
6079 /* Make default attribute. */
6080 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6083 case NEXTHOP_TYPE_IFINDEX
:
6085 case NEXTHOP_TYPE_IPV4
:
6086 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6087 attr
.nexthop
= nexthop
->ipv4
;
6089 case NEXTHOP_TYPE_IPV6
:
6090 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6091 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6092 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6094 case NEXTHOP_TYPE_BLACKHOLE
:
6095 switch (p
->family
) {
6097 attr
.nexthop
.s_addr
= INADDR_ANY
;
6100 memset(&attr
.mp_nexthop_global
, 0,
6101 sizeof(attr
.mp_nexthop_global
));
6102 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6107 attr
.nh_ifindex
= ifindex
;
6110 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6113 afi
= family2afi(p
->family
);
6115 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6117 struct attr attr_new
;
6119 /* Copy attribute for modification. */
6120 bgp_attr_dup(&attr_new
, &attr
);
6122 if (red
->redist_metric_flag
)
6123 attr_new
.med
= red
->redist_metric
;
6125 /* Apply route-map. */
6126 if (red
->rmap
.name
) {
6127 memset(&info
, 0, sizeof(struct bgp_path_info
));
6128 info
.peer
= bgp
->peer_self
;
6129 info
.attr
= &attr_new
;
6131 SET_FLAG(bgp
->peer_self
->rmap_type
,
6132 PEER_RMAP_TYPE_REDISTRIBUTE
);
6134 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6137 bgp
->peer_self
->rmap_type
= 0;
6139 if (ret
== RMAP_DENYMATCH
) {
6140 /* Free uninterned attribute. */
6141 bgp_attr_flush(&attr_new
);
6143 /* Unintern original. */
6144 aspath_unintern(&attr
.aspath
);
6145 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6150 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6151 bgp_attr_add_gshut_community(&attr_new
);
6153 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6154 SAFI_UNICAST
, p
, NULL
);
6156 new_attr
= bgp_attr_intern(&attr_new
);
6158 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6159 if (bi
->peer
== bgp
->peer_self
6160 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6164 /* Ensure the (source route) type is updated. */
6166 if (attrhash_cmp(bi
->attr
, new_attr
)
6167 && !CHECK_FLAG(bi
->flags
, BGP_PATH_REMOVED
)) {
6168 bgp_attr_unintern(&new_attr
);
6169 aspath_unintern(&attr
.aspath
);
6170 bgp_unlock_node(bn
);
6173 /* The attribute is changed. */
6174 bgp_info_set_flag(bn
, bi
,
6175 BGP_PATH_ATTR_CHANGED
);
6177 /* Rewrite BGP route information. */
6178 if (CHECK_FLAG(bi
->flags
, BGP_PATH_REMOVED
))
6179 bgp_info_restore(bn
, bi
);
6181 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6183 bgp_attr_unintern(&bi
->attr
);
6184 bi
->attr
= new_attr
;
6185 bi
->uptime
= bgp_clock();
6187 /* Process change. */
6188 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6190 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6191 bgp_unlock_node(bn
);
6192 aspath_unintern(&attr
.aspath
);
6194 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6196 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6198 vpn_leak_from_vrf_update(
6199 bgp_get_default(), bgp
, bi
);
6205 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6206 bgp
->peer_self
, new_attr
, bn
);
6207 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6209 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6210 bgp_info_add(bn
, new);
6211 bgp_unlock_node(bn
);
6212 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6214 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6215 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6217 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6221 /* Unintern original. */
6222 aspath_unintern(&attr
.aspath
);
6225 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6226 unsigned short instance
)
6229 struct bgp_node
*rn
;
6230 struct bgp_path_info
*ri
;
6231 struct bgp_redist
*red
;
6233 afi
= family2afi(p
->family
);
6235 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6237 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6238 SAFI_UNICAST
, p
, NULL
);
6240 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6241 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6245 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6246 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6248 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6251 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6252 bgp_info_delete(rn
, ri
);
6253 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6255 bgp_unlock_node(rn
);
6259 /* Withdraw specified route type's route. */
6260 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6261 unsigned short instance
)
6263 struct bgp_node
*rn
;
6264 struct bgp_path_info
*ri
;
6265 struct bgp_table
*table
;
6267 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6269 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6270 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6271 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6272 && ri
->instance
== instance
)
6276 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6277 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6279 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6282 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6284 bgp_info_delete(rn
, ri
);
6285 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6290 /* Static function to display route. */
6291 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6297 if (p
->family
== AF_INET
) {
6301 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6304 json_object_string_add(json
, "prefix",
6305 inet_ntop(p
->family
,
6308 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6310 } else if (p
->family
== AF_ETHERNET
) {
6311 prefix2str(p
, buf
, PREFIX_STRLEN
);
6312 len
= vty_out(vty
, "%s", buf
);
6313 } else if (p
->family
== AF_EVPN
) {
6317 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6320 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6321 } else if (p
->family
== AF_FLOWSPEC
) {
6322 route_vty_out_flowspec(vty
, p
, NULL
,
6324 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6325 NLRI_STRING_FORMAT_MIN
, json
);
6330 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6337 vty_out(vty
, "\n%*s", 20, " ");
6339 vty_out(vty
, "%*s", len
, " ");
6343 enum bgp_display_type
{
6347 /* Print the short form route status for a bgp_info */
6348 static void route_vty_short_status_out(struct vty
*vty
,
6349 struct bgp_path_info
*binfo
,
6350 json_object
*json_path
)
6354 /* Route status display. */
6355 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_REMOVED
))
6356 json_object_boolean_true_add(json_path
, "removed");
6358 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_STALE
))
6359 json_object_boolean_true_add(json_path
, "stale");
6361 if (binfo
->extra
&& binfo
->extra
->suppress
)
6362 json_object_boolean_true_add(json_path
, "suppressed");
6364 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_VALID
)
6365 && !CHECK_FLAG(binfo
->flags
, BGP_PATH_HISTORY
))
6366 json_object_boolean_true_add(json_path
, "valid");
6369 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_HISTORY
))
6370 json_object_boolean_true_add(json_path
, "history");
6372 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_DAMPED
))
6373 json_object_boolean_true_add(json_path
, "damped");
6375 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_SELECTED
))
6376 json_object_boolean_true_add(json_path
, "bestpath");
6378 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_MULTIPATH
))
6379 json_object_boolean_true_add(json_path
, "multipath");
6381 /* Internal route. */
6382 if ((binfo
->peer
->as
)
6383 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6384 json_object_string_add(json_path
, "pathFrom",
6387 json_object_string_add(json_path
, "pathFrom",
6393 /* Route status display. */
6394 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_REMOVED
))
6396 else if (CHECK_FLAG(binfo
->flags
, BGP_PATH_STALE
))
6398 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6400 else if (CHECK_FLAG(binfo
->flags
, BGP_PATH_VALID
)
6401 && !CHECK_FLAG(binfo
->flags
, BGP_PATH_HISTORY
))
6407 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_HISTORY
))
6409 else if (CHECK_FLAG(binfo
->flags
, BGP_PATH_DAMPED
))
6411 else if (CHECK_FLAG(binfo
->flags
, BGP_PATH_SELECTED
))
6413 else if (CHECK_FLAG(binfo
->flags
, BGP_PATH_MULTIPATH
))
6418 /* Internal route. */
6419 if (binfo
->peer
&& (binfo
->peer
->as
)
6420 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6426 /* called from terminal list command */
6427 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6428 struct bgp_path_info
*binfo
, int display
, safi_t safi
,
6429 json_object
*json_paths
)
6432 json_object
*json_path
= NULL
;
6433 json_object
*json_nexthops
= NULL
;
6434 json_object
*json_nexthop_global
= NULL
;
6435 json_object
*json_nexthop_ll
= NULL
;
6436 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6438 CHECK_FLAG(binfo
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6439 bool nexthop_othervrf
= false;
6440 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6441 const char *nexthop_vrfname
= "Default";
6444 json_path
= json_object_new_object();
6446 /* short status lead text */
6447 route_vty_short_status_out(vty
, binfo
, json_path
);
6450 /* print prefix and mask */
6452 route_vty_out_route(p
, vty
, json_path
);
6454 vty_out(vty
, "%*s", 17, " ");
6456 route_vty_out_route(p
, vty
, json_path
);
6459 /* Print attribute */
6463 json_object_array_add(json_paths
, json_path
);
6471 * If vrf id of nexthop is different from that of prefix,
6472 * set up printable string to append
6474 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6475 const char *self
= "";
6480 nexthop_othervrf
= true;
6481 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6483 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6484 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6485 "@%s%s", VRFID_NONE_STR
, self
);
6487 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6488 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6490 if (binfo
->extra
->bgp_orig
->inst_type
!=
6491 BGP_INSTANCE_TYPE_DEFAULT
)
6493 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6495 const char *self
= "";
6500 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6504 * For ENCAP and EVPN routes, nexthop address family is not
6505 * neccessarily the same as the prefix address family.
6506 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6507 * EVPN routes are also exchanged with a MP nexthop. Currently,
6509 * is only IPv4, the value will be present in either
6511 * attr->mp_nexthop_global_in
6513 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6516 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6520 sprintf(nexthop
, "%s",
6521 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6525 sprintf(nexthop
, "%s",
6526 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6530 sprintf(nexthop
, "?");
6535 json_nexthop_global
= json_object_new_object();
6537 json_object_string_add(json_nexthop_global
, "afi",
6538 (af
== AF_INET
) ? "ip" : "ipv6");
6539 json_object_string_add(json_nexthop_global
,
6540 (af
== AF_INET
) ? "ip" : "ipv6",
6542 json_object_boolean_true_add(json_nexthop_global
,
6545 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6546 } else if (safi
== SAFI_EVPN
) {
6548 json_nexthop_global
= json_object_new_object();
6550 json_object_string_add(json_nexthop_global
, "ip",
6551 inet_ntoa(attr
->nexthop
));
6552 json_object_string_add(json_nexthop_global
, "afi",
6554 json_object_boolean_true_add(json_nexthop_global
,
6557 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6559 } else if (safi
== SAFI_FLOWSPEC
) {
6560 if (attr
->nexthop
.s_addr
!= 0) {
6562 json_nexthop_global
= json_object_new_object();
6563 json_object_string_add(
6564 json_nexthop_global
, "ip",
6565 inet_ntoa(attr
->nexthop
));
6566 json_object_string_add(json_nexthop_global
,
6568 json_object_boolean_true_add(json_nexthop_global
,
6571 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6574 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6576 json_nexthop_global
= json_object_new_object();
6578 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6579 json_object_string_add(
6580 json_nexthop_global
, "ip",
6581 inet_ntoa(attr
->mp_nexthop_global_in
));
6583 json_object_string_add(
6584 json_nexthop_global
, "ip",
6585 inet_ntoa(attr
->nexthop
));
6587 json_object_string_add(json_nexthop_global
, "afi",
6589 json_object_boolean_true_add(json_nexthop_global
,
6594 snprintf(buf
, sizeof(buf
), "%s%s",
6595 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6596 vty_out(vty
, "%-16s", buf
);
6601 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6606 json_nexthop_global
= json_object_new_object();
6607 json_object_string_add(
6608 json_nexthop_global
, "ip",
6609 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6611 json_object_string_add(json_nexthop_global
, "afi",
6613 json_object_string_add(json_nexthop_global
, "scope",
6616 /* We display both LL & GL if both have been
6618 if ((attr
->mp_nexthop_len
== 32)
6619 || (binfo
->peer
->conf_if
)) {
6620 json_nexthop_ll
= json_object_new_object();
6621 json_object_string_add(
6622 json_nexthop_ll
, "ip",
6624 &attr
->mp_nexthop_local
, buf
,
6626 json_object_string_add(json_nexthop_ll
, "afi",
6628 json_object_string_add(json_nexthop_ll
, "scope",
6631 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6632 &attr
->mp_nexthop_local
)
6634 && !attr
->mp_nexthop_prefer_global
)
6635 json_object_boolean_true_add(
6636 json_nexthop_ll
, "used");
6638 json_object_boolean_true_add(
6639 json_nexthop_global
, "used");
6641 json_object_boolean_true_add(
6642 json_nexthop_global
, "used");
6644 /* Display LL if LL/Global both in table unless
6645 * prefer-global is set */
6646 if (((attr
->mp_nexthop_len
== 32)
6647 && !attr
->mp_nexthop_prefer_global
)
6648 || (binfo
->peer
->conf_if
)) {
6649 if (binfo
->peer
->conf_if
) {
6650 len
= vty_out(vty
, "%s",
6651 binfo
->peer
->conf_if
);
6652 len
= 16 - len
; /* len of IPv6
6658 vty_out(vty
, "\n%*s", 36, " ");
6660 vty_out(vty
, "%*s", len
, " ");
6666 &attr
->mp_nexthop_local
,
6672 vty_out(vty
, "\n%*s", 36, " ");
6674 vty_out(vty
, "%*s", len
, " ");
6680 &attr
->mp_nexthop_global
, buf
,
6686 vty_out(vty
, "\n%*s", 36, " ");
6688 vty_out(vty
, "%*s", len
, " ");
6694 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6696 json_object_int_add(json_path
, "med", attr
->med
);
6698 vty_out(vty
, "%10u", attr
->med
);
6699 else if (!json_paths
)
6703 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6705 json_object_int_add(json_path
, "localpref",
6708 vty_out(vty
, "%7u", attr
->local_pref
);
6709 else if (!json_paths
)
6713 json_object_int_add(json_path
, "weight", attr
->weight
);
6715 vty_out(vty
, "%7u ", attr
->weight
);
6719 json_object_string_add(
6720 json_path
, "peerId",
6721 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6727 json_object_string_add(json_path
, "aspath",
6730 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6735 json_object_string_add(json_path
, "origin",
6736 bgp_origin_long_str
[attr
->origin
]);
6738 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6742 json_object_boolean_true_add(json_path
,
6743 "announceNexthopSelf");
6744 if (nexthop_othervrf
) {
6745 json_object_string_add(json_path
, "nhVrfName",
6748 json_object_int_add(json_path
, "nhVrfId",
6749 ((nexthop_vrfid
== VRF_UNKNOWN
)
6751 : (int)nexthop_vrfid
));
6756 if (json_nexthop_global
|| json_nexthop_ll
) {
6757 json_nexthops
= json_object_new_array();
6759 if (json_nexthop_global
)
6760 json_object_array_add(json_nexthops
,
6761 json_nexthop_global
);
6763 if (json_nexthop_ll
)
6764 json_object_array_add(json_nexthops
,
6767 json_object_object_add(json_path
, "nexthops",
6771 json_object_array_add(json_paths
, json_path
);
6775 /* prints an additional line, indented, with VNC info, if
6777 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6778 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6783 /* called from terminal list command */
6784 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6785 safi_t safi
, bool use_json
, json_object
*json_ar
)
6787 json_object
*json_status
= NULL
;
6788 json_object
*json_net
= NULL
;
6790 /* Route status display. */
6792 json_status
= json_object_new_object();
6793 json_net
= json_object_new_object();
6800 /* print prefix and mask */
6802 json_object_string_add(
6803 json_net
, "addrPrefix",
6804 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6806 route_vty_out_route(p
, vty
, NULL
);
6808 /* Print attribute */
6811 if (p
->family
== AF_INET
6812 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6813 || safi
== SAFI_EVPN
6814 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6815 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6816 || safi
== SAFI_EVPN
)
6817 json_object_string_add(
6818 json_net
, "nextHop",
6820 attr
->mp_nexthop_global_in
));
6822 json_object_string_add(
6823 json_net
, "nextHop",
6824 inet_ntoa(attr
->nexthop
));
6825 } else if (p
->family
== AF_INET6
6826 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6829 json_object_string_add(
6830 json_net
, "netHopGloabal",
6832 &attr
->mp_nexthop_global
, buf
,
6837 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6838 json_object_int_add(json_net
, "metric",
6841 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6842 json_object_int_add(json_net
, "localPref",
6845 json_object_int_add(json_net
, "weight", attr
->weight
);
6849 json_object_string_add(json_net
, "asPath",
6853 json_object_string_add(json_net
, "bgpOriginCode",
6854 bgp_origin_str
[attr
->origin
]);
6856 if (p
->family
== AF_INET
6857 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6858 || safi
== SAFI_EVPN
6859 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6860 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6861 || safi
== SAFI_EVPN
)
6862 vty_out(vty
, "%-16s",
6864 attr
->mp_nexthop_global_in
));
6866 vty_out(vty
, "%-16s",
6867 inet_ntoa(attr
->nexthop
));
6868 } else if (p
->family
== AF_INET6
6869 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6876 &attr
->mp_nexthop_global
, buf
,
6880 vty_out(vty
, "\n%*s", 36, " ");
6882 vty_out(vty
, "%*s", len
, " ");
6885 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6886 vty_out(vty
, "%10u", attr
->med
);
6890 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6891 vty_out(vty
, "%7u", attr
->local_pref
);
6895 vty_out(vty
, "%7u ", attr
->weight
);
6899 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6902 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6906 json_object_boolean_true_add(json_status
, "*");
6907 json_object_boolean_true_add(json_status
, ">");
6908 json_object_object_add(json_net
, "appliedStatusSymbols",
6910 char buf_cut
[BUFSIZ
];
6911 json_object_object_add(
6913 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6919 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6920 struct bgp_path_info
*binfo
, int display
, safi_t safi
,
6923 json_object
*json_out
= NULL
;
6925 mpls_label_t label
= MPLS_INVALID_LABEL
;
6931 json_out
= json_object_new_object();
6933 /* short status lead text */
6934 route_vty_short_status_out(vty
, binfo
, json_out
);
6936 /* print prefix and mask */
6939 route_vty_out_route(p
, vty
, NULL
);
6941 vty_out(vty
, "%*s", 17, " ");
6944 /* Print attribute */
6947 if (((p
->family
== AF_INET
)
6948 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6949 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6950 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6951 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6952 || safi
== SAFI_EVPN
) {
6954 json_object_string_add(
6955 json_out
, "mpNexthopGlobalIn",
6957 attr
->mp_nexthop_global_in
));
6959 vty_out(vty
, "%-16s",
6961 attr
->mp_nexthop_global_in
));
6964 json_object_string_add(
6965 json_out
, "nexthop",
6966 inet_ntoa(attr
->nexthop
));
6968 vty_out(vty
, "%-16s",
6969 inet_ntoa(attr
->nexthop
));
6971 } else if (((p
->family
== AF_INET6
)
6972 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6973 || (safi
== SAFI_EVPN
6974 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6975 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6979 if (attr
->mp_nexthop_len
6980 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6982 json_object_string_add(
6983 json_out
, "mpNexthopGlobalIn",
6986 &attr
->mp_nexthop_global
,
6987 buf_a
, sizeof(buf_a
)));
6992 &attr
->mp_nexthop_global
,
6993 buf_a
, sizeof(buf_a
)));
6994 } else if (attr
->mp_nexthop_len
6995 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6998 &attr
->mp_nexthop_global
,
6999 buf_a
, sizeof(buf_a
));
7001 &attr
->mp_nexthop_local
,
7002 buf_b
, sizeof(buf_b
));
7003 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7004 json_object_string_add(
7006 "mpNexthopGlobalLocal", buf_c
);
7008 vty_out(vty
, "%s(%s)",
7011 &attr
->mp_nexthop_global
,
7012 buf_a
, sizeof(buf_a
)),
7015 &attr
->mp_nexthop_local
,
7016 buf_b
, sizeof(buf_b
)));
7021 label
= decode_label(&binfo
->extra
->label
[0]);
7023 if (bgp_is_valid_label(&label
)) {
7025 json_object_int_add(json_out
, "notag", label
);
7026 json_object_array_add(json
, json_out
);
7028 vty_out(vty
, "notag/%d", label
);
7034 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7035 struct bgp_path_info
*binfo
, int display
,
7036 json_object
*json_paths
)
7040 json_object
*json_path
= NULL
;
7043 json_path
= json_object_new_object();
7048 /* short status lead text */
7049 route_vty_short_status_out(vty
, binfo
, json_path
);
7051 /* print prefix and mask */
7053 route_vty_out_route(p
, vty
, NULL
);
7055 vty_out(vty
, "%*s", 17, " ");
7057 /* Print attribute */
7061 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7065 vty_out(vty
, "%-16s",
7066 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7070 vty_out(vty
, "%s(%s)",
7071 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7073 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7080 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7082 vty_out(vty
, "%s", str
);
7083 XFREE(MTYPE_TMP
, str
);
7085 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7087 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7088 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7091 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7094 if (attr
->ecommunity
) {
7096 struct ecommunity_val
*routermac
= ecommunity_lookup(
7097 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7098 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7100 mac
= ecom_mac2str((char *)routermac
->val
);
7102 vty_out(vty
, "/%s", (char *)mac
);
7103 XFREE(MTYPE_TMP
, mac
);
7111 /* dampening route */
7112 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7113 struct bgp_path_info
*binfo
, int display
,
7114 safi_t safi
, bool use_json
, json_object
*json
)
7118 char timebuf
[BGP_UPTIME_LEN
];
7120 /* short status lead text */
7121 route_vty_short_status_out(vty
, binfo
, json
);
7123 /* print prefix and mask */
7126 route_vty_out_route(p
, vty
, NULL
);
7128 vty_out(vty
, "%*s", 17, " ");
7131 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7135 vty_out(vty
, "\n%*s", 34, " ");
7138 json_object_int_add(json
, "peerHost", len
);
7140 vty_out(vty
, "%*s", len
, " ");
7144 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7147 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7151 /* Print attribute */
7157 json_object_string_add(json
, "asPath",
7160 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7165 json_object_string_add(json
, "origin",
7166 bgp_origin_str
[attr
->origin
]);
7168 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7175 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7176 struct bgp_path_info
*binfo
, int display
,
7177 safi_t safi
, bool use_json
, json_object
*json
)
7180 struct bgp_damp_info
*bdi
;
7181 char timebuf
[BGP_UPTIME_LEN
];
7187 bdi
= binfo
->extra
->damp_info
;
7189 /* short status lead text */
7190 route_vty_short_status_out(vty
, binfo
, json
);
7192 /* print prefix and mask */
7195 route_vty_out_route(p
, vty
, NULL
);
7197 vty_out(vty
, "%*s", 17, " ");
7200 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7204 vty_out(vty
, "\n%*s", 33, " ");
7207 json_object_int_add(json
, "peerHost", len
);
7209 vty_out(vty
, "%*s", len
, " ");
7212 len
= vty_out(vty
, "%d", bdi
->flap
);
7219 json_object_int_add(json
, "bdiFlap", len
);
7221 vty_out(vty
, "%*s", len
, " ");
7225 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7228 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7229 BGP_UPTIME_LEN
, 0, NULL
));
7231 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_DAMPED
)
7232 && !CHECK_FLAG(binfo
->flags
, BGP_PATH_HISTORY
)) {
7234 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7235 BGP_UPTIME_LEN
, use_json
, json
);
7238 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7243 vty_out(vty
, "%*s ", 8, " ");
7246 /* Print attribute */
7252 json_object_string_add(json
, "asPath",
7255 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7260 json_object_string_add(json
, "origin",
7261 bgp_origin_str
[attr
->origin
]);
7263 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7269 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7270 int *first
, const char *header
,
7271 json_object
*json_adv_to
)
7273 char buf1
[INET6_ADDRSTRLEN
];
7274 json_object
*json_peer
= NULL
;
7277 /* 'advertised-to' is a dictionary of peers we have advertised
7279 * prefix too. The key is the peer's IP or swpX, the value is
7281 * hostname if we know it and "" if not.
7283 json_peer
= json_object_new_object();
7286 json_object_string_add(json_peer
, "hostname",
7290 json_object_object_add(json_adv_to
, peer
->conf_if
,
7293 json_object_object_add(
7295 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7299 vty_out(vty
, "%s", header
);
7304 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7306 vty_out(vty
, " %s(%s)", peer
->hostname
,
7309 vty_out(vty
, " %s(%s)", peer
->hostname
,
7310 sockunion2str(&peer
->su
, buf1
,
7314 vty_out(vty
, " %s", peer
->conf_if
);
7317 sockunion2str(&peer
->su
, buf1
,
7323 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7324 struct bgp_path_info
*binfo
, afi_t afi
, safi_t safi
,
7325 json_object
*json_paths
)
7327 char buf
[INET6_ADDRSTRLEN
];
7329 char buf2
[EVPN_ROUTE_STRLEN
];
7331 int sockunion_vty_out(struct vty
*, union sockunion
*);
7333 json_object
*json_bestpath
= NULL
;
7334 json_object
*json_cluster_list
= NULL
;
7335 json_object
*json_cluster_list_list
= NULL
;
7336 json_object
*json_ext_community
= NULL
;
7337 json_object
*json_last_update
= NULL
;
7338 json_object
*json_pmsi
= NULL
;
7339 json_object
*json_nexthop_global
= NULL
;
7340 json_object
*json_nexthop_ll
= NULL
;
7341 json_object
*json_nexthops
= NULL
;
7342 json_object
*json_path
= NULL
;
7343 json_object
*json_peer
= NULL
;
7344 json_object
*json_string
= NULL
;
7345 json_object
*json_adv_to
= NULL
;
7347 struct listnode
*node
, *nnode
;
7349 int addpath_capable
;
7351 unsigned int first_as
;
7353 CHECK_FLAG(binfo
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7356 json_path
= json_object_new_object();
7357 json_peer
= json_object_new_object();
7358 json_nexthop_global
= json_object_new_object();
7361 if (!json_paths
&& safi
== SAFI_EVPN
) {
7364 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7365 vty_out(vty
, " Route %s", buf2
);
7367 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7368 bgp_evpn_label2str(binfo
->extra
->label
,
7369 binfo
->extra
->num_labels
, tag_buf
,
7371 vty_out(vty
, " VNI %s", tag_buf
);
7374 if (binfo
->extra
&& binfo
->extra
->parent
) {
7375 struct bgp_path_info
*parent_ri
;
7376 struct bgp_node
*rn
, *prn
;
7379 (struct bgp_path_info
*)binfo
->extra
->parent
;
7380 rn
= parent_ri
->net
;
7381 if (rn
&& rn
->prn
) {
7383 vty_out(vty
, " Imported from %s:%s\n",
7385 (struct prefix_rd
*)&prn
->p
,
7386 buf1
, sizeof(buf1
)),
7395 /* Line1 display AS-path, Aggregator */
7398 if (!attr
->aspath
->json
)
7399 aspath_str_update(attr
->aspath
, true);
7400 json_object_lock(attr
->aspath
->json
);
7401 json_object_object_add(json_path
, "aspath",
7402 attr
->aspath
->json
);
7404 if (attr
->aspath
->segments
)
7405 aspath_print_vty(vty
, " %s",
7408 vty_out(vty
, " Local");
7412 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_REMOVED
)) {
7414 json_object_boolean_true_add(json_path
,
7417 vty_out(vty
, ", (removed)");
7420 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_STALE
)) {
7422 json_object_boolean_true_add(json_path
,
7425 vty_out(vty
, ", (stale)");
7428 if (CHECK_FLAG(attr
->flag
,
7429 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7431 json_object_int_add(json_path
, "aggregatorAs",
7432 attr
->aggregator_as
);
7433 json_object_string_add(
7434 json_path
, "aggregatorId",
7435 inet_ntoa(attr
->aggregator_addr
));
7437 vty_out(vty
, ", (aggregated by %u %s)",
7438 attr
->aggregator_as
,
7439 inet_ntoa(attr
->aggregator_addr
));
7443 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7444 PEER_FLAG_REFLECTOR_CLIENT
)) {
7446 json_object_boolean_true_add(
7447 json_path
, "rxedFromRrClient");
7449 vty_out(vty
, ", (Received from a RR-client)");
7452 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7453 PEER_FLAG_RSERVER_CLIENT
)) {
7455 json_object_boolean_true_add(
7456 json_path
, "rxedFromRsClient");
7458 vty_out(vty
, ", (Received from a RS-client)");
7461 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_HISTORY
)) {
7463 json_object_boolean_true_add(
7464 json_path
, "dampeningHistoryEntry");
7466 vty_out(vty
, ", (history entry)");
7467 } else if (CHECK_FLAG(binfo
->flags
, BGP_PATH_DAMPED
)) {
7469 json_object_boolean_true_add(
7470 json_path
, "dampeningSuppressed");
7472 vty_out(vty
, ", (suppressed due to dampening)");
7478 /* Line2 display Next-hop, Neighbor, Router-id */
7479 /* Display the nexthop */
7480 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7481 || p
->family
== AF_EVPN
)
7482 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7483 || safi
== SAFI_EVPN
7484 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7485 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7486 || safi
== SAFI_EVPN
) {
7488 json_object_string_add(
7489 json_nexthop_global
, "ip",
7491 attr
->mp_nexthop_global_in
));
7495 attr
->mp_nexthop_global_in
));
7498 json_object_string_add(
7499 json_nexthop_global
, "ip",
7500 inet_ntoa(attr
->nexthop
));
7503 inet_ntoa(attr
->nexthop
));
7507 json_object_string_add(json_nexthop_global
,
7511 json_object_string_add(
7512 json_nexthop_global
, "ip",
7514 &attr
->mp_nexthop_global
, buf
,
7516 json_object_string_add(json_nexthop_global
,
7518 json_object_string_add(json_nexthop_global
,
7523 &attr
->mp_nexthop_global
, buf
,
7528 /* Display the IGP cost or 'inaccessible' */
7529 if (!CHECK_FLAG(binfo
->flags
, BGP_PATH_VALID
)) {
7531 json_object_boolean_false_add(
7532 json_nexthop_global
, "accessible");
7534 vty_out(vty
, " (inaccessible)");
7536 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7538 json_object_int_add(
7539 json_nexthop_global
, "metric",
7540 binfo
->extra
->igpmetric
);
7542 vty_out(vty
, " (metric %u)",
7543 binfo
->extra
->igpmetric
);
7546 /* IGP cost is 0, display this only for json */
7549 json_object_int_add(json_nexthop_global
,
7554 json_object_boolean_true_add(
7555 json_nexthop_global
, "accessible");
7558 /* Display peer "from" output */
7559 /* This path was originated locally */
7560 if (binfo
->peer
== bgp
->peer_self
) {
7562 if (safi
== SAFI_EVPN
7563 || (p
->family
== AF_INET
7564 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7566 json_object_string_add(
7567 json_peer
, "peerId", "0.0.0.0");
7569 vty_out(vty
, " from 0.0.0.0 ");
7572 json_object_string_add(json_peer
,
7575 vty_out(vty
, " from :: ");
7579 json_object_string_add(
7580 json_peer
, "routerId",
7581 inet_ntoa(bgp
->router_id
));
7583 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7586 /* We RXed this path from one of our peers */
7590 json_object_string_add(
7591 json_peer
, "peerId",
7592 sockunion2str(&binfo
->peer
->su
, buf
,
7594 json_object_string_add(
7595 json_peer
, "routerId",
7597 &binfo
->peer
->remote_id
, buf1
,
7600 if (binfo
->peer
->hostname
)
7601 json_object_string_add(
7602 json_peer
, "hostname",
7603 binfo
->peer
->hostname
);
7605 if (binfo
->peer
->domainname
)
7606 json_object_string_add(
7607 json_peer
, "domainname",
7608 binfo
->peer
->domainname
);
7610 if (binfo
->peer
->conf_if
)
7611 json_object_string_add(
7612 json_peer
, "interface",
7613 binfo
->peer
->conf_if
);
7615 if (binfo
->peer
->conf_if
) {
7616 if (binfo
->peer
->hostname
7619 BGP_FLAG_SHOW_HOSTNAME
))
7620 vty_out(vty
, " from %s(%s)",
7621 binfo
->peer
->hostname
,
7622 binfo
->peer
->conf_if
);
7624 vty_out(vty
, " from %s",
7625 binfo
->peer
->conf_if
);
7627 if (binfo
->peer
->hostname
7630 BGP_FLAG_SHOW_HOSTNAME
))
7631 vty_out(vty
, " from %s(%s)",
7632 binfo
->peer
->hostname
,
7635 vty_out(vty
, " from %s",
7644 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7645 vty_out(vty
, " (%s)",
7646 inet_ntoa(attr
->originator_id
));
7648 vty_out(vty
, " (%s)",
7651 &binfo
->peer
->remote_id
,
7652 buf1
, sizeof(buf1
)));
7657 * Note when vrfid of nexthop is different from that of prefix
7659 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7660 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7665 if (binfo
->extra
->bgp_orig
->inst_type
==
7666 BGP_INSTANCE_TYPE_DEFAULT
)
7670 vn
= binfo
->extra
->bgp_orig
->name
;
7672 json_object_string_add(json_path
, "nhVrfName",
7675 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7676 json_object_int_add(json_path
,
7679 json_object_int_add(json_path
,
7680 "nhVrfId", (int)nexthop_vrfid
);
7683 if (nexthop_vrfid
== VRF_UNKNOWN
)
7684 vty_out(vty
, " vrf ?");
7686 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7692 json_object_boolean_true_add(json_path
,
7693 "announceNexthopSelf");
7695 vty_out(vty
, " announce-nh-self");
7702 /* display the link-local nexthop */
7703 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7705 json_nexthop_ll
= json_object_new_object();
7706 json_object_string_add(
7707 json_nexthop_ll
, "ip",
7709 &attr
->mp_nexthop_local
, buf
,
7711 json_object_string_add(json_nexthop_ll
, "afi",
7713 json_object_string_add(json_nexthop_ll
, "scope",
7716 json_object_boolean_true_add(json_nexthop_ll
,
7719 if (!attr
->mp_nexthop_prefer_global
)
7720 json_object_boolean_true_add(
7721 json_nexthop_ll
, "used");
7723 json_object_boolean_true_add(
7724 json_nexthop_global
, "used");
7726 vty_out(vty
, " (%s) %s\n",
7728 &attr
->mp_nexthop_local
, buf
,
7730 attr
->mp_nexthop_prefer_global
7735 /* If we do not have a link-local nexthop then we must flag the
7739 json_object_boolean_true_add(
7740 json_nexthop_global
, "used");
7743 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7744 * Int/Ext/Local, Atomic, best */
7746 json_object_string_add(
7747 json_path
, "origin",
7748 bgp_origin_long_str
[attr
->origin
]);
7750 vty_out(vty
, " Origin %s",
7751 bgp_origin_long_str
[attr
->origin
]);
7753 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7755 json_object_int_add(json_path
, "med",
7758 vty_out(vty
, ", metric %u", attr
->med
);
7761 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7763 json_object_int_add(json_path
, "localpref",
7766 vty_out(vty
, ", localpref %u",
7770 if (attr
->weight
!= 0) {
7772 json_object_int_add(json_path
, "weight",
7775 vty_out(vty
, ", weight %u", attr
->weight
);
7778 if (attr
->tag
!= 0) {
7780 json_object_int_add(json_path
, "tag",
7783 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7787 if (!CHECK_FLAG(binfo
->flags
, BGP_PATH_VALID
)) {
7789 json_object_boolean_false_add(json_path
,
7792 vty_out(vty
, ", invalid");
7793 } else if (!CHECK_FLAG(binfo
->flags
, BGP_PATH_HISTORY
)) {
7795 json_object_boolean_true_add(json_path
,
7798 vty_out(vty
, ", valid");
7801 if (binfo
->peer
!= bgp
->peer_self
) {
7802 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7803 if (CHECK_FLAG(bgp
->config
,
7804 BGP_CONFIG_CONFEDERATION
)) {
7806 json_object_string_add(
7811 ", confed-internal");
7814 json_object_string_add(
7818 vty_out(vty
, ", internal");
7821 if (bgp_confederation_peers_check(
7822 bgp
, binfo
->peer
->as
)) {
7824 json_object_string_add(
7829 ", confed-external");
7832 json_object_string_add(
7836 vty_out(vty
, ", external");
7839 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7841 json_object_boolean_true_add(json_path
,
7843 json_object_boolean_true_add(json_path
,
7846 vty_out(vty
, ", aggregated, local");
7848 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7850 json_object_boolean_true_add(json_path
,
7853 vty_out(vty
, ", sourced");
7856 json_object_boolean_true_add(json_path
,
7858 json_object_boolean_true_add(json_path
,
7861 vty_out(vty
, ", sourced, local");
7865 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7867 json_object_boolean_true_add(json_path
,
7870 vty_out(vty
, ", atomic-aggregate");
7873 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_MULTIPATH
)
7874 || (CHECK_FLAG(binfo
->flags
, BGP_PATH_SELECTED
)
7875 && bgp_info_mpath_count(binfo
))) {
7877 json_object_boolean_true_add(json_path
,
7880 vty_out(vty
, ", multipath");
7883 // Mark the bestpath(s)
7884 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_DMED_SELECTED
)) {
7885 first_as
= aspath_get_first_as(attr
->aspath
);
7890 json_object_new_object();
7891 json_object_int_add(json_bestpath
,
7892 "bestpathFromAs", first_as
);
7895 vty_out(vty
, ", bestpath-from-AS %u",
7899 ", bestpath-from-AS Local");
7903 if (CHECK_FLAG(binfo
->flags
, BGP_PATH_SELECTED
)) {
7907 json_object_new_object();
7908 json_object_boolean_true_add(json_bestpath
,
7911 vty_out(vty
, ", best");
7915 json_object_object_add(json_path
, "bestpath",
7921 /* Line 4 display Community */
7922 if (attr
->community
) {
7924 if (!attr
->community
->json
)
7925 community_str(attr
->community
, true);
7926 json_object_lock(attr
->community
->json
);
7927 json_object_object_add(json_path
, "community",
7928 attr
->community
->json
);
7930 vty_out(vty
, " Community: %s\n",
7931 attr
->community
->str
);
7935 /* Line 5 display Extended-community */
7936 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7938 json_ext_community
= json_object_new_object();
7939 json_object_string_add(json_ext_community
,
7941 attr
->ecommunity
->str
);
7942 json_object_object_add(json_path
,
7943 "extendedCommunity",
7944 json_ext_community
);
7946 vty_out(vty
, " Extended Community: %s\n",
7947 attr
->ecommunity
->str
);
7951 /* Line 6 display Large community */
7952 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7954 if (!attr
->lcommunity
->json
)
7955 lcommunity_str(attr
->lcommunity
, true);
7956 json_object_lock(attr
->lcommunity
->json
);
7957 json_object_object_add(json_path
,
7959 attr
->lcommunity
->json
);
7961 vty_out(vty
, " Large Community: %s\n",
7962 attr
->lcommunity
->str
);
7966 /* Line 7 display Originator, Cluster-id */
7967 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7968 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7970 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7972 json_object_string_add(
7973 json_path
, "originatorId",
7974 inet_ntoa(attr
->originator_id
));
7976 vty_out(vty
, " Originator: %s",
7977 inet_ntoa(attr
->originator_id
));
7980 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7985 json_object_new_object();
7986 json_cluster_list_list
=
7987 json_object_new_array();
7990 i
< attr
->cluster
->length
/ 4;
7992 json_string
= json_object_new_string(
7996 json_object_array_add(
7997 json_cluster_list_list
,
8001 /* struct cluster_list does not have
8003 * aspath and community do. Add this
8006 json_object_string_add(json_cluster_list,
8007 "string", attr->cluster->str);
8009 json_object_object_add(
8010 json_cluster_list
, "list",
8011 json_cluster_list_list
);
8012 json_object_object_add(
8013 json_path
, "clusterList",
8016 vty_out(vty
, ", Cluster list: ");
8019 i
< attr
->cluster
->length
/ 4;
8033 if (binfo
->extra
&& binfo
->extra
->damp_info
)
8034 bgp_damp_info_vty(vty
, binfo
, json_path
);
8037 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8038 && safi
!= SAFI_EVPN
) {
8039 mpls_label_t label
=
8040 label_pton(&binfo
->extra
->label
[0]);
8042 json_object_int_add(json_path
, "remoteLabel",
8045 vty_out(vty
, " Remote label: %d\n", label
);
8049 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8051 json_object_int_add(json_path
, "labelIndex",
8054 vty_out(vty
, " Label Index: %d\n",
8058 /* Line 8 display Addpath IDs */
8059 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8061 json_object_int_add(json_path
, "addpathRxId",
8062 binfo
->addpath_rx_id
);
8063 json_object_int_add(json_path
, "addpathTxId",
8064 binfo
->addpath_tx_id
);
8066 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8067 binfo
->addpath_rx_id
,
8068 binfo
->addpath_tx_id
);
8072 /* If we used addpath to TX a non-bestpath we need to display
8073 * "Advertised to" on a path-by-path basis */
8074 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8077 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8079 bgp_addpath_encode_tx(peer
, afi
, safi
);
8080 has_adj
= bgp_adj_out_lookup(
8081 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8083 if ((addpath_capable
&& has_adj
)
8084 || (!addpath_capable
&& has_adj
8085 && CHECK_FLAG(binfo
->flags
,
8086 BGP_PATH_SELECTED
))) {
8087 if (json_path
&& !json_adv_to
)
8089 json_object_new_object();
8091 route_vty_out_advertised_to(
8100 json_object_object_add(json_path
,
8111 /* Line 9 display Uptime */
8112 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8114 json_last_update
= json_object_new_object();
8115 json_object_int_add(json_last_update
, "epoch", tbuf
);
8116 json_object_string_add(json_last_update
, "string",
8118 json_object_object_add(json_path
, "lastUpdate",
8121 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8123 /* Line 10 display PMSI tunnel attribute, if present */
8124 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8125 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8126 attr
->pmsi_tnl_type
,
8127 PMSI_TNLTYPE_STR_DEFAULT
);
8130 json_pmsi
= json_object_new_object();
8131 json_object_string_add(json_pmsi
,
8133 json_object_object_add(json_path
, "pmsi",
8136 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8142 /* We've constructed the json object for this path, add it to the json
8146 if (json_nexthop_global
|| json_nexthop_ll
) {
8147 json_nexthops
= json_object_new_array();
8149 if (json_nexthop_global
)
8150 json_object_array_add(json_nexthops
,
8151 json_nexthop_global
);
8153 if (json_nexthop_ll
)
8154 json_object_array_add(json_nexthops
,
8157 json_object_object_add(json_path
, "nexthops",
8161 json_object_object_add(json_path
, "peer", json_peer
);
8162 json_object_array_add(json_paths
, json_path
);
8167 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8168 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8169 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8171 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8172 const char *prefix_list_str
, afi_t afi
,
8173 safi_t safi
, enum bgp_show_type type
);
8174 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8175 const char *filter
, afi_t afi
, safi_t safi
,
8176 enum bgp_show_type type
);
8177 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8178 const char *rmap_str
, afi_t afi
, safi_t safi
,
8179 enum bgp_show_type type
);
8180 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8181 const char *com
, int exact
, afi_t afi
,
8183 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8184 const char *prefix
, afi_t afi
, safi_t safi
,
8185 enum bgp_show_type type
);
8186 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8187 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8188 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8189 const char *comstr
, int exact
, afi_t afi
,
8190 safi_t safi
, bool use_json
);
8193 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8194 struct bgp_table
*table
, enum bgp_show_type type
,
8195 void *output_arg
, bool use_json
, char *rd
,
8196 int is_last
, unsigned long *output_cum
,
8197 unsigned long *total_cum
,
8198 unsigned long *json_header_depth
)
8200 struct bgp_path_info
*ri
;
8201 struct bgp_node
*rn
;
8204 unsigned long output_count
= 0;
8205 unsigned long total_count
= 0;
8209 json_object
*json_paths
= NULL
;
8212 if (output_cum
&& *output_cum
!= 0)
8215 if (use_json
&& !*json_header_depth
) {
8217 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8218 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8219 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8220 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8222 table
->version
, inet_ntoa(bgp
->router_id
));
8223 *json_header_depth
= 2;
8225 vty_out(vty
, " \"routeDistinguishers\" : {");
8226 ++*json_header_depth
;
8230 if (use_json
&& rd
) {
8231 vty_out(vty
, " \"%s\" : { ", rd
);
8234 /* Start processing of routes. */
8235 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8236 if (rn
->info
== NULL
)
8241 json_paths
= json_object_new_array();
8245 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8247 if (type
== bgp_show_type_flap_statistics
8248 || type
== bgp_show_type_flap_neighbor
8249 || type
== bgp_show_type_dampend_paths
8250 || type
== bgp_show_type_damp_neighbor
) {
8251 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8254 if (type
== bgp_show_type_regexp
) {
8255 regex_t
*regex
= output_arg
;
8257 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8261 if (type
== bgp_show_type_prefix_list
) {
8262 struct prefix_list
*plist
= output_arg
;
8264 if (prefix_list_apply(plist
, &rn
->p
)
8268 if (type
== bgp_show_type_filter_list
) {
8269 struct as_list
*as_list
= output_arg
;
8271 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8272 != AS_FILTER_PERMIT
)
8275 if (type
== bgp_show_type_route_map
) {
8276 struct route_map
*rmap
= output_arg
;
8277 struct bgp_path_info binfo
;
8278 struct attr dummy_attr
;
8281 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8283 binfo
.peer
= ri
->peer
;
8284 binfo
.attr
= &dummy_attr
;
8286 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8288 if (ret
== RMAP_DENYMATCH
)
8291 if (type
== bgp_show_type_neighbor
8292 || type
== bgp_show_type_flap_neighbor
8293 || type
== bgp_show_type_damp_neighbor
) {
8294 union sockunion
*su
= output_arg
;
8296 if (ri
->peer
== NULL
8297 || ri
->peer
->su_remote
== NULL
8298 || !sockunion_same(ri
->peer
->su_remote
, su
))
8301 if (type
== bgp_show_type_cidr_only
) {
8302 uint32_t destination
;
8304 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8305 if (IN_CLASSC(destination
)
8306 && rn
->p
.prefixlen
== 24)
8308 if (IN_CLASSB(destination
)
8309 && rn
->p
.prefixlen
== 16)
8311 if (IN_CLASSA(destination
)
8312 && rn
->p
.prefixlen
== 8)
8315 if (type
== bgp_show_type_prefix_longer
) {
8317 if (!prefix_match(p
, &rn
->p
))
8320 if (type
== bgp_show_type_community_all
) {
8321 if (!ri
->attr
->community
)
8324 if (type
== bgp_show_type_community
) {
8325 struct community
*com
= output_arg
;
8327 if (!ri
->attr
->community
8328 || !community_match(ri
->attr
->community
,
8332 if (type
== bgp_show_type_community_exact
) {
8333 struct community
*com
= output_arg
;
8335 if (!ri
->attr
->community
8336 || !community_cmp(ri
->attr
->community
, com
))
8339 if (type
== bgp_show_type_community_list
) {
8340 struct community_list
*list
= output_arg
;
8342 if (!community_list_match(ri
->attr
->community
,
8346 if (type
== bgp_show_type_community_list_exact
) {
8347 struct community_list
*list
= output_arg
;
8349 if (!community_list_exact_match(
8350 ri
->attr
->community
, list
))
8353 if (type
== bgp_show_type_lcommunity
) {
8354 struct lcommunity
*lcom
= output_arg
;
8356 if (!ri
->attr
->lcommunity
8357 || !lcommunity_match(ri
->attr
->lcommunity
,
8361 if (type
== bgp_show_type_lcommunity_list
) {
8362 struct community_list
*list
= output_arg
;
8364 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8368 if (type
== bgp_show_type_lcommunity_all
) {
8369 if (!ri
->attr
->lcommunity
)
8372 if (type
== bgp_show_type_dampend_paths
8373 || type
== bgp_show_type_damp_neighbor
) {
8374 if (!CHECK_FLAG(ri
->flags
, BGP_PATH_DAMPED
)
8375 || CHECK_FLAG(ri
->flags
, BGP_PATH_HISTORY
))
8379 if (!use_json
&& header
) {
8380 vty_out(vty
, "BGP table version is %" PRIu64
8381 ", local router ID is %s, vrf id ",
8383 inet_ntoa(bgp
->router_id
));
8384 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8385 vty_out(vty
, "%s", VRFID_NONE_STR
);
8387 vty_out(vty
, "%u", bgp
->vrf_id
);
8389 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8390 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8391 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8392 if (type
== bgp_show_type_dampend_paths
8393 || type
== bgp_show_type_damp_neighbor
)
8394 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8395 else if (type
== bgp_show_type_flap_statistics
8396 || type
== bgp_show_type_flap_neighbor
)
8397 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8399 vty_out(vty
, BGP_SHOW_HEADER
);
8402 if (rd
!= NULL
&& !display
&& !output_count
) {
8405 "Route Distinguisher: %s\n",
8408 if (type
== bgp_show_type_dampend_paths
8409 || type
== bgp_show_type_damp_neighbor
)
8410 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8411 safi
, use_json
, json_paths
);
8412 else if (type
== bgp_show_type_flap_statistics
8413 || type
== bgp_show_type_flap_neighbor
)
8414 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8415 safi
, use_json
, json_paths
);
8417 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8428 sprintf(buf2
, "%s/%d",
8429 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8432 vty_out(vty
, "\"%s\": ", buf2
);
8434 vty_out(vty
, ",\"%s\": ", buf2
);
8437 json_object_to_json_string(json_paths
));
8438 json_object_free(json_paths
);
8445 output_count
+= *output_cum
;
8446 *output_cum
= output_count
;
8449 total_count
+= *total_cum
;
8450 *total_cum
= total_count
;
8454 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8458 for (i
= 0; i
< *json_header_depth
; ++i
)
8459 vty_out(vty
, " } ");
8463 /* No route is displayed */
8464 if (output_count
== 0) {
8465 if (type
== bgp_show_type_normal
)
8467 "No BGP prefixes displayed, %ld exist\n",
8471 "\nDisplayed %ld routes and %ld total paths\n",
8472 output_count
, total_count
);
8479 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8480 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8481 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8483 struct bgp_node
*rn
, *next
;
8484 unsigned long output_cum
= 0;
8485 unsigned long total_cum
= 0;
8486 unsigned long json_header_depth
= 0;
8489 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8491 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8492 next
= bgp_route_next(rn
);
8493 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8495 if (rn
->info
!= NULL
) {
8496 struct prefix_rd prd
;
8497 char rd
[RD_ADDRSTRLEN
];
8499 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8500 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8501 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8502 output_arg
, use_json
, rd
, next
== NULL
,
8503 &output_cum
, &total_cum
,
8504 &json_header_depth
);
8510 if (output_cum
== 0)
8511 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8515 "\nDisplayed %ld routes and %ld total paths\n",
8516 output_cum
, total_cum
);
8520 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8521 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8523 struct bgp_table
*table
;
8524 unsigned long json_header_depth
= 0;
8527 bgp
= bgp_get_default();
8532 vty_out(vty
, "No BGP process is configured\n");
8534 vty_out(vty
, "{}\n");
8538 table
= bgp
->rib
[afi
][safi
];
8539 /* use MPLS and ENCAP specific shows until they are merged */
8540 if (safi
== SAFI_MPLS_VPN
) {
8541 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8542 output_arg
, use_json
);
8545 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8546 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8547 output_arg
, use_json
,
8550 /* labeled-unicast routes live in the unicast table */
8551 else if (safi
== SAFI_LABELED_UNICAST
)
8552 safi
= SAFI_UNICAST
;
8554 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8555 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8558 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8559 safi_t safi
, bool use_json
)
8561 struct listnode
*node
, *nnode
;
8564 bool route_output
= false;
8567 vty_out(vty
, "{\n");
8569 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8570 route_output
= true;
8573 vty_out(vty
, ",\n");
8577 vty_out(vty
, "\"%s\":",
8578 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8582 vty_out(vty
, "\nInstance %s:\n",
8583 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8587 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8592 vty_out(vty
, "}\n");
8593 else if (!route_output
)
8594 vty_out(vty
, "%% BGP instance not found\n");
8597 /* Header of detailed BGP route information */
8598 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8599 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8600 afi_t afi
, safi_t safi
, json_object
*json
)
8602 struct bgp_path_info
*ri
;
8605 struct listnode
*node
, *nnode
;
8606 char buf1
[RD_ADDRSTRLEN
];
8607 char buf2
[INET6_ADDRSTRLEN
];
8608 char buf3
[EVPN_ROUTE_STRLEN
];
8609 char prefix_str
[BUFSIZ
];
8614 int route_filter_translated_v4
= 0;
8615 int route_filter_v4
= 0;
8616 int route_filter_translated_v6
= 0;
8617 int route_filter_v6
= 0;
8620 int accept_own_nexthop
= 0;
8623 int no_advertise
= 0;
8627 int has_valid_label
= 0;
8628 mpls_label_t label
= 0;
8629 json_object
*json_adv_to
= NULL
;
8632 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8634 if (has_valid_label
)
8635 label
= label_pton(&rn
->local_label
);
8638 if (has_valid_label
)
8639 json_object_int_add(json
, "localLabel", label
);
8641 json_object_string_add(
8643 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8645 if (safi
== SAFI_EVPN
)
8646 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8647 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8650 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8651 buf3
, sizeof(buf3
)));
8653 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8654 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8655 ? prefix_rd2str(prd
, buf1
,
8658 safi
== SAFI_MPLS_VPN
? ":" : "",
8659 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8663 if (has_valid_label
)
8664 vty_out(vty
, "Local label: %d\n", label
);
8665 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8666 vty_out(vty
, "not allocated\n");
8669 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8671 if (CHECK_FLAG(ri
->flags
, BGP_PATH_SELECTED
)) {
8673 if (ri
->extra
&& ri
->extra
->suppress
)
8676 if (ri
->attr
->community
== NULL
)
8679 no_advertise
+= community_include(
8680 ri
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
8681 no_export
+= community_include(ri
->attr
->community
,
8682 COMMUNITY_NO_EXPORT
);
8683 local_as
+= community_include(ri
->attr
->community
,
8684 COMMUNITY_LOCAL_AS
);
8685 accept_own
+= community_include(ri
->attr
->community
,
8686 COMMUNITY_ACCEPT_OWN
);
8687 route_filter_translated_v4
+= community_include(
8688 ri
->attr
->community
,
8689 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
8690 route_filter_translated_v6
+= community_include(
8691 ri
->attr
->community
,
8692 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
8693 route_filter_v4
+= community_include(
8694 ri
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
8695 route_filter_v6
+= community_include(
8696 ri
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
8697 llgr_stale
+= community_include(ri
->attr
->community
,
8698 COMMUNITY_LLGR_STALE
);
8699 no_llgr
+= community_include(ri
->attr
->community
,
8701 accept_own_nexthop
+=
8702 community_include(ri
->attr
->community
,
8703 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
8704 blackhole
+= community_include(ri
->attr
->community
,
8705 COMMUNITY_BLACKHOLE
);
8706 no_peer
+= community_include(ri
->attr
->community
,
8712 vty_out(vty
, "Paths: (%d available", count
);
8714 vty_out(vty
, ", best #%d", best
);
8715 if (safi
== SAFI_UNICAST
)
8716 vty_out(vty
, ", table %s",
8718 == BGP_INSTANCE_TYPE_DEFAULT
)
8719 ? "Default-IP-Routing-Table"
8722 vty_out(vty
, ", no best path");
8726 ", accept own local route exported and imported in different VRF");
8727 else if (route_filter_translated_v4
)
8729 ", mark translated RTs for VPNv4 route filtering");
8730 else if (route_filter_v4
)
8732 ", attach RT as-is for VPNv4 route filtering");
8733 else if (route_filter_translated_v6
)
8735 ", mark translated RTs for VPNv6 route filtering");
8736 else if (route_filter_v6
)
8738 ", attach RT as-is for VPNv6 route filtering");
8739 else if (llgr_stale
)
8741 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
8744 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
8745 else if (accept_own_nexthop
)
8747 ", accept local nexthop");
8749 vty_out(vty
, ", inform peer to blackhole prefix");
8751 vty_out(vty
, ", not advertised to EBGP peer");
8752 else if (no_advertise
)
8753 vty_out(vty
, ", not advertised to any peer");
8755 vty_out(vty
, ", not advertised outside local AS");
8758 ", inform EBGP peer not to advertise to their EBGP peers");
8762 ", Advertisements suppressed by an aggregate.");
8763 vty_out(vty
, ")\n");
8766 /* If we are not using addpath then we can display Advertised to and
8768 * show what peers we advertised the bestpath to. If we are using
8770 * though then we must display Advertised to on a path-by-path basis. */
8771 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8772 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8773 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8774 if (json
&& !json_adv_to
)
8775 json_adv_to
= json_object_new_object();
8777 route_vty_out_advertised_to(
8779 " Advertised to non peer-group peers:\n ",
8786 json_object_object_add(json
, "advertisedTo",
8791 vty_out(vty
, " Not advertised to any peer");
8797 /* Display specified route of BGP table. */
8798 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8799 struct bgp_table
*rib
, const char *ip_str
,
8800 afi_t afi
, safi_t safi
,
8801 struct prefix_rd
*prd
, int prefix_check
,
8802 enum bgp_path_type pathtype
, bool use_json
)
8807 struct prefix match
;
8808 struct bgp_node
*rn
;
8809 struct bgp_node
*rm
;
8810 struct bgp_path_info
*ri
;
8811 struct bgp_table
*table
;
8812 json_object
*json
= NULL
;
8813 json_object
*json_paths
= NULL
;
8815 /* Check IP address argument. */
8816 ret
= str2prefix(ip_str
, &match
);
8818 vty_out(vty
, "address is malformed\n");
8822 match
.family
= afi2family(afi
);
8825 json
= json_object_new_object();
8826 json_paths
= json_object_new_array();
8829 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8830 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8831 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8834 if ((table
= rn
->info
) == NULL
)
8839 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8843 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8844 bgp_unlock_node(rm
);
8848 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8850 route_vty_out_detail_header(
8852 (struct prefix_rd
*)&rn
->p
,
8853 AFI_IP
, safi
, json
);
8858 if (pathtype
== BGP_PATH_SHOW_ALL
8859 || (pathtype
== BGP_PATH_SHOW_BESTPATH
8860 && CHECK_FLAG(ri
->flags
,
8862 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
8863 && (CHECK_FLAG(ri
->flags
,
8865 || CHECK_FLAG(ri
->flags
,
8866 BGP_PATH_SELECTED
))))
8867 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8872 bgp_unlock_node(rm
);
8874 } else if (safi
== SAFI_FLOWSPEC
) {
8875 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
8876 &match
, prefix_check
,
8883 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8885 || rn
->p
.prefixlen
== match
.prefixlen
) {
8886 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8888 route_vty_out_detail_header(
8889 vty
, bgp
, rn
, NULL
, afi
,
8895 if (pathtype
== BGP_PATH_SHOW_ALL
8897 == BGP_PATH_SHOW_BESTPATH
8902 == BGP_PATH_SHOW_MULTIPATH
8908 BGP_PATH_SELECTED
))))
8909 route_vty_out_detail(
8910 vty
, bgp
, &rn
->p
, ri
,
8911 afi
, safi
, json_paths
);
8915 bgp_unlock_node(rn
);
8921 json_object_object_add(json
, "paths", json_paths
);
8923 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8924 json
, JSON_C_TO_STRING_PRETTY
));
8925 json_object_free(json
);
8928 vty_out(vty
, "%% Network not in table\n");
8936 /* Display specified route of Main RIB */
8937 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8938 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8939 int prefix_check
, enum bgp_path_type pathtype
,
8943 bgp
= bgp_get_default();
8946 vty_out(vty
, "No BGP process is configured\n");
8948 vty_out(vty
, "{}\n");
8953 /* labeled-unicast routes live in the unicast table */
8954 if (safi
== SAFI_LABELED_UNICAST
)
8955 safi
= SAFI_UNICAST
;
8957 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8958 afi
, safi
, prd
, prefix_check
, pathtype
,
8962 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8963 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8966 struct lcommunity
*lcom
;
8972 b
= buffer_new(1024);
8973 for (i
= 0; i
< argc
; i
++) {
8975 buffer_putc(b
, ' ');
8977 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8979 buffer_putstr(b
, argv
[i
]->arg
);
8983 buffer_putc(b
, '\0');
8985 str
= buffer_getstr(b
);
8988 lcom
= lcommunity_str2com(str
);
8989 XFREE(MTYPE_TMP
, str
);
8991 vty_out(vty
, "%% Large-community malformed\n");
8995 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8999 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9000 const char *lcom
, afi_t afi
, safi_t safi
,
9003 struct community_list
*list
;
9005 list
= community_list_lookup(bgp_clist
, lcom
,
9006 LARGE_COMMUNITY_LIST_MASTER
);
9008 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9013 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9017 DEFUN (show_ip_bgp_large_community_list
,
9018 show_ip_bgp_large_community_list_cmd
,
9019 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9023 BGP_INSTANCE_HELP_STR
9025 BGP_SAFI_WITH_LABEL_HELP_STR
9026 "Display routes matching the large-community-list\n"
9027 "large-community-list number\n"
9028 "large-community-list name\n"
9032 afi_t afi
= AFI_IP6
;
9033 safi_t safi
= SAFI_UNICAST
;
9036 if (argv_find(argv
, argc
, "ip", &idx
))
9038 if (argv_find(argv
, argc
, "view", &idx
)
9039 || argv_find(argv
, argc
, "vrf", &idx
))
9040 vrf
= argv
[++idx
]->arg
;
9041 if (argv_find(argv
, argc
, "ipv4", &idx
)
9042 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9043 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9044 if (argv_find(argv
, argc
, "unicast", &idx
)
9045 || argv_find(argv
, argc
, "multicast", &idx
))
9046 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9049 bool uj
= use_json(argc
, argv
);
9051 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9053 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9057 argv_find(argv
, argc
, "large-community-list", &idx
);
9058 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9061 DEFUN (show_ip_bgp_large_community
,
9062 show_ip_bgp_large_community_cmd
,
9063 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9067 BGP_INSTANCE_HELP_STR
9069 BGP_SAFI_WITH_LABEL_HELP_STR
9070 "Display routes matching the large-communities\n"
9071 "List of large-community numbers\n"
9075 afi_t afi
= AFI_IP6
;
9076 safi_t safi
= SAFI_UNICAST
;
9079 if (argv_find(argv
, argc
, "ip", &idx
))
9081 if (argv_find(argv
, argc
, "view", &idx
)
9082 || argv_find(argv
, argc
, "vrf", &idx
))
9083 vrf
= argv
[++idx
]->arg
;
9084 if (argv_find(argv
, argc
, "ipv4", &idx
)
9085 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9086 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9087 if (argv_find(argv
, argc
, "unicast", &idx
)
9088 || argv_find(argv
, argc
, "multicast", &idx
))
9089 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9092 bool uj
= use_json(argc
, argv
);
9094 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9096 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9100 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9101 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9103 return bgp_show(vty
, bgp
, afi
, safi
,
9104 bgp_show_type_lcommunity_all
, NULL
, uj
);
9107 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9111 /* BGP route print out function without JSON */
9114 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9115 <dampening <parameters>\
9120 |community-list <(1-500)|WORD> [exact-match]\
9121 |A.B.C.D/M longer-prefixes\
9122 |X:X::X:X/M longer-prefixes\
9127 BGP_INSTANCE_HELP_STR
9129 BGP_SAFI_WITH_LABEL_HELP_STR
9130 "Display detailed information about dampening\n"
9131 "Display detail of configured dampening parameters\n"
9132 "Display routes matching the route-map\n"
9133 "A route-map to match on\n"
9134 "Display routes conforming to the prefix-list\n"
9135 "Prefix-list name\n"
9136 "Display routes conforming to the filter-list\n"
9137 "Regular expression access list name\n"
9138 "BGP RIB advertisement statistics\n"
9139 "Display routes matching the community-list\n"
9140 "community-list number\n"
9141 "community-list name\n"
9142 "Exact match of the communities\n"
9144 "Display route and more specific routes\n"
9146 "Display route and more specific routes\n")
9148 afi_t afi
= AFI_IP6
;
9149 safi_t safi
= SAFI_UNICAST
;
9150 int exact_match
= 0;
9151 struct bgp
*bgp
= NULL
;
9154 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9159 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9160 if (argv_find(argv
, argc
, "parameters", &idx
))
9161 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9164 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9165 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9166 safi
, bgp_show_type_prefix_list
);
9168 if (argv_find(argv
, argc
, "filter-list", &idx
))
9169 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9170 safi
, bgp_show_type_filter_list
);
9172 if (argv_find(argv
, argc
, "statistics", &idx
))
9173 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9175 if (argv_find(argv
, argc
, "route-map", &idx
))
9176 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9177 safi
, bgp_show_type_route_map
);
9179 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9180 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9181 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9183 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9184 exact_match
, afi
, safi
);
9187 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9188 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9189 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9191 bgp_show_type_prefix_longer
);
9196 /* BGP route print out function with JSON */
9197 DEFUN (show_ip_bgp_json
,
9198 show_ip_bgp_json_cmd
,
9199 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9201 |dampening <flap-statistics|dampened-paths>\
9202 |community [AA:NN|local-AS|no-advertise|no-export\
9203 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9204 |accept-own|accept-own-nexthop|route-filter-v6\
9205 |route-filter-v4|route-filter-translated-v6\
9206 |route-filter-translated-v4] [exact-match]\
9211 BGP_INSTANCE_HELP_STR
9213 BGP_SAFI_WITH_LABEL_HELP_STR
9214 "Display only routes with non-natural netmasks\n"
9215 "Display detailed information about dampening\n"
9216 "Display flap statistics of routes\n"
9217 "Display paths suppressed due to dampening\n"
9218 "Display routes matching the communities\n"
9220 "Do not send outside local AS (well-known community)\n"
9221 "Do not advertise to any peer (well-known community)\n"
9222 "Do not export to next AS (well-known community)\n"
9223 "Graceful shutdown (well-known community)\n"
9224 "Do not export to any peer (well-known community)\n"
9225 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9226 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9227 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9228 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9229 "Should accept VPN route with local nexthop (well-known community)\n"
9230 "RT VPNv6 route filtering (well-known community)\n"
9231 "RT VPNv4 route filtering (well-known community)\n"
9232 "RT translated VPNv6 route filtering (well-known community)\n"
9233 "RT translated VPNv4 route filtering (well-known community)\n"
9234 "Exact match of the communities\n"
9237 afi_t afi
= AFI_IP6
;
9238 safi_t safi
= SAFI_UNICAST
;
9239 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9240 struct bgp
*bgp
= NULL
;
9242 int exact_match
= 0;
9243 bool uj
= use_json(argc
, argv
);
9248 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9253 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9254 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9257 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9258 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9259 return bgp_show(vty
, bgp
, afi
, safi
,
9260 bgp_show_type_dampend_paths
, NULL
, uj
);
9261 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9262 return bgp_show(vty
, bgp
, afi
, safi
,
9263 bgp_show_type_flap_statistics
, NULL
,
9267 if (argv_find(argv
, argc
, "community", &idx
)) {
9268 char *maybecomm
= idx
+ 1 < argc
? argv
[idx
+ 1]->text
: NULL
;
9269 char *community
= NULL
;
9271 if (maybecomm
&& !strmatch(maybecomm
, "json")
9272 && !strmatch(maybecomm
, "exact-match"))
9273 community
= maybecomm
;
9275 if (argv_find(argv
, argc
, "exact-match", &idx
))
9279 return bgp_show_community(vty
, bgp
, community
,
9280 exact_match
, afi
, safi
, uj
);
9282 return (bgp_show(vty
, bgp
, afi
, safi
,
9283 bgp_show_type_community_all
, NULL
,
9287 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9290 DEFUN (show_ip_bgp_route
,
9291 show_ip_bgp_route_cmd
,
9292 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9293 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9297 BGP_INSTANCE_HELP_STR
9299 BGP_SAFI_WITH_LABEL_HELP_STR
9300 "Network in the BGP routing table to display\n"
9302 "Network in the BGP routing table to display\n"
9304 "Display only the bestpath\n"
9305 "Display only multipaths\n"
9308 int prefix_check
= 0;
9310 afi_t afi
= AFI_IP6
;
9311 safi_t safi
= SAFI_UNICAST
;
9312 char *prefix
= NULL
;
9313 struct bgp
*bgp
= NULL
;
9314 enum bgp_path_type path_type
;
9315 bool uj
= use_json(argc
, argv
);
9319 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9326 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9330 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9331 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9332 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9334 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9335 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9338 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9339 && afi
!= AFI_IP6
) {
9341 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9344 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9347 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9351 prefix
= argv
[idx
]->arg
;
9353 /* [<bestpath|multipath>] */
9354 if (argv_find(argv
, argc
, "bestpath", &idx
))
9355 path_type
= BGP_PATH_SHOW_BESTPATH
;
9356 else if (argv_find(argv
, argc
, "multipath", &idx
))
9357 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9359 path_type
= BGP_PATH_SHOW_ALL
;
9361 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9365 DEFUN (show_ip_bgp_regexp
,
9366 show_ip_bgp_regexp_cmd
,
9367 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9371 BGP_INSTANCE_HELP_STR
9373 BGP_SAFI_WITH_LABEL_HELP_STR
9374 "Display routes matching the AS path regular expression\n"
9375 "A regular-expression to match the BGP AS paths\n")
9377 afi_t afi
= AFI_IP6
;
9378 safi_t safi
= SAFI_UNICAST
;
9379 struct bgp
*bgp
= NULL
;
9382 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9387 // get index of regex
9388 argv_find(argv
, argc
, "regexp", &idx
);
9391 char *regstr
= argv_concat(argv
, argc
, idx
);
9392 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9393 bgp_show_type_regexp
);
9394 XFREE(MTYPE_TMP
, regstr
);
9398 DEFUN (show_ip_bgp_instance_all
,
9399 show_ip_bgp_instance_all_cmd
,
9400 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9404 BGP_INSTANCE_ALL_HELP_STR
9406 BGP_SAFI_WITH_LABEL_HELP_STR
9410 safi_t safi
= SAFI_UNICAST
;
9411 struct bgp
*bgp
= NULL
;
9413 bool uj
= use_json(argc
, argv
);
9418 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9423 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9427 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9428 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9433 regex
= bgp_regcomp(regstr
);
9435 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9439 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9440 bgp_regex_free(regex
);
9444 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9445 const char *prefix_list_str
, afi_t afi
,
9446 safi_t safi
, enum bgp_show_type type
)
9448 struct prefix_list
*plist
;
9450 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9451 if (plist
== NULL
) {
9452 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9457 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9460 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9461 const char *filter
, afi_t afi
, safi_t safi
,
9462 enum bgp_show_type type
)
9464 struct as_list
*as_list
;
9466 as_list
= as_list_lookup(filter
);
9467 if (as_list
== NULL
) {
9468 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9473 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9476 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9477 const char *rmap_str
, afi_t afi
, safi_t safi
,
9478 enum bgp_show_type type
)
9480 struct route_map
*rmap
;
9482 rmap
= route_map_lookup_by_name(rmap_str
);
9484 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9488 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9491 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9492 const char *comstr
, int exact
, afi_t afi
,
9493 safi_t safi
, bool use_json
)
9495 struct community
*com
;
9498 com
= community_str2com(comstr
);
9500 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9504 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9505 (exact
? bgp_show_type_community_exact
9506 : bgp_show_type_community
),
9508 community_free(com
);
9513 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9514 const char *com
, int exact
, afi_t afi
,
9517 struct community_list
*list
;
9519 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9521 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9525 return bgp_show(vty
, bgp
, afi
, safi
,
9526 (exact
? bgp_show_type_community_list_exact
9527 : bgp_show_type_community_list
),
9531 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9532 const char *prefix
, afi_t afi
, safi_t safi
,
9533 enum bgp_show_type type
)
9540 ret
= str2prefix(prefix
, p
);
9542 vty_out(vty
, "%% Malformed Prefix\n");
9546 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9551 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9552 const char *ip_str
, bool use_json
)
9558 /* Get peer sockunion. */
9559 ret
= str2sockunion(ip_str
, &su
);
9561 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9563 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9567 json_object
*json_no
= NULL
;
9568 json_no
= json_object_new_object();
9569 json_object_string_add(
9571 "malformedAddressOrName",
9573 vty_out(vty
, "%s\n",
9574 json_object_to_json_string_ext(
9576 JSON_C_TO_STRING_PRETTY
));
9577 json_object_free(json_no
);
9580 "%% Malformed address or name: %s\n",
9588 /* Peer structure lookup. */
9589 peer
= peer_lookup(bgp
, &su
);
9592 json_object
*json_no
= NULL
;
9593 json_no
= json_object_new_object();
9594 json_object_string_add(json_no
, "warning",
9595 "No such neighbor in this view/vrf");
9596 vty_out(vty
, "%s\n",
9597 json_object_to_json_string_ext(
9598 json_no
, JSON_C_TO_STRING_PRETTY
));
9599 json_object_free(json_no
);
9601 vty_out(vty
, "No such neighbor in this view/vrf\n");
9609 BGP_STATS_MAXBITLEN
= 0,
9613 BGP_STATS_UNAGGREGATEABLE
,
9614 BGP_STATS_MAX_AGGREGATEABLE
,
9615 BGP_STATS_AGGREGATES
,
9617 BGP_STATS_ASPATH_COUNT
,
9618 BGP_STATS_ASPATH_MAXHOPS
,
9619 BGP_STATS_ASPATH_TOTHOPS
,
9620 BGP_STATS_ASPATH_MAXSIZE
,
9621 BGP_STATS_ASPATH_TOTSIZE
,
9622 BGP_STATS_ASN_HIGHEST
,
9626 static const char *table_stats_strs
[] = {
9627 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9628 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9629 [BGP_STATS_RIB
] = "Total Advertisements",
9630 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9631 [BGP_STATS_MAX_AGGREGATEABLE
] =
9632 "Maximum aggregateable prefixes",
9633 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9634 [BGP_STATS_SPACE
] = "Address space advertised",
9635 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9636 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9637 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9638 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9639 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9640 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9641 [BGP_STATS_MAX
] = NULL
,
9644 struct bgp_table_stats
{
9645 struct bgp_table
*table
;
9646 unsigned long long counts
[BGP_STATS_MAX
];
9651 #define TALLY_SIGFIG 100000
9652 static unsigned long
9653 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9655 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9656 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9657 unsigned long ret
= newtot
/ count
;
9659 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9666 static int bgp_table_stats_walker(struct thread
*t
)
9668 struct bgp_node
*rn
;
9669 struct bgp_node
*top
;
9670 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9671 unsigned int space
= 0;
9673 if (!(top
= bgp_table_top(ts
->table
)))
9676 switch (top
->p
.family
) {
9678 space
= IPV4_MAX_BITLEN
;
9681 space
= IPV6_MAX_BITLEN
;
9685 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9687 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9688 struct bgp_path_info
*ri
;
9689 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9690 unsigned int rinum
= 0;
9698 ts
->counts
[BGP_STATS_PREFIXES
]++;
9699 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9702 ts
->counts
[BGP_STATS_AVGPLEN
]
9703 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9704 ts
->counts
[BGP_STATS_AVGPLEN
],
9708 /* check if the prefix is included by any other announcements */
9709 while (prn
&& !prn
->info
)
9710 prn
= bgp_node_parent_nolock(prn
);
9712 if (prn
== NULL
|| prn
== top
) {
9713 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9714 /* announced address space */
9717 pow(2.0, space
- rn
->p
.prefixlen
);
9718 } else if (prn
->info
)
9719 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9721 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9723 ts
->counts
[BGP_STATS_RIB
]++;
9726 && (CHECK_FLAG(ri
->attr
->flag
,
9728 BGP_ATTR_ATOMIC_AGGREGATE
))))
9729 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9732 if (ri
->attr
&& ri
->attr
->aspath
) {
9734 aspath_count_hops(ri
->attr
->aspath
);
9736 aspath_size(ri
->attr
->aspath
);
9737 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9739 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9741 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9742 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9745 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9746 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9749 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9750 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9752 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9753 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9754 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9756 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9757 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9758 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9761 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9762 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9770 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9773 struct bgp_table_stats ts
;
9776 if (!bgp
->rib
[afi
][safi
]) {
9777 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9782 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9784 /* labeled-unicast routes live in the unicast table */
9785 if (safi
== SAFI_LABELED_UNICAST
)
9786 safi
= SAFI_UNICAST
;
9788 memset(&ts
, 0, sizeof(ts
));
9789 ts
.table
= bgp
->rib
[afi
][safi
];
9790 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9792 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9793 if (!table_stats_strs
[i
])
9798 case BGP_STATS_ASPATH_AVGHOPS
:
9799 case BGP_STATS_ASPATH_AVGSIZE
:
9800 case BGP_STATS_AVGPLEN
:
9801 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9802 vty_out (vty
, "%12.2f",
9803 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9806 case BGP_STATS_ASPATH_TOTHOPS
:
9807 case BGP_STATS_ASPATH_TOTSIZE
:
9808 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9809 vty_out(vty
, "%12.2f",
9811 ? (float)ts
.counts
[i
]
9813 [BGP_STATS_ASPATH_COUNT
]
9816 case BGP_STATS_TOTPLEN
:
9817 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9818 vty_out(vty
, "%12.2f",
9820 ? (float)ts
.counts
[i
]
9822 [BGP_STATS_PREFIXES
]
9825 case BGP_STATS_SPACE
:
9826 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9827 vty_out(vty
, "%12g\n", ts
.total_space
);
9829 if (afi
== AFI_IP6
) {
9830 vty_out(vty
, "%30s: ", "/32 equivalent ");
9831 vty_out(vty
, "%12g\n",
9832 ts
.total_space
* pow(2.0, -128 + 32));
9833 vty_out(vty
, "%30s: ", "/48 equivalent ");
9834 vty_out(vty
, "%12g\n",
9835 ts
.total_space
* pow(2.0, -128 + 48));
9837 vty_out(vty
, "%30s: ", "% announced ");
9838 vty_out(vty
, "%12.2f\n",
9839 ts
.total_space
* 100. * pow(2.0, -32));
9840 vty_out(vty
, "%30s: ", "/8 equivalent ");
9841 vty_out(vty
, "%12.2f\n",
9842 ts
.total_space
* pow(2.0, -32 + 8));
9843 vty_out(vty
, "%30s: ", "/24 equivalent ");
9844 vty_out(vty
, "%12.2f\n",
9845 ts
.total_space
* pow(2.0, -32 + 24));
9849 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9850 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9867 PCOUNT_PFCNT
, /* the figure we display to users */
9871 static const char *pcount_strs
[] = {
9872 [PCOUNT_ADJ_IN
] = "Adj-in",
9873 [PCOUNT_DAMPED
] = "Damped",
9874 [PCOUNT_REMOVED
] = "Removed",
9875 [PCOUNT_HISTORY
] = "History",
9876 [PCOUNT_STALE
] = "Stale",
9877 [PCOUNT_VALID
] = "Valid",
9878 [PCOUNT_ALL
] = "All RIB",
9879 [PCOUNT_COUNTED
] = "PfxCt counted",
9880 [PCOUNT_PFCNT
] = "Useable",
9881 [PCOUNT_MAX
] = NULL
,
9884 struct peer_pcounts
{
9885 unsigned int count
[PCOUNT_MAX
];
9886 const struct peer
*peer
;
9887 const struct bgp_table
*table
;
9890 static int bgp_peer_count_walker(struct thread
*t
)
9892 struct bgp_node
*rn
;
9893 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9894 const struct peer
*peer
= pc
->peer
;
9896 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9897 struct bgp_adj_in
*ain
;
9898 struct bgp_path_info
*ri
;
9900 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9901 if (ain
->peer
== peer
)
9902 pc
->count
[PCOUNT_ADJ_IN
]++;
9904 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9905 if (ri
->peer
!= peer
)
9908 pc
->count
[PCOUNT_ALL
]++;
9910 if (CHECK_FLAG(ri
->flags
, BGP_PATH_DAMPED
))
9911 pc
->count
[PCOUNT_DAMPED
]++;
9912 if (CHECK_FLAG(ri
->flags
, BGP_PATH_HISTORY
))
9913 pc
->count
[PCOUNT_HISTORY
]++;
9914 if (CHECK_FLAG(ri
->flags
, BGP_PATH_REMOVED
))
9915 pc
->count
[PCOUNT_REMOVED
]++;
9916 if (CHECK_FLAG(ri
->flags
, BGP_PATH_STALE
))
9917 pc
->count
[PCOUNT_STALE
]++;
9918 if (CHECK_FLAG(ri
->flags
, BGP_PATH_VALID
))
9919 pc
->count
[PCOUNT_VALID
]++;
9920 if (!CHECK_FLAG(ri
->flags
, BGP_PATH_UNUSEABLE
))
9921 pc
->count
[PCOUNT_PFCNT
]++;
9923 if (CHECK_FLAG(ri
->flags
, BGP_PATH_COUNTED
)) {
9924 pc
->count
[PCOUNT_COUNTED
]++;
9925 if (CHECK_FLAG(ri
->flags
, BGP_PATH_UNUSEABLE
))
9928 "Attempting to count but flags say it is unusable");
9930 if (!CHECK_FLAG(ri
->flags
, BGP_PATH_UNUSEABLE
))
9933 "Not counted but flags say we should");
9940 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9941 safi_t safi
, bool use_json
)
9943 struct peer_pcounts pcounts
= {.peer
= peer
};
9945 json_object
*json
= NULL
;
9946 json_object
*json_loop
= NULL
;
9949 json
= json_object_new_object();
9950 json_loop
= json_object_new_object();
9953 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9954 || !peer
->bgp
->rib
[afi
][safi
]) {
9956 json_object_string_add(
9958 "No such neighbor or address family");
9959 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9960 json_object_free(json
);
9962 vty_out(vty
, "%% No such neighbor or address family\n");
9967 memset(&pcounts
, 0, sizeof(pcounts
));
9968 pcounts
.peer
= peer
;
9969 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9971 /* in-place call via thread subsystem so as to record execution time
9972 * stats for the thread-walk (i.e. ensure this can't be blamed on
9973 * on just vty_read()).
9975 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9978 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9979 json_object_string_add(json
, "multiProtocol",
9980 afi_safi_print(afi
, safi
));
9981 json_object_int_add(json
, "pfxCounter",
9982 peer
->pcount
[afi
][safi
]);
9984 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9985 json_object_int_add(json_loop
, pcount_strs
[i
],
9988 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9990 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9991 json_object_string_add(json
, "pfxctDriftFor",
9993 json_object_string_add(
9994 json
, "recommended",
9995 "Please report this bug, with the above command output");
9997 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9998 json
, JSON_C_TO_STRING_PRETTY
));
9999 json_object_free(json
);
10003 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10004 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10005 peer
->hostname
, peer
->host
,
10006 afi_safi_print(afi
, safi
));
10008 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10009 afi_safi_print(afi
, safi
));
10012 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10013 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10015 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10016 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10019 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10020 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10022 "Please report this bug, with the above command output\n");
10026 return CMD_SUCCESS
;
10029 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10030 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10031 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10032 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10036 BGP_INSTANCE_HELP_STR
10039 "Detailed information on TCP and BGP neighbor connections\n"
10040 "Neighbor to display information about\n"
10041 "Neighbor to display information about\n"
10042 "Neighbor on BGP configured interface\n"
10043 "Display detailed prefix count information\n"
10046 afi_t afi
= AFI_IP6
;
10047 safi_t safi
= SAFI_UNICAST
;
10050 struct bgp
*bgp
= NULL
;
10051 bool uj
= use_json(argc
, argv
);
10056 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10059 return CMD_WARNING
;
10061 argv_find(argv
, argc
, "neighbors", &idx
);
10062 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10064 return CMD_WARNING
;
10066 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10069 #ifdef KEEP_OLD_VPN_COMMANDS
10070 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10071 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10072 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10077 "Display information about all VPNv4 NLRIs\n"
10078 "Detailed information on TCP and BGP neighbor connections\n"
10079 "Neighbor to display information about\n"
10080 "Neighbor to display information about\n"
10081 "Neighbor on BGP configured interface\n"
10082 "Display detailed prefix count information\n"
10087 bool uj
= use_json(argc
, argv
);
10089 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10091 return CMD_WARNING
;
10093 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10096 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10097 show_ip_bgp_vpn_all_route_prefix_cmd
,
10098 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10103 "Display information about all VPNv4 NLRIs\n"
10104 "Network in the BGP routing table to display\n"
10105 "Network in the BGP routing table to display\n"
10109 char *network
= NULL
;
10110 struct bgp
*bgp
= bgp_get_default();
10112 vty_out(vty
, "Can't find default instance\n");
10113 return CMD_WARNING
;
10116 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10117 network
= argv
[idx
]->arg
;
10118 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10119 network
= argv
[idx
]->arg
;
10121 vty_out(vty
, "Unable to figure out Network\n");
10122 return CMD_WARNING
;
10125 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10126 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10128 #endif /* KEEP_OLD_VPN_COMMANDS */
10130 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10131 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10132 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10138 "Display information about all EVPN NLRIs\n"
10139 "Network in the BGP routing table to display\n"
10140 "Network in the BGP routing table to display\n"
10144 char *network
= NULL
;
10146 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10147 network
= argv
[idx
]->arg
;
10148 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10149 network
= argv
[idx
]->arg
;
10151 vty_out(vty
, "Unable to figure out Network\n");
10152 return CMD_WARNING
;
10154 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10155 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10158 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10159 safi_t safi
, enum bgp_show_adj_route_type type
,
10160 const char *rmap_name
, bool use_json
,
10163 struct bgp_table
*table
;
10164 struct bgp_adj_in
*ain
;
10165 struct bgp_adj_out
*adj
;
10166 unsigned long output_count
;
10167 unsigned long filtered_count
;
10168 struct bgp_node
*rn
;
10174 struct update_subgroup
*subgrp
;
10175 json_object
*json_scode
= NULL
;
10176 json_object
*json_ocode
= NULL
;
10177 json_object
*json_ar
= NULL
;
10178 struct peer_af
*paf
;
10179 bool route_filtered
;
10182 json_scode
= json_object_new_object();
10183 json_ocode
= json_object_new_object();
10184 json_ar
= json_object_new_object();
10186 json_object_string_add(json_scode
, "suppressed", "s");
10187 json_object_string_add(json_scode
, "damped", "d");
10188 json_object_string_add(json_scode
, "history", "h");
10189 json_object_string_add(json_scode
, "valid", "*");
10190 json_object_string_add(json_scode
, "best", ">");
10191 json_object_string_add(json_scode
, "multipath", "=");
10192 json_object_string_add(json_scode
, "internal", "i");
10193 json_object_string_add(json_scode
, "ribFailure", "r");
10194 json_object_string_add(json_scode
, "stale", "S");
10195 json_object_string_add(json_scode
, "removed", "R");
10197 json_object_string_add(json_ocode
, "igp", "i");
10198 json_object_string_add(json_ocode
, "egp", "e");
10199 json_object_string_add(json_ocode
, "incomplete", "?");
10206 json_object_string_add(json
, "alert", "no BGP");
10207 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10208 json_object_free(json
);
10210 vty_out(vty
, "%% No bgp\n");
10214 table
= bgp
->rib
[afi
][safi
];
10216 output_count
= filtered_count
= 0;
10217 subgrp
= peer_subgroup(peer
, afi
, safi
);
10219 if (type
== bgp_show_adj_route_advertised
&& subgrp
10220 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10222 json_object_int_add(json
, "bgpTableVersion",
10224 json_object_string_add(json
, "bgpLocalRouterId",
10225 inet_ntoa(bgp
->router_id
));
10226 json_object_object_add(json
, "bgpStatusCodes",
10228 json_object_object_add(json
, "bgpOriginCodes",
10230 json_object_string_add(
10231 json
, "bgpOriginatingDefaultNetwork",
10232 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10234 vty_out(vty
, "BGP table version is %" PRIu64
10235 ", local router ID is %s, vrf id ",
10236 table
->version
, inet_ntoa(bgp
->router_id
));
10237 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10238 vty_out(vty
, "%s", VRFID_NONE_STR
);
10240 vty_out(vty
, "%u", bgp
->vrf_id
);
10241 vty_out(vty
, "\n");
10242 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10243 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10244 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10246 vty_out(vty
, "Originating default network %s\n\n",
10247 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10252 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10253 if (type
== bgp_show_adj_route_received
10254 || type
== bgp_show_adj_route_filtered
) {
10255 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10256 if (ain
->peer
!= peer
|| !ain
->attr
)
10261 json_object_int_add(
10262 json
, "bgpTableVersion",
10264 json_object_string_add(
10266 "bgpLocalRouterId",
10269 json_object_object_add(
10270 json
, "bgpStatusCodes",
10272 json_object_object_add(
10273 json
, "bgpOriginCodes",
10277 "BGP table version is 0, local router ID is %s, vrf id ",
10280 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10286 vty_out(vty
, "\n");
10288 BGP_SHOW_SCODE_HEADER
);
10290 BGP_SHOW_NCODE_HEADER
);
10292 BGP_SHOW_OCODE_HEADER
);
10298 vty_out(vty
, BGP_SHOW_HEADER
);
10302 bgp_attr_dup(&attr
, ain
->attr
);
10303 route_filtered
= false;
10305 /* Filter prefix using distribute list,
10306 * filter list or prefix list
10308 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10309 safi
)) == FILTER_DENY
)
10310 route_filtered
= true;
10312 /* Filter prefix using route-map */
10313 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10314 afi
, safi
, rmap_name
);
10316 if (type
== bgp_show_adj_route_filtered
&&
10317 !route_filtered
&& ret
!= RMAP_DENY
) {
10318 bgp_attr_undup(&attr
, ain
->attr
);
10322 if (type
== bgp_show_adj_route_received
&&
10323 (route_filtered
|| ret
== RMAP_DENY
))
10326 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10327 use_json
, json_ar
);
10328 bgp_attr_undup(&attr
, ain
->attr
);
10331 } else if (type
== bgp_show_adj_route_advertised
) {
10332 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10333 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10334 if (paf
->peer
!= peer
|| !adj
->attr
)
10339 json_object_int_add(
10343 json_object_string_add(
10345 "bgpLocalRouterId",
10348 json_object_object_add(
10352 json_object_object_add(
10358 "BGP table version is %" PRIu64
10359 ", local router ID is %s, vrf id ",
10372 vty_out(vty
, "\n");
10374 BGP_SHOW_SCODE_HEADER
);
10376 BGP_SHOW_NCODE_HEADER
);
10378 BGP_SHOW_OCODE_HEADER
);
10389 bgp_attr_dup(&attr
, adj
->attr
);
10390 ret
= bgp_output_modifier(
10391 peer
, &rn
->p
, &attr
, afi
, safi
,
10394 if (ret
!= RMAP_DENY
) {
10395 route_vty_out_tmp(vty
, &rn
->p
,
10404 bgp_attr_undup(&attr
, adj
->attr
);
10410 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10411 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10412 json_object_int_add(json
, "filteredPrefixCounter",
10415 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10416 json
, JSON_C_TO_STRING_PRETTY
));
10417 json_object_free(json
);
10418 } else if (output_count
> 0) {
10419 if (filtered_count
> 0)
10421 "\nTotal number of prefixes %ld (%ld filtered)\n",
10422 output_count
, filtered_count
);
10424 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10429 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10430 safi_t safi
, enum bgp_show_adj_route_type type
,
10431 const char *rmap_name
, bool use_json
)
10433 json_object
*json
= NULL
;
10436 json
= json_object_new_object();
10438 /* labeled-unicast routes live in the unicast table */
10439 if (safi
== SAFI_LABELED_UNICAST
)
10440 safi
= SAFI_UNICAST
;
10442 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10444 json_object_string_add(
10446 "No such neighbor or address family");
10447 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10448 json_object_free(json
);
10450 vty_out(vty
, "%% No such neighbor or address family\n");
10452 return CMD_WARNING
;
10455 if ((type
== bgp_show_adj_route_received
10456 || type
== bgp_show_adj_route_filtered
)
10457 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10458 PEER_FLAG_SOFT_RECONFIG
)) {
10460 json_object_string_add(
10462 "Inbound soft reconfiguration not enabled");
10463 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10464 json_object_free(json
);
10467 "%% Inbound soft reconfiguration not enabled\n");
10469 return CMD_WARNING
;
10472 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10474 return CMD_SUCCESS
;
10477 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10478 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10479 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10480 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10484 BGP_INSTANCE_HELP_STR
10486 BGP_SAFI_WITH_LABEL_HELP_STR
10487 "Detailed information on TCP and BGP neighbor connections\n"
10488 "Neighbor to display information about\n"
10489 "Neighbor to display information about\n"
10490 "Neighbor on BGP configured interface\n"
10491 "Display the routes advertised to a BGP neighbor\n"
10492 "Display the received routes from neighbor\n"
10493 "Display the filtered routes received from neighbor\n"
10494 "Route-map to modify the attributes\n"
10495 "Name of the route map\n"
10498 afi_t afi
= AFI_IP6
;
10499 safi_t safi
= SAFI_UNICAST
;
10500 char *rmap_name
= NULL
;
10501 char *peerstr
= NULL
;
10502 struct bgp
*bgp
= NULL
;
10504 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10506 bool uj
= use_json(argc
, argv
);
10511 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10514 return CMD_WARNING
;
10516 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10517 argv_find(argv
, argc
, "neighbors", &idx
);
10518 peerstr
= argv
[++idx
]->arg
;
10520 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10522 return CMD_WARNING
;
10524 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10525 type
= bgp_show_adj_route_advertised
;
10526 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10527 type
= bgp_show_adj_route_received
;
10528 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10529 type
= bgp_show_adj_route_filtered
;
10531 if (argv_find(argv
, argc
, "route-map", &idx
))
10532 rmap_name
= argv
[++idx
]->arg
;
10534 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10537 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10538 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10539 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10545 "Address Family modifier\n"
10546 "Detailed information on TCP and BGP neighbor connections\n"
10547 "Neighbor to display information about\n"
10548 "Neighbor to display information about\n"
10549 "Neighbor on BGP configured interface\n"
10550 "Display information received from a BGP neighbor\n"
10551 "Display the prefixlist filter\n"
10554 afi_t afi
= AFI_IP6
;
10555 safi_t safi
= SAFI_UNICAST
;
10556 char *peerstr
= NULL
;
10559 union sockunion su
;
10565 /* show [ip] bgp */
10566 if (argv_find(argv
, argc
, "ip", &idx
))
10568 /* [<ipv4|ipv6> [unicast]] */
10569 if (argv_find(argv
, argc
, "ipv4", &idx
))
10571 if (argv_find(argv
, argc
, "ipv6", &idx
))
10573 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10574 argv_find(argv
, argc
, "neighbors", &idx
);
10575 peerstr
= argv
[++idx
]->arg
;
10577 bool uj
= use_json(argc
, argv
);
10579 ret
= str2sockunion(peerstr
, &su
);
10581 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10584 vty_out(vty
, "{}\n");
10587 "%% Malformed address or name: %s\n",
10589 return CMD_WARNING
;
10592 peer
= peer_lookup(NULL
, &su
);
10595 vty_out(vty
, "{}\n");
10597 vty_out(vty
, "No peer\n");
10598 return CMD_WARNING
;
10602 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10603 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10606 vty_out(vty
, "Address Family: %s\n",
10607 afi_safi_print(afi
, safi
));
10608 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10611 vty_out(vty
, "{}\n");
10613 vty_out(vty
, "No functional output\n");
10616 return CMD_SUCCESS
;
10619 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10620 afi_t afi
, safi_t safi
,
10621 enum bgp_show_type type
, bool use_json
)
10623 /* labeled-unicast routes live in the unicast table */
10624 if (safi
== SAFI_LABELED_UNICAST
)
10625 safi
= SAFI_UNICAST
;
10627 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10629 json_object
*json_no
= NULL
;
10630 json_no
= json_object_new_object();
10631 json_object_string_add(
10632 json_no
, "warning",
10633 "No such neighbor or address family");
10634 vty_out(vty
, "%s\n",
10635 json_object_to_json_string(json_no
));
10636 json_object_free(json_no
);
10638 vty_out(vty
, "%% No such neighbor or address family\n");
10639 return CMD_WARNING
;
10642 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10645 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10646 show_ip_bgp_flowspec_routes_detailed_cmd
,
10647 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10651 BGP_INSTANCE_HELP_STR
10654 "Detailed information on flowspec entries\n"
10657 afi_t afi
= AFI_IP
;
10658 safi_t safi
= SAFI_UNICAST
;
10659 struct bgp
*bgp
= NULL
;
10661 bool uj
= use_json(argc
, argv
);
10666 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10669 return CMD_WARNING
;
10671 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
10674 DEFUN (show_ip_bgp_neighbor_routes
,
10675 show_ip_bgp_neighbor_routes_cmd
,
10676 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10677 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10681 BGP_INSTANCE_HELP_STR
10683 BGP_SAFI_WITH_LABEL_HELP_STR
10684 "Detailed information on TCP and BGP neighbor connections\n"
10685 "Neighbor to display information about\n"
10686 "Neighbor to display information about\n"
10687 "Neighbor on BGP configured interface\n"
10688 "Display flap statistics of the routes learned from neighbor\n"
10689 "Display the dampened routes received from neighbor\n"
10690 "Display routes learned from neighbor\n"
10693 char *peerstr
= NULL
;
10694 struct bgp
*bgp
= NULL
;
10695 afi_t afi
= AFI_IP6
;
10696 safi_t safi
= SAFI_UNICAST
;
10698 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10700 bool uj
= use_json(argc
, argv
);
10705 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10708 return CMD_WARNING
;
10710 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10711 argv_find(argv
, argc
, "neighbors", &idx
);
10712 peerstr
= argv
[++idx
]->arg
;
10714 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10716 return CMD_WARNING
;
10718 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10719 sh_type
= bgp_show_type_flap_neighbor
;
10720 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10721 sh_type
= bgp_show_type_damp_neighbor
;
10722 else if (argv_find(argv
, argc
, "routes", &idx
))
10723 sh_type
= bgp_show_type_neighbor
;
10725 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10728 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10730 struct bgp_distance
{
10731 /* Distance value for the IP source prefix. */
10734 /* Name of the access-list to be matched. */
10738 DEFUN (show_bgp_afi_vpn_rd_route
,
10739 show_bgp_afi_vpn_rd_route_cmd
,
10740 "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]",
10744 "Address Family modifier\n"
10745 "Display information for a route distinguisher\n"
10746 "Route Distinguisher\n"
10747 "Network in the BGP routing table to display\n"
10748 "Network in the BGP routing table to display\n"
10752 struct prefix_rd prd
;
10753 afi_t afi
= AFI_MAX
;
10756 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10757 vty_out(vty
, "%% Malformed Address Family\n");
10758 return CMD_WARNING
;
10761 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10763 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10764 return CMD_WARNING
;
10767 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10768 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10771 static struct bgp_distance
*bgp_distance_new(void)
10773 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10776 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10778 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10781 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10782 const char *ip_str
, const char *access_list_str
)
10789 struct bgp_node
*rn
;
10790 struct bgp_distance
*bdistance
;
10792 afi
= bgp_node_afi(vty
);
10793 safi
= bgp_node_safi(vty
);
10795 ret
= str2prefix(ip_str
, &p
);
10797 vty_out(vty
, "Malformed prefix\n");
10798 return CMD_WARNING_CONFIG_FAILED
;
10801 distance
= atoi(distance_str
);
10803 /* Get BGP distance node. */
10804 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10805 bdistance
= bgp_distance_get_node(rn
);
10807 bgp_unlock_node(rn
);
10809 bdistance
= bgp_distance_new();
10810 bgp_distance_set_node_info(rn
, bdistance
);
10813 /* Set distance value. */
10814 bdistance
->distance
= distance
;
10816 /* Reset access-list configuration. */
10817 if (bdistance
->access_list
) {
10818 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10819 bdistance
->access_list
= NULL
;
10821 if (access_list_str
)
10822 bdistance
->access_list
=
10823 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10825 return CMD_SUCCESS
;
10828 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10829 const char *ip_str
, const char *access_list_str
)
10836 struct bgp_node
*rn
;
10837 struct bgp_distance
*bdistance
;
10839 afi
= bgp_node_afi(vty
);
10840 safi
= bgp_node_safi(vty
);
10842 ret
= str2prefix(ip_str
, &p
);
10844 vty_out(vty
, "Malformed prefix\n");
10845 return CMD_WARNING_CONFIG_FAILED
;
10848 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10849 (struct prefix
*)&p
);
10851 vty_out(vty
, "Can't find specified prefix\n");
10852 return CMD_WARNING_CONFIG_FAILED
;
10855 bdistance
= bgp_distance_get_node(rn
);
10856 distance
= atoi(distance_str
);
10858 if (bdistance
->distance
!= distance
) {
10859 vty_out(vty
, "Distance does not match configured\n");
10860 return CMD_WARNING_CONFIG_FAILED
;
10863 if (bdistance
->access_list
)
10864 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10865 bgp_distance_free(bdistance
);
10868 bgp_unlock_node(rn
);
10869 bgp_unlock_node(rn
);
10871 return CMD_SUCCESS
;
10874 /* Apply BGP information to distance method. */
10875 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*rinfo
,
10876 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
10878 struct bgp_node
*rn
;
10881 struct bgp_distance
*bdistance
;
10882 struct access_list
*alist
;
10883 struct bgp_static
*bgp_static
;
10888 peer
= rinfo
->peer
;
10890 /* Check source address. */
10891 sockunion2hostprefix(&peer
->su
, &q
);
10892 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10894 bdistance
= bgp_distance_get_node(rn
);
10895 bgp_unlock_node(rn
);
10897 if (bdistance
->access_list
) {
10898 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10900 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10901 return bdistance
->distance
;
10903 return bdistance
->distance
;
10906 /* Backdoor check. */
10907 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10909 bgp_static
= bgp_static_get_node_info(rn
);
10910 bgp_unlock_node(rn
);
10912 if (bgp_static
->backdoor
) {
10913 if (bgp
->distance_local
[afi
][safi
])
10914 return bgp
->distance_local
[afi
][safi
];
10916 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10920 if (peer
->sort
== BGP_PEER_EBGP
) {
10921 if (bgp
->distance_ebgp
[afi
][safi
])
10922 return bgp
->distance_ebgp
[afi
][safi
];
10923 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10925 if (bgp
->distance_ibgp
[afi
][safi
])
10926 return bgp
->distance_ibgp
[afi
][safi
];
10927 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10931 DEFUN (bgp_distance
,
10933 "distance bgp (1-255) (1-255) (1-255)",
10934 "Define an administrative distance\n"
10936 "Distance for routes external to the AS\n"
10937 "Distance for routes internal to the AS\n"
10938 "Distance for local routes\n")
10940 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10941 int idx_number
= 2;
10942 int idx_number_2
= 3;
10943 int idx_number_3
= 4;
10947 afi
= bgp_node_afi(vty
);
10948 safi
= bgp_node_safi(vty
);
10950 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10951 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10952 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10953 return CMD_SUCCESS
;
10956 DEFUN (no_bgp_distance
,
10957 no_bgp_distance_cmd
,
10958 "no distance bgp [(1-255) (1-255) (1-255)]",
10960 "Define an administrative distance\n"
10962 "Distance for routes external to the AS\n"
10963 "Distance for routes internal to the AS\n"
10964 "Distance for local routes\n")
10966 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10970 afi
= bgp_node_afi(vty
);
10971 safi
= bgp_node_safi(vty
);
10973 bgp
->distance_ebgp
[afi
][safi
] = 0;
10974 bgp
->distance_ibgp
[afi
][safi
] = 0;
10975 bgp
->distance_local
[afi
][safi
] = 0;
10976 return CMD_SUCCESS
;
10980 DEFUN (bgp_distance_source
,
10981 bgp_distance_source_cmd
,
10982 "distance (1-255) A.B.C.D/M",
10983 "Define an administrative distance\n"
10984 "Administrative distance\n"
10985 "IP source prefix\n")
10987 int idx_number
= 1;
10988 int idx_ipv4_prefixlen
= 2;
10989 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10990 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10991 return CMD_SUCCESS
;
10994 DEFUN (no_bgp_distance_source
,
10995 no_bgp_distance_source_cmd
,
10996 "no distance (1-255) A.B.C.D/M",
10998 "Define an administrative distance\n"
10999 "Administrative distance\n"
11000 "IP source prefix\n")
11002 int idx_number
= 2;
11003 int idx_ipv4_prefixlen
= 3;
11004 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11005 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11006 return CMD_SUCCESS
;
11009 DEFUN (bgp_distance_source_access_list
,
11010 bgp_distance_source_access_list_cmd
,
11011 "distance (1-255) A.B.C.D/M WORD",
11012 "Define an administrative distance\n"
11013 "Administrative distance\n"
11014 "IP source prefix\n"
11015 "Access list name\n")
11017 int idx_number
= 1;
11018 int idx_ipv4_prefixlen
= 2;
11020 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11021 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11022 return CMD_SUCCESS
;
11025 DEFUN (no_bgp_distance_source_access_list
,
11026 no_bgp_distance_source_access_list_cmd
,
11027 "no distance (1-255) A.B.C.D/M WORD",
11029 "Define an administrative distance\n"
11030 "Administrative distance\n"
11031 "IP source prefix\n"
11032 "Access list name\n")
11034 int idx_number
= 2;
11035 int idx_ipv4_prefixlen
= 3;
11037 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11038 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11039 return CMD_SUCCESS
;
11042 DEFUN (ipv6_bgp_distance_source
,
11043 ipv6_bgp_distance_source_cmd
,
11044 "distance (1-255) X:X::X:X/M",
11045 "Define an administrative distance\n"
11046 "Administrative distance\n"
11047 "IP source prefix\n")
11049 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11050 return CMD_SUCCESS
;
11053 DEFUN (no_ipv6_bgp_distance_source
,
11054 no_ipv6_bgp_distance_source_cmd
,
11055 "no distance (1-255) X:X::X:X/M",
11057 "Define an administrative distance\n"
11058 "Administrative distance\n"
11059 "IP source prefix\n")
11061 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11062 return CMD_SUCCESS
;
11065 DEFUN (ipv6_bgp_distance_source_access_list
,
11066 ipv6_bgp_distance_source_access_list_cmd
,
11067 "distance (1-255) X:X::X:X/M WORD",
11068 "Define an administrative distance\n"
11069 "Administrative distance\n"
11070 "IP source prefix\n"
11071 "Access list name\n")
11073 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11074 return CMD_SUCCESS
;
11077 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11078 no_ipv6_bgp_distance_source_access_list_cmd
,
11079 "no distance (1-255) X:X::X:X/M WORD",
11081 "Define an administrative distance\n"
11082 "Administrative distance\n"
11083 "IP source prefix\n"
11084 "Access list name\n")
11086 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11087 return CMD_SUCCESS
;
11090 DEFUN (bgp_damp_set
,
11092 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11093 "BGP Specific commands\n"
11094 "Enable route-flap dampening\n"
11095 "Half-life time for the penalty\n"
11096 "Value to start reusing a route\n"
11097 "Value to start suppressing a route\n"
11098 "Maximum duration to suppress a stable route\n")
11100 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11101 int idx_half_life
= 2;
11103 int idx_suppress
= 4;
11104 int idx_max_suppress
= 5;
11105 int half
= DEFAULT_HALF_LIFE
* 60;
11106 int reuse
= DEFAULT_REUSE
;
11107 int suppress
= DEFAULT_SUPPRESS
;
11108 int max
= 4 * half
;
11111 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11112 reuse
= atoi(argv
[idx_reuse
]->arg
);
11113 suppress
= atoi(argv
[idx_suppress
]->arg
);
11114 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11115 } else if (argc
== 3) {
11116 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11120 if (suppress
< reuse
) {
11122 "Suppress value cannot be less than reuse value \n");
11126 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11127 reuse
, suppress
, max
);
11130 DEFUN (bgp_damp_unset
,
11131 bgp_damp_unset_cmd
,
11132 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11134 "BGP Specific commands\n"
11135 "Enable route-flap dampening\n"
11136 "Half-life time for the penalty\n"
11137 "Value to start reusing a route\n"
11138 "Value to start suppressing a route\n"
11139 "Maximum duration to suppress a stable route\n")
11141 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11142 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11145 /* Display specified route of BGP table. */
11146 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11147 const char *ip_str
, afi_t afi
, safi_t safi
,
11148 struct prefix_rd
*prd
, int prefix_check
)
11151 struct prefix match
;
11152 struct bgp_node
*rn
;
11153 struct bgp_node
*rm
;
11154 struct bgp_path_info
*ri
;
11155 struct bgp_path_info
*ri_temp
;
11157 struct bgp_table
*table
;
11159 /* BGP structure lookup. */
11161 bgp
= bgp_lookup_by_name(view_name
);
11163 vty_out(vty
, "%% Can't find BGP instance %s\n",
11165 return CMD_WARNING
;
11168 bgp
= bgp_get_default();
11170 vty_out(vty
, "%% No BGP process is configured\n");
11171 return CMD_WARNING
;
11175 /* Check IP address argument. */
11176 ret
= str2prefix(ip_str
, &match
);
11178 vty_out(vty
, "%% address is malformed\n");
11179 return CMD_WARNING
;
11182 match
.family
= afi2family(afi
);
11184 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11185 || (safi
== SAFI_EVPN
)) {
11186 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11187 rn
= bgp_route_next(rn
)) {
11188 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11190 if ((table
= rn
->info
) == NULL
)
11192 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11196 || rm
->p
.prefixlen
== match
.prefixlen
) {
11199 if (ri
->extra
&& ri
->extra
->damp_info
) {
11200 ri_temp
= ri
->next
;
11201 bgp_damp_info_free(
11202 ri
->extra
->damp_info
,
11210 bgp_unlock_node(rm
);
11213 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11216 || rn
->p
.prefixlen
== match
.prefixlen
) {
11219 if (ri
->extra
&& ri
->extra
->damp_info
) {
11220 ri_temp
= ri
->next
;
11221 bgp_damp_info_free(
11222 ri
->extra
->damp_info
,
11230 bgp_unlock_node(rn
);
11234 return CMD_SUCCESS
;
11237 DEFUN (clear_ip_bgp_dampening
,
11238 clear_ip_bgp_dampening_cmd
,
11239 "clear ip bgp dampening",
11243 "Clear route flap dampening information\n")
11245 bgp_damp_info_clean();
11246 return CMD_SUCCESS
;
11249 DEFUN (clear_ip_bgp_dampening_prefix
,
11250 clear_ip_bgp_dampening_prefix_cmd
,
11251 "clear ip bgp dampening A.B.C.D/M",
11255 "Clear route flap dampening information\n"
11258 int idx_ipv4_prefixlen
= 4;
11259 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11260 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11263 DEFUN (clear_ip_bgp_dampening_address
,
11264 clear_ip_bgp_dampening_address_cmd
,
11265 "clear ip bgp dampening A.B.C.D",
11269 "Clear route flap dampening information\n"
11270 "Network to clear damping information\n")
11273 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11274 SAFI_UNICAST
, NULL
, 0);
11277 DEFUN (clear_ip_bgp_dampening_address_mask
,
11278 clear_ip_bgp_dampening_address_mask_cmd
,
11279 "clear ip bgp dampening A.B.C.D A.B.C.D",
11283 "Clear route flap dampening information\n"
11284 "Network to clear damping information\n"
11288 int idx_ipv4_2
= 5;
11290 char prefix_str
[BUFSIZ
];
11292 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11295 vty_out(vty
, "%% Inconsistent address and mask\n");
11296 return CMD_WARNING
;
11299 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11303 /* also used for encap safi */
11304 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11305 afi_t afi
, safi_t safi
)
11307 struct bgp_node
*prn
;
11308 struct bgp_node
*rn
;
11309 struct bgp_table
*table
;
11311 struct prefix_rd
*prd
;
11312 struct bgp_static
*bgp_static
;
11313 mpls_label_t label
;
11314 char buf
[SU_ADDRSTRLEN
];
11315 char rdbuf
[RD_ADDRSTRLEN
];
11317 /* Network configuration. */
11318 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11319 prn
= bgp_route_next(prn
)) {
11320 if ((table
= prn
->info
) == NULL
)
11323 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11324 bgp_static
= bgp_static_get_node_info(rn
);
11325 if (bgp_static
== NULL
)
11329 prd
= (struct prefix_rd
*)&prn
->p
;
11331 /* "network" configuration display. */
11332 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11333 label
= decode_label(&bgp_static
->label
);
11335 vty_out(vty
, " network %s/%d rd %s",
11336 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11338 p
->prefixlen
, rdbuf
);
11339 if (safi
== SAFI_MPLS_VPN
)
11340 vty_out(vty
, " label %u", label
);
11342 if (bgp_static
->rmap
.name
)
11343 vty_out(vty
, " route-map %s",
11344 bgp_static
->rmap
.name
);
11346 if (bgp_static
->backdoor
)
11347 vty_out(vty
, " backdoor");
11349 vty_out(vty
, "\n");
11354 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11355 afi_t afi
, safi_t safi
)
11357 struct bgp_node
*prn
;
11358 struct bgp_node
*rn
;
11359 struct bgp_table
*table
;
11361 struct prefix_rd
*prd
;
11362 struct bgp_static
*bgp_static
;
11363 char buf
[PREFIX_STRLEN
* 2];
11364 char buf2
[SU_ADDRSTRLEN
];
11365 char rdbuf
[RD_ADDRSTRLEN
];
11367 /* Network configuration. */
11368 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11369 prn
= bgp_route_next(prn
)) {
11370 if ((table
= prn
->info
) == NULL
)
11373 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11374 bgp_static
= bgp_static_get_node_info(rn
);
11375 if (bgp_static
== NULL
)
11378 char *macrouter
= NULL
;
11381 if (bgp_static
->router_mac
)
11382 macrouter
= prefix_mac2str(
11383 bgp_static
->router_mac
, NULL
, 0);
11384 if (bgp_static
->eth_s_id
)
11385 esi
= esi2str(bgp_static
->eth_s_id
);
11387 prd
= (struct prefix_rd
*)&prn
->p
;
11389 /* "network" configuration display. */
11390 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11391 if (p
->u
.prefix_evpn
.route_type
== 5) {
11392 char local_buf
[PREFIX_STRLEN
];
11393 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11394 struct prefix_evpn
*)p
)
11398 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11399 local_buf
, PREFIX_STRLEN
);
11400 sprintf(buf
, "%s/%u", local_buf
,
11401 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11403 prefix2str(p
, buf
, sizeof(buf
));
11406 if (bgp_static
->gatewayIp
.family
== AF_INET
11407 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11408 inet_ntop(bgp_static
->gatewayIp
.family
,
11409 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11412 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11414 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11415 decode_label(&bgp_static
->label
), esi
, buf2
,
11419 XFREE(MTYPE_TMP
, macrouter
);
11421 XFREE(MTYPE_TMP
, esi
);
11426 /* Configuration of static route announcement and aggregate
11428 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11431 struct bgp_node
*rn
;
11433 struct bgp_static
*bgp_static
;
11434 struct bgp_aggregate
*bgp_aggregate
;
11435 char buf
[SU_ADDRSTRLEN
];
11437 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11438 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11442 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11443 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11447 /* Network configuration. */
11448 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11449 rn
= bgp_route_next(rn
)) {
11450 bgp_static
= bgp_static_get_node_info(rn
);
11451 if (bgp_static
== NULL
)
11456 /* "network" configuration display. */
11457 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11458 uint32_t destination
;
11459 struct in_addr netmask
;
11461 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11462 masklen2ip(p
->prefixlen
, &netmask
);
11463 vty_out(vty
, " network %s",
11464 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11467 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11468 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11469 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11470 || p
->u
.prefix4
.s_addr
== 0) {
11471 /* Natural mask is not display. */
11473 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11475 vty_out(vty
, " network %s/%d",
11476 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11481 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11482 vty_out(vty
, " label-index %u",
11483 bgp_static
->label_index
);
11485 if (bgp_static
->rmap
.name
)
11486 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11488 if (bgp_static
->backdoor
)
11489 vty_out(vty
, " backdoor");
11491 vty_out(vty
, "\n");
11494 /* Aggregate-address configuration. */
11495 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11496 rn
= bgp_route_next(rn
)) {
11497 bgp_aggregate
= bgp_aggregate_get_node_info(rn
);
11498 if (bgp_aggregate
== NULL
)
11503 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11504 struct in_addr netmask
;
11506 masklen2ip(p
->prefixlen
, &netmask
);
11507 vty_out(vty
, " aggregate-address %s %s",
11508 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11510 inet_ntoa(netmask
));
11512 vty_out(vty
, " aggregate-address %s/%d",
11513 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11518 if (bgp_aggregate
->as_set
)
11519 vty_out(vty
, " as-set");
11521 if (bgp_aggregate
->summary_only
)
11522 vty_out(vty
, " summary-only");
11524 vty_out(vty
, "\n");
11528 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11531 struct bgp_node
*rn
;
11532 struct bgp_distance
*bdistance
;
11534 /* Distance configuration. */
11535 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11536 && bgp
->distance_local
[afi
][safi
]
11537 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11538 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11539 || bgp
->distance_local
[afi
][safi
]
11540 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11541 vty_out(vty
, " distance bgp %d %d %d\n",
11542 bgp
->distance_ebgp
[afi
][safi
],
11543 bgp
->distance_ibgp
[afi
][safi
],
11544 bgp
->distance_local
[afi
][safi
]);
11547 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11548 rn
= bgp_route_next(rn
)) {
11549 bdistance
= bgp_distance_get_node(rn
);
11550 if (bdistance
!= NULL
) {
11551 char buf
[PREFIX_STRLEN
];
11553 vty_out(vty
, " distance %d %s %s\n",
11554 bdistance
->distance
,
11555 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11556 bdistance
->access_list
? bdistance
->access_list
11562 /* Allocate routing table structure and install commands. */
11563 void bgp_route_init(void)
11568 /* Init BGP distance table. */
11569 FOREACH_AFI_SAFI (afi
, safi
)
11570 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11572 /* IPv4 BGP commands. */
11573 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11574 install_element(BGP_NODE
, &bgp_network_cmd
);
11575 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11577 install_element(BGP_NODE
, &aggregate_address_cmd
);
11578 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11579 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11580 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11582 /* IPv4 unicast configuration. */
11583 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11584 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11585 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11587 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11588 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11589 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11590 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11592 /* IPv4 multicast configuration. */
11593 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11594 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11595 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11596 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11597 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11598 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11599 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11601 /* IPv4 labeled-unicast configuration. */
11602 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11603 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11604 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11605 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11606 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11608 install_element(VIEW_NODE
,
11609 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11610 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11611 install_element(VIEW_NODE
,
11612 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11613 #ifdef KEEP_OLD_VPN_COMMANDS
11614 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11615 #endif /* KEEP_OLD_VPN_COMMANDS */
11616 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11617 install_element(VIEW_NODE
,
11618 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11620 /* BGP dampening clear commands */
11621 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11622 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11624 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11625 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11628 install_element(ENABLE_NODE
,
11629 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11630 #ifdef KEEP_OLD_VPN_COMMANDS
11631 install_element(ENABLE_NODE
,
11632 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11633 #endif /* KEEP_OLD_VPN_COMMANDS */
11635 /* New config IPv6 BGP commands. */
11636 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11637 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11638 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11640 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11641 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11643 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11645 install_element(BGP_NODE
, &bgp_distance_cmd
);
11646 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11647 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11648 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11649 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11650 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11651 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11652 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11653 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11654 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11655 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11656 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11657 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11658 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11659 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11660 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11661 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11662 install_element(BGP_IPV4M_NODE
,
11663 &no_bgp_distance_source_access_list_cmd
);
11664 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11665 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11666 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11667 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11668 install_element(BGP_IPV6_NODE
,
11669 &ipv6_bgp_distance_source_access_list_cmd
);
11670 install_element(BGP_IPV6_NODE
,
11671 &no_ipv6_bgp_distance_source_access_list_cmd
);
11672 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11673 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11674 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11675 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11676 install_element(BGP_IPV6M_NODE
,
11677 &ipv6_bgp_distance_source_access_list_cmd
);
11678 install_element(BGP_IPV6M_NODE
,
11679 &no_ipv6_bgp_distance_source_access_list_cmd
);
11681 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11682 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11683 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11684 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11686 /* IPv4 Multicast Mode */
11687 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11688 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11690 /* Large Communities */
11691 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11692 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11694 /* show bgp ipv4 flowspec detailed */
11695 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11699 void bgp_route_finish(void)
11704 FOREACH_AFI_SAFI (afi
, safi
) {
11705 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11706 bgp_distance_table
[afi
][safi
] = NULL
;