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
35 #include "sockunion.h"
38 #include "workqueue.h"
42 #include "lib_errors.h"
44 #include "bgpd/bgpd.h"
45 #include "bgpd/bgp_table.h"
46 #include "bgpd/bgp_route.h"
47 #include "bgpd/bgp_attr.h"
48 #include "bgpd/bgp_debug.h"
49 #include "bgpd/bgp_errors.h"
50 #include "bgpd/bgp_aspath.h"
51 #include "bgpd/bgp_regex.h"
52 #include "bgpd/bgp_community.h"
53 #include "bgpd/bgp_ecommunity.h"
54 #include "bgpd/bgp_lcommunity.h"
55 #include "bgpd/bgp_clist.h"
56 #include "bgpd/bgp_packet.h"
57 #include "bgpd/bgp_filter.h"
58 #include "bgpd/bgp_fsm.h"
59 #include "bgpd/bgp_mplsvpn.h"
60 #include "bgpd/bgp_nexthop.h"
61 #include "bgpd/bgp_damp.h"
62 #include "bgpd/bgp_advertise.h"
63 #include "bgpd/bgp_zebra.h"
64 #include "bgpd/bgp_vty.h"
65 #include "bgpd/bgp_mpath.h"
66 #include "bgpd/bgp_nht.h"
67 #include "bgpd/bgp_updgrp.h"
68 #include "bgpd/bgp_label.h"
69 #include "bgpd/bgp_addpath.h"
70 #include "bgpd/bgp_mac.h"
73 #include "bgpd/rfapi/rfapi_backend.h"
74 #include "bgpd/rfapi/vnc_import_bgp.h"
75 #include "bgpd/rfapi/vnc_export_bgp.h"
77 #include "bgpd/bgp_encap_types.h"
78 #include "bgpd/bgp_encap_tlv.h"
79 #include "bgpd/bgp_evpn.h"
80 #include "bgpd/bgp_evpn_vty.h"
81 #include "bgpd/bgp_flowspec.h"
82 #include "bgpd/bgp_flowspec_util.h"
83 #include "bgpd/bgp_pbr.h"
85 #ifndef VTYSH_EXTRACT_PL
86 #include "bgpd/bgp_route_clippy.c"
89 /* Extern from bgp_dump.c */
90 extern const char *bgp_origin_str
[];
91 extern const char *bgp_origin_long_str
[];
94 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
95 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
96 static const struct message bgp_pmsi_tnltype_str
[] = {
97 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
98 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
99 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
100 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
101 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
102 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
103 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
104 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
108 #define VRFID_NONE_STR "-"
110 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
111 safi_t safi
, struct prefix
*p
,
112 struct prefix_rd
*prd
)
115 struct bgp_node
*prn
= NULL
;
121 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
122 || (safi
== SAFI_EVPN
)) {
123 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
125 if (!bgp_node_has_bgp_path_info_data(prn
))
126 bgp_node_set_bgp_table_info(
127 prn
, bgp_table_init(table
->bgp
, afi
, safi
));
129 bgp_unlock_node(prn
);
130 table
= bgp_node_get_bgp_table_info(prn
);
133 rn
= bgp_node_get(table
, p
);
135 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
136 || (safi
== SAFI_EVPN
))
142 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
143 safi_t safi
, struct prefix
*p
,
144 struct prefix_rd
*prd
)
147 struct bgp_node
*prn
= NULL
;
152 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
153 || (safi
== SAFI_EVPN
)) {
154 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
158 if (!bgp_node_has_bgp_path_info_data(prn
)) {
159 bgp_unlock_node(prn
);
163 table
= bgp_node_get_bgp_table_info(prn
);
166 rn
= bgp_node_lookup(table
, p
);
171 /* Allocate bgp_path_info_extra */
172 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
174 struct bgp_path_info_extra
*new;
175 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
176 sizeof(struct bgp_path_info_extra
));
177 new->label
[0] = MPLS_INVALID_LABEL
;
179 new->bgp_fs_pbr
= NULL
;
180 new->bgp_fs_iprule
= NULL
;
184 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
186 struct bgp_path_info_extra
*e
;
188 if (!extra
|| !*extra
)
193 bgp_damp_info_free(e
->damp_info
, 0);
197 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
200 /* FIXME: since multiple e may have the same e->parent
201 * and e->parent->net is holding a refcount for each
202 * of them, we need to do some fudging here.
204 * WARNING: if bpi->net->lock drops to 0, bpi may be
205 * freed as well (because bpi->net was holding the
206 * last reference to bpi) => write after free!
210 bpi
= bgp_path_info_lock(bpi
);
211 refcount
= bpi
->net
->lock
- 1;
212 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
215 bgp_path_info_unlock(bpi
);
217 bgp_path_info_unlock(e
->parent
);
222 bgp_unlock(e
->bgp_orig
);
224 if ((*extra
)->bgp_fs_iprule
)
225 list_delete(&((*extra
)->bgp_fs_iprule
));
226 if ((*extra
)->bgp_fs_pbr
)
227 list_delete(&((*extra
)->bgp_fs_pbr
));
228 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
233 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
234 * allocated if required.
236 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
239 pi
->extra
= bgp_path_info_extra_new();
243 /* Free bgp route information. */
244 static void bgp_path_info_free(struct bgp_path_info
*path
)
247 bgp_attr_unintern(&path
->attr
);
249 bgp_unlink_nexthop(path
);
250 bgp_path_info_extra_free(&path
->extra
);
251 bgp_path_info_mpath_free(&path
->mpath
);
253 bgp_addpath_free_info_data(&path
->tx_addpath
,
254 &path
->net
->tx_addpath
);
256 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
258 XFREE(MTYPE_BGP_ROUTE
, path
);
261 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
267 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
269 assert(path
&& path
->lock
> 0);
272 if (path
->lock
== 0) {
274 zlog_debug ("%s: unlocked and freeing", __func__
);
275 zlog_backtrace (LOG_DEBUG
);
277 bgp_path_info_free(path
);
284 zlog_debug ("%s: unlocked to 1", __func__
);
285 zlog_backtrace (LOG_DEBUG
);
292 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
294 struct bgp_path_info
*top
;
296 top
= bgp_node_get_bgp_path_info(rn
);
302 bgp_node_set_bgp_path_info(rn
, pi
);
304 bgp_path_info_lock(pi
);
306 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
309 /* Do the actual removal of info from RIB, for use by bgp_process
310 completion callback *only* */
311 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
314 pi
->next
->prev
= pi
->prev
;
316 pi
->prev
->next
= pi
->next
;
318 bgp_node_set_bgp_path_info(rn
, pi
->next
);
320 bgp_path_info_mpath_dequeue(pi
);
321 bgp_path_info_unlock(pi
);
325 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
327 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
328 /* set of previous already took care of pcount */
329 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
332 /* undo the effects of a previous call to bgp_path_info_delete; typically
333 called when a route is deleted and then quickly re-added before the
334 deletion has been processed */
335 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
337 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
338 /* unset of previous already took care of pcount */
339 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
342 /* Adjust pcount as required */
343 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
345 struct bgp_table
*table
;
347 assert(rn
&& bgp_node_table(rn
));
348 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
350 table
= bgp_node_table(rn
);
352 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
355 if (!BGP_PATH_COUNTABLE(pi
)
356 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
358 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
360 /* slight hack, but more robust against errors. */
361 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
362 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
364 flog_err(EC_LIB_DEVELOPMENT
,
365 "Asked to decrement 0 prefix count for peer");
366 } else if (BGP_PATH_COUNTABLE(pi
)
367 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
368 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
369 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
373 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
374 struct bgp_path_info
*pi2
)
376 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
379 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
380 * This is here primarily to keep prefix-count in check.
382 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
385 SET_FLAG(pi
->flags
, flag
);
387 /* early bath if we know it's not a flag that changes countability state
389 if (!CHECK_FLAG(flag
,
390 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
393 bgp_pcount_adjust(rn
, pi
);
396 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
399 UNSET_FLAG(pi
->flags
, flag
);
401 /* early bath if we know it's not a flag that changes countability state
403 if (!CHECK_FLAG(flag
,
404 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
407 bgp_pcount_adjust(rn
, pi
);
410 /* Get MED value. If MED value is missing and "bgp bestpath
411 missing-as-worst" is specified, treat it as the worst value. */
412 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
414 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
417 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
424 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
426 if (pi
->addpath_rx_id
)
427 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
430 sprintf(buf
, "path %s", pi
->peer
->host
);
433 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
435 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
436 struct bgp_path_info
*exist
, int *paths_eq
,
437 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
438 char *pfx_buf
, afi_t afi
, safi_t safi
,
439 enum bgp_path_selection_reason
*reason
)
441 struct attr
*newattr
, *existattr
;
442 bgp_peer_sort_t new_sort
;
443 bgp_peer_sort_t exist_sort
;
449 uint32_t exist_weight
;
450 uint32_t newm
, existm
;
451 struct in_addr new_id
;
452 struct in_addr exist_id
;
455 int internal_as_route
;
458 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
459 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
461 uint32_t exist_mm_seq
;
468 *reason
= bgp_path_selection_none
;
470 zlog_debug("%s: new is NULL", pfx_buf
);
475 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
478 *reason
= bgp_path_selection_first
;
480 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
486 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
487 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
488 pfx_buf
, new_buf
, new->flags
, exist_buf
,
493 existattr
= exist
->attr
;
495 /* For EVPN routes, we cannot just go by local vs remote, we have to
496 * look at the MAC mobility sequence number, if present.
498 if (safi
== SAFI_EVPN
) {
499 /* This is an error condition described in RFC 7432 Section
501 * states that in this scenario "the PE MUST alert the operator"
503 * does not state what other action to take. In order to provide
505 * consistency in this scenario we are going to prefer the path
509 if (newattr
->sticky
!= existattr
->sticky
) {
511 prefix2str(&new->net
->p
, pfx_buf
,
513 * PREFIX2STR_BUFFER
);
514 bgp_path_info_path_with_addpath_rx_str(new,
516 bgp_path_info_path_with_addpath_rx_str(
520 if (newattr
->sticky
&& !existattr
->sticky
) {
521 *reason
= bgp_path_selection_evpn_sticky_mac
;
524 "%s: %s wins over %s due to sticky MAC flag",
525 pfx_buf
, new_buf
, exist_buf
);
529 if (!newattr
->sticky
&& existattr
->sticky
) {
530 *reason
= bgp_path_selection_evpn_sticky_mac
;
533 "%s: %s loses to %s due to sticky MAC flag",
534 pfx_buf
, new_buf
, exist_buf
);
539 new_mm_seq
= mac_mobility_seqnum(newattr
);
540 exist_mm_seq
= mac_mobility_seqnum(existattr
);
542 if (new_mm_seq
> exist_mm_seq
) {
543 *reason
= bgp_path_selection_evpn_seq
;
546 "%s: %s wins over %s due to MM seq %u > %u",
547 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
552 if (new_mm_seq
< exist_mm_seq
) {
553 *reason
= bgp_path_selection_evpn_seq
;
556 "%s: %s loses to %s due to MM seq %u < %u",
557 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
563 * if sequence numbers are the same path with the lowest IP
566 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
568 *reason
= bgp_path_selection_evpn_lower_ip
;
571 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
572 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
573 inet_ntoa(new->attr
->nexthop
));
577 *reason
= bgp_path_selection_evpn_lower_ip
;
580 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
581 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
582 inet_ntoa(new->attr
->nexthop
));
587 /* 1. Weight check. */
588 new_weight
= newattr
->weight
;
589 exist_weight
= existattr
->weight
;
591 if (new_weight
> exist_weight
) {
592 *reason
= bgp_path_selection_weight
;
594 zlog_debug("%s: %s wins over %s due to weight %d > %d",
595 pfx_buf
, new_buf
, exist_buf
, new_weight
,
600 if (new_weight
< exist_weight
) {
601 *reason
= bgp_path_selection_weight
;
603 zlog_debug("%s: %s loses to %s due to weight %d < %d",
604 pfx_buf
, new_buf
, exist_buf
, new_weight
,
609 /* 2. Local preference check. */
610 new_pref
= exist_pref
= bgp
->default_local_pref
;
612 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
613 new_pref
= newattr
->local_pref
;
614 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
615 exist_pref
= existattr
->local_pref
;
617 if (new_pref
> exist_pref
) {
618 *reason
= bgp_path_selection_local_pref
;
621 "%s: %s wins over %s due to localpref %d > %d",
622 pfx_buf
, new_buf
, exist_buf
, new_pref
,
627 if (new_pref
< exist_pref
) {
628 *reason
= bgp_path_selection_local_pref
;
631 "%s: %s loses to %s due to localpref %d < %d",
632 pfx_buf
, new_buf
, exist_buf
, new_pref
,
637 /* 3. Local route check. We prefer:
639 * - BGP_ROUTE_AGGREGATE
640 * - BGP_ROUTE_REDISTRIBUTE
642 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
643 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
644 *reason
= bgp_path_selection_local_route
;
647 "%s: %s wins over %s due to preferred BGP_ROUTE type",
648 pfx_buf
, new_buf
, exist_buf
);
652 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
653 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
654 *reason
= bgp_path_selection_local_route
;
657 "%s: %s loses to %s due to preferred BGP_ROUTE type",
658 pfx_buf
, new_buf
, exist_buf
);
662 /* 4. AS path length check. */
663 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
664 int exist_hops
= aspath_count_hops(existattr
->aspath
);
665 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
667 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
670 aspath_hops
= aspath_count_hops(newattr
->aspath
);
671 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
673 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
674 *reason
= bgp_path_selection_confed_as_path
;
677 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
678 pfx_buf
, new_buf
, exist_buf
,
680 (exist_hops
+ exist_confeds
));
684 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
685 *reason
= bgp_path_selection_confed_as_path
;
688 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
689 pfx_buf
, new_buf
, exist_buf
,
691 (exist_hops
+ exist_confeds
));
695 int newhops
= aspath_count_hops(newattr
->aspath
);
697 if (newhops
< exist_hops
) {
698 *reason
= bgp_path_selection_as_path
;
701 "%s: %s wins over %s due to aspath hopcount %d < %d",
702 pfx_buf
, new_buf
, exist_buf
,
703 newhops
, exist_hops
);
707 if (newhops
> exist_hops
) {
708 *reason
= bgp_path_selection_as_path
;
711 "%s: %s loses to %s due to aspath hopcount %d > %d",
712 pfx_buf
, new_buf
, exist_buf
,
713 newhops
, exist_hops
);
719 /* 5. Origin check. */
720 if (newattr
->origin
< existattr
->origin
) {
721 *reason
= bgp_path_selection_origin
;
723 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
724 pfx_buf
, new_buf
, exist_buf
,
725 bgp_origin_long_str
[newattr
->origin
],
726 bgp_origin_long_str
[existattr
->origin
]);
730 if (newattr
->origin
> existattr
->origin
) {
731 *reason
= bgp_path_selection_origin
;
733 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
734 pfx_buf
, new_buf
, exist_buf
,
735 bgp_origin_long_str
[newattr
->origin
],
736 bgp_origin_long_str
[existattr
->origin
]);
741 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
742 && aspath_count_hops(existattr
->aspath
) == 0);
743 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
744 && aspath_count_confeds(existattr
->aspath
) > 0
745 && aspath_count_hops(newattr
->aspath
) == 0
746 && aspath_count_hops(existattr
->aspath
) == 0);
748 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
749 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
750 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
751 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
752 || internal_as_route
) {
753 new_med
= bgp_med_value(new->attr
, bgp
);
754 exist_med
= bgp_med_value(exist
->attr
, bgp
);
756 if (new_med
< exist_med
) {
757 *reason
= bgp_path_selection_med
;
760 "%s: %s wins over %s due to MED %d < %d",
761 pfx_buf
, new_buf
, exist_buf
, new_med
,
766 if (new_med
> exist_med
) {
767 *reason
= bgp_path_selection_med
;
770 "%s: %s loses to %s due to MED %d > %d",
771 pfx_buf
, new_buf
, exist_buf
, new_med
,
777 /* 7. Peer type check. */
778 new_sort
= new->peer
->sort
;
779 exist_sort
= exist
->peer
->sort
;
781 if (new_sort
== BGP_PEER_EBGP
782 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
783 *reason
= bgp_path_selection_peer
;
786 "%s: %s wins over %s due to eBGP peer > iBGP peer",
787 pfx_buf
, new_buf
, exist_buf
);
791 if (exist_sort
== BGP_PEER_EBGP
792 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
793 *reason
= bgp_path_selection_peer
;
796 "%s: %s loses to %s due to iBGP peer < eBGP peer",
797 pfx_buf
, new_buf
, exist_buf
);
801 /* 8. IGP metric check. */
805 newm
= new->extra
->igpmetric
;
807 existm
= exist
->extra
->igpmetric
;
812 "%s: %s wins over %s due to IGP metric %d < %d",
813 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
820 "%s: %s loses to %s due to IGP metric %d > %d",
821 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
825 /* 9. Same IGP metric. Compare the cluster list length as
826 representative of IGP hops metric. Rewrite the metric value
827 pair (newm, existm) with the cluster list length. Prefer the
828 path with smaller cluster list length. */
829 if (newm
== existm
) {
830 if (peer_sort(new->peer
) == BGP_PEER_IBGP
831 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
832 && (mpath_cfg
== NULL
834 mpath_cfg
->ibgp_flags
,
835 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
836 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
837 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
842 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
843 pfx_buf
, new_buf
, exist_buf
,
851 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
852 pfx_buf
, new_buf
, exist_buf
,
859 /* 10. confed-external vs. confed-internal */
860 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
861 if (new_sort
== BGP_PEER_CONFED
862 && exist_sort
== BGP_PEER_IBGP
) {
863 *reason
= bgp_path_selection_confed
;
866 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
867 pfx_buf
, new_buf
, exist_buf
);
871 if (exist_sort
== BGP_PEER_CONFED
872 && new_sort
== BGP_PEER_IBGP
) {
873 *reason
= bgp_path_selection_confed
;
876 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
877 pfx_buf
, new_buf
, exist_buf
);
882 /* 11. Maximum path check. */
883 if (newm
== existm
) {
884 /* If one path has a label but the other does not, do not treat
885 * them as equals for multipath
887 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
889 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
892 "%s: %s and %s cannot be multipath, one has a label while the other does not",
893 pfx_buf
, new_buf
, exist_buf
);
894 } else if (bgp_flag_check(bgp
,
895 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
898 * For the two paths, all comparison steps till IGP
900 * have succeeded - including AS_PATH hop count. Since
902 * bestpath as-path multipath-relax' knob is on, we
904 * an exact match of AS_PATH. Thus, mark the paths are
906 * That will trigger both these paths to get into the
914 "%s: %s and %s are equal via multipath-relax",
915 pfx_buf
, new_buf
, exist_buf
);
916 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
917 if (aspath_cmp(new->attr
->aspath
,
918 exist
->attr
->aspath
)) {
923 "%s: %s and %s are equal via matching aspaths",
924 pfx_buf
, new_buf
, exist_buf
);
926 } else if (new->peer
->as
== exist
->peer
->as
) {
931 "%s: %s and %s are equal via same remote-as",
932 pfx_buf
, new_buf
, exist_buf
);
936 * TODO: If unequal cost ibgp multipath is enabled we can
937 * mark the paths as equal here instead of returning
942 "%s: %s wins over %s after IGP metric comparison",
943 pfx_buf
, new_buf
, exist_buf
);
946 "%s: %s loses to %s after IGP metric comparison",
947 pfx_buf
, new_buf
, exist_buf
);
949 *reason
= bgp_path_selection_igp_metric
;
953 /* 12. If both paths are external, prefer the path that was received
954 first (the oldest one). This step minimizes route-flap, since a
955 newer path won't displace an older one, even if it was the
956 preferred route based on the additional decision criteria below. */
957 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
958 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
959 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
960 *reason
= bgp_path_selection_older
;
963 "%s: %s wins over %s due to oldest external",
964 pfx_buf
, new_buf
, exist_buf
);
968 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
969 *reason
= bgp_path_selection_older
;
972 "%s: %s loses to %s due to oldest external",
973 pfx_buf
, new_buf
, exist_buf
);
978 /* 13. Router-ID comparision. */
979 /* If one of the paths is "stale", the corresponding peer router-id will
980 * be 0 and would always win over the other path. If originator id is
981 * used for the comparision, it will decide which path is better.
983 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
984 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
986 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
987 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
988 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
990 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
992 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
993 *reason
= bgp_path_selection_router_id
;
996 "%s: %s wins over %s due to Router-ID comparison",
997 pfx_buf
, new_buf
, exist_buf
);
1001 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1002 *reason
= bgp_path_selection_router_id
;
1005 "%s: %s loses to %s due to Router-ID comparison",
1006 pfx_buf
, new_buf
, exist_buf
);
1010 /* 14. Cluster length comparision. */
1011 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1012 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1014 if (new_cluster
< exist_cluster
) {
1015 *reason
= bgp_path_selection_cluster_length
;
1018 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1019 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1024 if (new_cluster
> exist_cluster
) {
1025 *reason
= bgp_path_selection_cluster_length
;
1028 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1029 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1034 /* 15. Neighbor address comparision. */
1035 /* Do this only if neither path is "stale" as stale paths do not have
1036 * valid peer information (as the connection may or may not be up).
1038 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1039 *reason
= bgp_path_selection_stale
;
1042 "%s: %s wins over %s due to latter path being STALE",
1043 pfx_buf
, new_buf
, exist_buf
);
1047 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1048 *reason
= bgp_path_selection_stale
;
1051 "%s: %s loses to %s due to former path being STALE",
1052 pfx_buf
, new_buf
, exist_buf
);
1056 /* locally configured routes to advertise do not have su_remote */
1057 if (new->peer
->su_remote
== NULL
) {
1058 *reason
= bgp_path_selection_local_configured
;
1061 if (exist
->peer
->su_remote
== NULL
) {
1062 *reason
= bgp_path_selection_local_configured
;
1066 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1069 *reason
= bgp_path_selection_neighbor_ip
;
1072 "%s: %s loses to %s due to Neighor IP comparison",
1073 pfx_buf
, new_buf
, exist_buf
);
1078 *reason
= bgp_path_selection_neighbor_ip
;
1081 "%s: %s wins over %s due to Neighor IP comparison",
1082 pfx_buf
, new_buf
, exist_buf
);
1086 *reason
= bgp_path_selection_default
;
1088 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1089 pfx_buf
, new_buf
, exist_buf
);
1094 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1095 * is preferred, or 0 if they are the same (usually will only occur if
1096 * multipath is enabled
1097 * This version is compatible with */
1098 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1099 struct bgp_path_info
*exist
, char *pfx_buf
,
1100 afi_t afi
, safi_t safi
,
1101 enum bgp_path_selection_reason
*reason
)
1105 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1119 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1120 struct attr
*attr
, afi_t afi
,
1123 struct bgp_filter
*filter
;
1125 filter
= &peer
->filter
[afi
][safi
];
1127 #define FILTER_EXIST_WARN(F, f, filter) \
1128 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1129 zlog_debug("%s: Could not find configured input %s-list %s!", \
1130 peer->host, #f, F##_IN_NAME(filter));
1132 if (DISTRIBUTE_IN_NAME(filter
)) {
1133 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1135 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1139 if (PREFIX_LIST_IN_NAME(filter
)) {
1140 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1142 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1146 if (FILTER_LIST_IN_NAME(filter
)) {
1147 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1149 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1154 return FILTER_PERMIT
;
1155 #undef FILTER_EXIST_WARN
1158 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1159 struct attr
*attr
, afi_t afi
,
1162 struct bgp_filter
*filter
;
1164 filter
= &peer
->filter
[afi
][safi
];
1166 #define FILTER_EXIST_WARN(F, f, filter) \
1167 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1168 zlog_debug("%s: Could not find configured output %s-list %s!", \
1169 peer->host, #f, F##_OUT_NAME(filter));
1171 if (DISTRIBUTE_OUT_NAME(filter
)) {
1172 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1174 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1178 if (PREFIX_LIST_OUT_NAME(filter
)) {
1179 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1181 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1186 if (FILTER_LIST_OUT_NAME(filter
)) {
1187 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1189 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1194 return FILTER_PERMIT
;
1195 #undef FILTER_EXIST_WARN
1198 /* If community attribute includes no_export then return 1. */
1199 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1201 if (attr
->community
) {
1202 /* NO_ADVERTISE check. */
1203 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1206 /* NO_EXPORT check. */
1207 if (peer
->sort
== BGP_PEER_EBGP
1208 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1211 /* NO_EXPORT_SUBCONFED check. */
1212 if (peer
->sort
== BGP_PEER_EBGP
1213 || peer
->sort
== BGP_PEER_CONFED
)
1214 if (community_include(attr
->community
,
1215 COMMUNITY_NO_EXPORT_SUBCONFED
))
1221 /* Route reflection loop check. */
1222 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1224 struct in_addr cluster_id
;
1226 if (attr
->cluster
) {
1227 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1228 cluster_id
= peer
->bgp
->cluster_id
;
1230 cluster_id
= peer
->bgp
->router_id
;
1232 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1238 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1239 struct attr
*attr
, afi_t afi
, safi_t safi
,
1240 const char *rmap_name
)
1242 struct bgp_filter
*filter
;
1243 struct bgp_path_info rmap_path
;
1244 route_map_result_t ret
;
1245 struct route_map
*rmap
= NULL
;
1247 filter
= &peer
->filter
[afi
][safi
];
1249 /* Apply default weight value. */
1250 if (peer
->weight
[afi
][safi
])
1251 attr
->weight
= peer
->weight
[afi
][safi
];
1254 rmap
= route_map_lookup_by_name(rmap_name
);
1259 if (ROUTE_MAP_IN_NAME(filter
)) {
1260 rmap
= ROUTE_MAP_IN(filter
);
1267 /* Route map apply. */
1269 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1270 /* Duplicate current value to new strucutre for modification. */
1271 rmap_path
.peer
= peer
;
1272 rmap_path
.attr
= attr
;
1274 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1276 /* Apply BGP route map to the attribute. */
1277 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1279 peer
->rmap_type
= 0;
1281 if (ret
== RMAP_DENYMATCH
)
1287 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1288 struct attr
*attr
, afi_t afi
, safi_t safi
,
1289 const char *rmap_name
)
1291 struct bgp_path_info rmap_path
;
1292 route_map_result_t ret
;
1293 struct route_map
*rmap
= NULL
;
1297 * So if we get to this point and have no rmap_name
1298 * we want to just show the output as it currently
1304 /* Apply default weight value. */
1305 if (peer
->weight
[afi
][safi
])
1306 attr
->weight
= peer
->weight
[afi
][safi
];
1308 rmap
= route_map_lookup_by_name(rmap_name
);
1311 * If we have a route map name and we do not find
1312 * the routemap that means we have an implicit
1318 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1319 /* Route map apply. */
1320 /* Duplicate current value to new strucutre for modification. */
1321 rmap_path
.peer
= peer
;
1322 rmap_path
.attr
= attr
;
1324 rmap_type
= peer
->rmap_type
;
1325 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1327 /* Apply BGP route map to the attribute. */
1328 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1330 peer
->rmap_type
= rmap_type
;
1332 if (ret
== RMAP_DENYMATCH
)
1334 * caller has multiple error paths with bgp_attr_flush()
1341 /* If this is an EBGP peer with remove-private-AS */
1342 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1343 struct peer
*peer
, struct attr
*attr
)
1345 if (peer
->sort
== BGP_PEER_EBGP
1346 && (peer_af_flag_check(peer
, afi
, safi
,
1347 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1348 || peer_af_flag_check(peer
, afi
, safi
,
1349 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1350 || peer_af_flag_check(peer
, afi
, safi
,
1351 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1352 || peer_af_flag_check(peer
, afi
, safi
,
1353 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1354 // Take action on the entire aspath
1355 if (peer_af_flag_check(peer
, afi
, safi
,
1356 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1357 || peer_af_flag_check(peer
, afi
, safi
,
1358 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1359 if (peer_af_flag_check(
1361 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1362 attr
->aspath
= aspath_replace_private_asns(
1363 attr
->aspath
, bgp
->as
);
1365 // The entire aspath consists of private ASNs so create
1367 else if (aspath_private_as_check(attr
->aspath
))
1368 attr
->aspath
= aspath_empty_get();
1370 // There are some public and some private ASNs, remove
1373 attr
->aspath
= aspath_remove_private_asns(
1377 // 'all' was not specified so the entire aspath must be private
1379 // for us to do anything
1380 else if (aspath_private_as_check(attr
->aspath
)) {
1381 if (peer_af_flag_check(
1383 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1384 attr
->aspath
= aspath_replace_private_asns(
1385 attr
->aspath
, bgp
->as
);
1387 attr
->aspath
= aspath_empty_get();
1392 /* If this is an EBGP peer with as-override */
1393 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1394 struct peer
*peer
, struct attr
*attr
)
1396 if (peer
->sort
== BGP_PEER_EBGP
1397 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1398 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1399 attr
->aspath
= aspath_replace_specific_asn(
1400 attr
->aspath
, peer
->as
, bgp
->as
);
1404 void bgp_attr_add_gshut_community(struct attr
*attr
)
1406 struct community
*old
;
1407 struct community
*new;
1408 struct community
*merge
;
1409 struct community
*gshut
;
1411 old
= attr
->community
;
1412 gshut
= community_str2com("graceful-shutdown");
1417 merge
= community_merge(community_dup(old
), gshut
);
1419 if (old
->refcnt
== 0)
1420 community_free(&old
);
1422 new = community_uniq_sort(merge
);
1423 community_free(&merge
);
1425 new = community_dup(gshut
);
1428 community_free(&gshut
);
1429 attr
->community
= new;
1430 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1432 /* When we add the graceful-shutdown community we must also
1433 * lower the local-preference */
1434 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1435 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1439 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1441 if (family
== AF_INET
) {
1442 attr
->nexthop
.s_addr
= 0;
1443 attr
->mp_nexthop_global_in
.s_addr
= 0;
1445 if (family
== AF_INET6
)
1446 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1447 if (family
== AF_EVPN
)
1448 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1451 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1452 struct update_subgroup
*subgrp
, struct prefix
*p
,
1455 struct bgp_filter
*filter
;
1458 struct peer
*onlypeer
;
1460 struct attr
*piattr
;
1461 char buf
[PREFIX_STRLEN
];
1467 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1469 if (DISABLE_BGP_ANNOUNCE
)
1472 afi
= SUBGRP_AFI(subgrp
);
1473 safi
= SUBGRP_SAFI(subgrp
);
1474 peer
= SUBGRP_PEER(subgrp
);
1476 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1477 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1480 filter
= &peer
->filter
[afi
][safi
];
1481 bgp
= SUBGRP_INST(subgrp
);
1482 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1486 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1487 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1488 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1491 * direct and direct_ext type routes originate internally even
1492 * though they can have peer pointers that reference other
1495 prefix2str(p
, buf
, PREFIX_STRLEN
);
1496 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1502 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1503 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1504 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1505 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1507 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1512 /* With addpath we may be asked to TX all kinds of paths so make sure
1514 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1515 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1516 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1520 /* If this is not the bestpath then check to see if there is an enabled
1522 * feature that requires us to advertise it */
1523 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1524 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1529 /* Aggregate-address suppress check. */
1530 if (pi
->extra
&& pi
->extra
->suppress
)
1531 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1536 * If we are doing VRF 2 VRF leaking via the import
1537 * statement, we want to prevent the route going
1538 * off box as that the RT and RD created are localy
1539 * significant and globaly useless.
1541 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1542 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1545 /* If it's labeled safi, make sure the route has a valid label. */
1546 if (safi
== SAFI_LABELED_UNICAST
) {
1547 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1548 if (!bgp_is_valid_label(&label
)) {
1549 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1550 zlog_debug("u%" PRIu64
":s%" PRIu64
1551 " %s/%d is filtered - no label (%p)",
1552 subgrp
->update_group
->id
, subgrp
->id
,
1553 inet_ntop(p
->family
, &p
->u
.prefix
,
1554 buf
, SU_ADDRSTRLEN
),
1555 p
->prefixlen
, &label
);
1560 /* Do not send back route to sender. */
1561 if (onlypeer
&& from
== onlypeer
) {
1565 /* Do not send the default route in the BGP table if the neighbor is
1566 * configured for default-originate */
1567 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1568 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1569 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1571 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1575 /* Transparency check. */
1576 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1577 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1582 /* If community is not disabled check the no-export and local. */
1583 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1584 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1586 "subgrpannouncecheck: community filter check fail");
1590 /* If the attribute has originator-id and it is same as remote
1592 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1593 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1594 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1596 "%s [Update:SEND] %s originator-id is same as "
1599 prefix2str(p
, buf
, sizeof(buf
)));
1603 /* ORF prefix-list filter check */
1604 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1605 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1606 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1607 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1608 if (peer
->orf_plist
[afi
][safi
]) {
1609 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1611 if (bgp_debug_update(NULL
, p
,
1612 subgrp
->update_group
, 0))
1614 "%s [Update:SEND] %s is filtered via ORF",
1622 /* Output filter check. */
1623 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1624 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1625 zlog_debug("%s [Update:SEND] %s is filtered",
1626 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1630 #ifdef BGP_SEND_ASPATH_CHECK
1631 /* AS path loop check. */
1632 if (onlypeer
&& aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1633 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1635 "%s [Update:SEND] suppress announcement to peer AS %u "
1636 "that is part of AS path.",
1637 onlypeer
->host
, onlypeer
->as
);
1640 #endif /* BGP_SEND_ASPATH_CHECK */
1642 /* If we're a CONFED we need to loop check the CONFED ID too */
1643 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1644 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1645 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1647 "%s [Update:SEND] suppress announcement to peer AS %u"
1649 peer
->host
, bgp
->confed_id
);
1654 /* Route-Reflect check. */
1655 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1660 /* IBGP reflection check. */
1661 if (reflect
&& !samepeer_safe
) {
1662 /* A route from a Client peer. */
1663 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1664 PEER_FLAG_REFLECTOR_CLIENT
)) {
1665 /* Reflect to all the Non-Client peers and also to the
1666 Client peers other than the originator. Originator
1668 is already done. So there is noting to do. */
1669 /* no bgp client-to-client reflection check. */
1670 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1671 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1672 PEER_FLAG_REFLECTOR_CLIENT
))
1675 /* A route from a Non-client peer. Reflect to all other
1677 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1678 PEER_FLAG_REFLECTOR_CLIENT
))
1683 /* For modify attribute, copy it to temporary structure. */
1684 bgp_attr_dup(attr
, piattr
);
1686 /* If local-preference is not set. */
1687 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1688 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1689 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1690 attr
->local_pref
= bgp
->default_local_pref
;
1693 /* If originator-id is not set and the route is to be reflected,
1694 set the originator id */
1696 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1697 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1698 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1701 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1703 if (peer
->sort
== BGP_PEER_EBGP
1704 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1705 if (from
!= bgp
->peer_self
&& !transparent
1706 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1707 PEER_FLAG_MED_UNCHANGED
))
1709 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1712 /* Since the nexthop attribute can vary per peer, it is not explicitly
1714 * in announce check, only certain flags and length (or number of
1716 * -- for IPv6/MP_REACH) are set here in order to guide the update
1718 * code in setting the nexthop(s) on a per peer basis in
1720 * Typically, the source nexthop in the attribute is preserved but in
1722 * scenarios where we know it will always be overwritten, we reset the
1723 * nexthop to "0" in an attempt to achieve better Update packing. An
1724 * example of this is when a prefix from each of 2 IBGP peers needs to
1726 * announced to an EBGP peer (and they have the same attributes barring
1730 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1732 #define NEXTHOP_IS_V6 \
1733 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1734 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1735 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1736 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1738 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1740 * the peer (group) is configured to receive link-local nexthop
1742 * and it is available in the prefix OR we're not reflecting the route
1744 * the peer (group) to whom we're going to announce is on a shared
1746 * and this is either a self-originated route or the peer is EBGP.
1748 if (NEXTHOP_IS_V6
) {
1749 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1750 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1751 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1752 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1753 || (!reflect
&& peer
->shared_network
1754 && (from
== bgp
->peer_self
1755 || peer
->sort
== BGP_PEER_EBGP
))) {
1756 attr
->mp_nexthop_len
=
1757 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1760 /* Clear off link-local nexthop in source, whenever it is not
1762 * ensure more prefixes share the same attribute for
1765 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1766 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1767 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1770 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1771 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1773 /* Route map & unsuppress-map apply. */
1774 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1775 struct bgp_path_info rmap_path
;
1776 struct bgp_path_info_extra dummy_rmap_path_extra
;
1777 struct attr dummy_attr
;
1779 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1780 rmap_path
.peer
= peer
;
1781 rmap_path
.attr
= attr
;
1784 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1785 sizeof(struct bgp_path_info_extra
));
1786 rmap_path
.extra
= &dummy_rmap_path_extra
;
1789 /* don't confuse inbound and outbound setting */
1790 RESET_FLAG(attr
->rmap_change_flags
);
1793 * The route reflector is not allowed to modify the attributes
1794 * of the reflected IBGP routes unless explicitly allowed.
1796 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1797 && !bgp_flag_check(bgp
,
1798 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1799 bgp_attr_dup(&dummy_attr
, attr
);
1800 rmap_path
.attr
= &dummy_attr
;
1803 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1805 if (pi
->extra
&& pi
->extra
->suppress
)
1806 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1807 RMAP_BGP
, &rmap_path
);
1809 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1810 RMAP_BGP
, &rmap_path
);
1812 peer
->rmap_type
= 0;
1814 if (ret
== RMAP_DENYMATCH
) {
1815 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1816 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1817 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1819 bgp_attr_flush(attr
);
1824 /* RFC 8212 to prevent route leaks.
1825 * This specification intends to improve this situation by requiring the
1826 * explicit configuration of both BGP Import and Export Policies for any
1827 * External BGP (EBGP) session such as customers, peers, or
1828 * confederation boundaries for all enabled address families. Through
1829 * codification of the aforementioned requirement, operators will
1830 * benefit from consistent behavior across different BGP
1833 if (peer
->bgp
->ebgp_requires_policy
1834 == DEFAULT_EBGP_POLICY_ENABLED
)
1835 if (!bgp_outbound_policy_exists(peer
, filter
))
1838 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1839 if (peer
->sort
== BGP_PEER_IBGP
1840 || peer
->sort
== BGP_PEER_CONFED
) {
1841 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1842 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1844 bgp_attr_add_gshut_community(attr
);
1848 /* After route-map has been applied, we check to see if the nexthop to
1849 * be carried in the attribute (that is used for the announcement) can
1850 * be cleared off or not. We do this in all cases where we would be
1851 * setting the nexthop to "ourselves". For IPv6, we only need to
1853 * the global nexthop here; the link-local nexthop would have been
1855 * already, and if not, it is required by the update formation code.
1856 * Also see earlier comments in this function.
1859 * If route-map has performed some operation on the nexthop or the peer
1860 * configuration says to pass it unchanged, we cannot reset the nexthop
1861 * here, so only attempt to do it if these aren't true. Note that the
1862 * route-map handler itself might have cleared the nexthop, if for
1864 * it is configured as 'peer-address'.
1866 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1867 piattr
->rmap_change_flags
)
1869 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1870 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1871 /* We can reset the nexthop, if setting (or forcing) it to
1873 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1874 PEER_FLAG_NEXTHOP_SELF
)
1875 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1876 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1878 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1879 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1880 subgroup_announce_reset_nhop(
1881 (peer_cap_enhe(peer
, afi
, safi
)
1885 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1886 /* Can also reset the nexthop if announcing to EBGP, but
1888 * no peer in the subgroup is on a shared subnet.
1889 * Note: 3rd party nexthop currently implemented for
1892 if ((p
->family
== AF_INET
) &&
1893 (!bgp_subgrp_multiaccess_check_v4(
1896 subgroup_announce_reset_nhop(
1897 (peer_cap_enhe(peer
, afi
, safi
)
1902 if ((p
->family
== AF_INET6
) &&
1903 (!bgp_subgrp_multiaccess_check_v6(
1904 piattr
->mp_nexthop_global
,
1906 subgroup_announce_reset_nhop(
1907 (peer_cap_enhe(peer
, afi
, safi
)
1914 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1916 * This flag is used for leaked vpn-vrf routes
1918 int family
= p
->family
;
1920 if (peer_cap_enhe(peer
, afi
, safi
))
1923 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1925 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1926 __func__
, family2str(family
));
1927 subgroup_announce_reset_nhop(family
, attr
);
1930 /* If IPv6/MP and nexthop does not have any override and happens
1932 * be a link-local address, reset it so that we don't pass along
1934 * source's link-local IPv6 address to recipients who may not be
1936 * the same interface.
1938 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1939 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1940 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1947 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1948 struct bgp_maxpaths_cfg
*mpath_cfg
,
1949 struct bgp_path_info_pair
*result
, afi_t afi
,
1952 struct bgp_path_info
*new_select
;
1953 struct bgp_path_info
*old_select
;
1954 struct bgp_path_info
*pi
;
1955 struct bgp_path_info
*pi1
;
1956 struct bgp_path_info
*pi2
;
1957 struct bgp_path_info
*nextpi
= NULL
;
1958 int paths_eq
, do_mpath
, debug
;
1959 struct list mp_list
;
1960 char pfx_buf
[PREFIX2STR_BUFFER
];
1961 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1963 bgp_mp_list_init(&mp_list
);
1965 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1967 debug
= bgp_debug_bestpath(&rn
->p
);
1970 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1972 /* bgp deterministic-med */
1974 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1976 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1977 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1979 bgp_path_info_unset_flag(rn
, pi1
,
1980 BGP_PATH_DMED_SELECTED
);
1982 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1984 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1986 if (BGP_PATH_HOLDDOWN(pi1
))
1988 if (pi1
->peer
!= bgp
->peer_self
)
1989 if (pi1
->peer
->status
!= Established
)
1994 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
1995 if (CHECK_FLAG(pi2
->flags
,
1996 BGP_PATH_DMED_CHECK
))
1998 if (BGP_PATH_HOLDDOWN(pi2
))
2000 if (pi2
->peer
!= bgp
->peer_self
2003 PEER_STATUS_NSF_WAIT
))
2004 if (pi2
->peer
->status
2008 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2010 && !aspath_cmp_left_confed(
2015 if (bgp_path_info_cmp(
2016 bgp
, pi2
, new_select
,
2017 &paths_eq
, mpath_cfg
, debug
,
2020 bgp_path_info_unset_flag(
2022 BGP_PATH_DMED_SELECTED
);
2026 bgp_path_info_set_flag(
2027 rn
, pi2
, BGP_PATH_DMED_CHECK
);
2030 bgp_path_info_set_flag(rn
, new_select
,
2031 BGP_PATH_DMED_CHECK
);
2032 bgp_path_info_set_flag(rn
, new_select
,
2033 BGP_PATH_DMED_SELECTED
);
2036 bgp_path_info_path_with_addpath_rx_str(
2037 new_select
, path_buf
);
2038 zlog_debug("%s: %s is the bestpath from AS %u",
2040 aspath_get_first_as(
2041 new_select
->attr
->aspath
));
2046 /* Check old selected route and new selected route. */
2049 for (pi
= bgp_node_get_bgp_path_info(rn
);
2050 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2051 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2054 if (BGP_PATH_HOLDDOWN(pi
)) {
2055 /* reap REMOVED routes, if needs be
2056 * selected route must stay for a while longer though
2058 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2059 && (pi
!= old_select
))
2060 bgp_path_info_reap(rn
, pi
);
2063 zlog_debug("%s: pi %p in holddown", __func__
,
2069 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2070 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2071 if (pi
->peer
->status
!= Established
) {
2075 "%s: pi %p non self peer %s not estab state",
2076 __func__
, pi
, pi
->peer
->host
);
2081 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2082 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2083 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2085 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2089 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2091 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2092 debug
, pfx_buf
, afi
, safi
, &rn
->reason
)) {
2097 /* Now that we know which path is the bestpath see if any of the other
2099 * qualify as multipaths
2103 bgp_path_info_path_with_addpath_rx_str(new_select
,
2106 sprintf(path_buf
, "NONE");
2108 "%s: After path selection, newbest is %s oldbest was %s",
2110 old_select
? old_select
->peer
->host
: "NONE");
2113 if (do_mpath
&& new_select
) {
2114 for (pi
= bgp_node_get_bgp_path_info(rn
);
2115 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2118 bgp_path_info_path_with_addpath_rx_str(
2121 if (pi
== new_select
) {
2124 "%s: %s is the bestpath, add to the multipath list",
2126 bgp_mp_list_add(&mp_list
, pi
);
2130 if (BGP_PATH_HOLDDOWN(pi
))
2133 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2134 && !CHECK_FLAG(pi
->peer
->sflags
,
2135 PEER_STATUS_NSF_WAIT
))
2136 if (pi
->peer
->status
!= Established
)
2139 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2142 "%s: %s has the same nexthop as the bestpath, skip it",
2147 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2148 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2154 "%s: %s is equivalent to the bestpath, add to the multipath list",
2156 bgp_mp_list_add(&mp_list
, pi
);
2161 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2163 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2164 bgp_mp_list_clear(&mp_list
);
2166 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2168 result
->old
= old_select
;
2169 result
->new = new_select
;
2175 * A new route/change in bestpath of an existing route. Evaluate the path
2176 * for advertisement to the subgroup.
2178 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2179 struct bgp_path_info
*selected
,
2180 struct bgp_node
*rn
,
2181 uint32_t addpath_tx_id
)
2184 struct peer
*onlypeer
;
2190 afi
= SUBGRP_AFI(subgrp
);
2191 safi
= SUBGRP_SAFI(subgrp
);
2192 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2195 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2196 char buf_prefix
[PREFIX_STRLEN
];
2197 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2198 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2202 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2203 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2204 PEER_STATUS_ORF_WAIT_REFRESH
))
2207 memset(&attr
, 0, sizeof(struct attr
));
2208 /* It's initialized in bgp_announce_check() */
2210 /* Announcement to the subgroup. If the route is filtered withdraw it.
2213 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2214 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2216 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2220 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2222 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2229 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2230 * This is called at the end of route processing.
2232 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2234 struct bgp_path_info
*pi
;
2236 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2237 if (BGP_PATH_HOLDDOWN(pi
))
2239 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2240 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2245 * Has the route changed from the RIB's perspective? This is invoked only
2246 * if the route selection returns the same best route as earlier - to
2247 * determine if we need to update zebra or not.
2249 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2250 struct bgp_path_info
*selected
)
2252 struct bgp_path_info
*mpinfo
;
2254 /* If this is multipath, check all selected paths for any nexthop
2255 * change or attribute change. Some attribute changes (e.g., community)
2256 * aren't of relevance to the RIB, but we'll update zebra to ensure
2257 * we handle the case of BGP nexthop change. This is the behavior
2258 * when the best path has an attribute change anyway.
2260 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2261 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2265 * If this is multipath, check all selected paths for any nexthop change
2267 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2268 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2269 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2270 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2274 /* Nothing has changed from the RIB's perspective. */
2278 struct bgp_process_queue
{
2280 STAILQ_HEAD(, bgp_node
) pqueue
;
2281 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2283 unsigned int queued
;
2287 * old_select = The old best path
2288 * new_select = the new best path
2290 * if (!old_select && new_select)
2291 * We are sending new information on.
2293 * if (old_select && new_select) {
2294 * if (new_select != old_select)
2295 * We have a new best path send a change
2297 * We've received a update with new attributes that needs
2301 * if (old_select && !new_select)
2302 * We have no eligible route that we can announce or the rn
2305 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2306 afi_t afi
, safi_t safi
)
2308 struct bgp_path_info
*new_select
;
2309 struct bgp_path_info
*old_select
;
2310 struct bgp_path_info_pair old_and_new
;
2311 char pfx_buf
[PREFIX2STR_BUFFER
];
2314 /* Is it end of initial update? (after startup) */
2316 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2317 sizeof(bgp
->update_delay_zebra_resume_time
));
2319 bgp
->main_zebra_update_hold
= 0;
2320 FOREACH_AFI_SAFI (afi
, safi
) {
2321 if (bgp_fibupd_safi(safi
))
2322 bgp_zebra_announce_table(bgp
, afi
, safi
);
2324 bgp
->main_peers_update_hold
= 0;
2326 bgp_start_routeadv(bgp
);
2330 struct prefix
*p
= &rn
->p
;
2332 debug
= bgp_debug_bestpath(&rn
->p
);
2334 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2335 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2336 afi2str(afi
), safi2str(safi
));
2339 /* Best path selection. */
2340 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2342 old_select
= old_and_new
.old
;
2343 new_select
= old_and_new
.new;
2345 /* Do we need to allocate or free labels?
2346 * Right now, since we only deal with per-prefix labels, it is not
2347 * necessary to do this upon changes to best path. Exceptions:
2348 * - label index has changed -> recalculate resulting label
2349 * - path_info sub_type changed -> switch to/from implicit-null
2350 * - no valid label (due to removed static label binding) -> get new one
2352 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2355 || bgp_label_index_differs(new_select
, old_select
)
2356 || new_select
->sub_type
!= old_select
->sub_type
2357 || !bgp_is_valid_label(&rn
->local_label
)) {
2358 /* Enforced penultimate hop popping:
2359 * implicit-null for local routes, aggregate
2360 * and redistributed routes
2362 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2363 || new_select
->sub_type
2364 == BGP_ROUTE_AGGREGATE
2365 || new_select
->sub_type
2366 == BGP_ROUTE_REDISTRIBUTE
) {
2369 BGP_NODE_REGISTERED_FOR_LABEL
))
2370 bgp_unregister_for_label(rn
);
2371 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2373 bgp_set_valid_label(&rn
->local_label
);
2375 bgp_register_for_label(rn
, new_select
);
2377 } else if (CHECK_FLAG(rn
->flags
,
2378 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2379 bgp_unregister_for_label(rn
);
2381 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2382 bgp_unregister_for_label(rn
);
2386 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2388 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2389 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2390 old_select
, new_select
);
2393 /* If best route remains the same and this is not due to user-initiated
2394 * clear, see exactly what needs to be done.
2396 if (old_select
&& old_select
== new_select
2397 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2398 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2399 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2400 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2402 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2403 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2405 if (bgp_fibupd_safi(safi
)
2406 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2408 if (new_select
->type
== ZEBRA_ROUTE_BGP
2409 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2410 || new_select
->sub_type
2411 == BGP_ROUTE_IMPORTED
))
2413 bgp_zebra_announce(rn
, p
, old_select
,
2417 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2418 bgp_zebra_clear_route_change_flags(rn
);
2420 /* If there is a change of interest to peers, reannounce the
2422 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2423 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2424 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2426 /* unicast routes must also be annouced to
2427 * labeled-unicast update-groups */
2428 if (safi
== SAFI_UNICAST
)
2429 group_announce_route(bgp
, afi
,
2430 SAFI_LABELED_UNICAST
, rn
,
2433 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2434 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2437 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2441 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2443 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2445 /* bestpath has changed; bump version */
2446 if (old_select
|| new_select
) {
2447 bgp_bump_version(rn
);
2449 if (!bgp
->t_rmap_def_originate_eval
) {
2453 update_group_refresh_default_originate_route_map
,
2454 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2455 &bgp
->t_rmap_def_originate_eval
);
2460 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2463 zlog_debug("%s: setting SELECTED flag", __func__
);
2464 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2465 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2466 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2470 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2471 if (old_select
!= new_select
) {
2473 vnc_import_bgp_exterior_del_route(bgp
, p
,
2475 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2478 vnc_import_bgp_exterior_add_route(bgp
, p
,
2480 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2486 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2488 /* unicast routes must also be annouced to labeled-unicast update-groups
2490 if (safi
== SAFI_UNICAST
)
2491 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2495 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2496 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2497 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2498 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2499 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2500 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2502 /* if this is an evpn imported type-5 prefix,
2503 * we need to withdraw the route first to clear
2504 * the nh neigh and the RMAC entry.
2507 is_route_parent_evpn(old_select
))
2508 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2510 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2512 /* Withdraw the route from the kernel. */
2513 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2514 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2515 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2516 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2518 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2522 /* advertise/withdraw type-5 routes */
2523 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2524 if (advertise_type5_routes(bgp
, afi
) &&
2526 is_route_injectable_into_evpn(new_select
)) {
2528 /* apply the route-map */
2529 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2532 ret
= route_map_apply(
2533 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2534 &rn
->p
, RMAP_BGP
, new_select
);
2535 if (ret
== RMAP_MATCH
)
2536 bgp_evpn_advertise_type5_route(
2537 bgp
, &rn
->p
, new_select
->attr
,
2540 bgp_evpn_withdraw_type5_route(
2541 bgp
, &rn
->p
, afi
, safi
);
2543 bgp_evpn_advertise_type5_route(bgp
,
2549 } else if (advertise_type5_routes(bgp
, afi
) &&
2551 is_route_injectable_into_evpn(old_select
))
2552 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2555 /* Clear any route change flags. */
2556 bgp_zebra_clear_route_change_flags(rn
);
2558 /* Reap old select bgp_path_info, if it has been removed */
2559 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2560 bgp_path_info_reap(rn
, old_select
);
2562 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2566 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2568 struct bgp_process_queue
*pqnode
= data
;
2569 struct bgp
*bgp
= pqnode
->bgp
;
2570 struct bgp_table
*table
;
2571 struct bgp_node
*rn
;
2574 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2575 bgp_process_main_one(bgp
, NULL
, 0, 0);
2576 /* should always have dedicated wq call */
2577 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2581 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2582 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2583 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2584 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2585 table
= bgp_node_table(rn
);
2586 /* note, new RNs may be added as part of processing */
2587 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2589 bgp_unlock_node(rn
);
2590 bgp_table_unlock(table
);
2596 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2598 struct bgp_process_queue
*pqnode
= data
;
2600 bgp_unlock(pqnode
->bgp
);
2602 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2605 void bgp_process_queue_init(void)
2607 if (!bm
->process_main_queue
)
2608 bm
->process_main_queue
=
2609 work_queue_new(bm
->master
, "process_main_queue");
2611 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2612 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2613 bm
->process_main_queue
->spec
.max_retries
= 0;
2614 bm
->process_main_queue
->spec
.hold
= 50;
2615 /* Use a higher yield value of 50ms for main queue processing */
2616 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2619 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2621 struct bgp_process_queue
*pqnode
;
2623 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2624 sizeof(struct bgp_process_queue
));
2626 /* unlocked in bgp_processq_del */
2627 pqnode
->bgp
= bgp_lock(bgp
);
2628 STAILQ_INIT(&pqnode
->pqueue
);
2633 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2635 #define ARBITRARY_PROCESS_QLEN 10000
2636 struct work_queue
*wq
= bm
->process_main_queue
;
2637 struct bgp_process_queue
*pqnode
;
2638 int pqnode_reuse
= 0;
2640 /* already scheduled for processing? */
2641 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2647 /* Add route nodes to an existing work queue item until reaching the
2648 limit only if is from the same BGP view and it's not an EOIU marker
2650 if (work_queue_item_count(wq
)) {
2651 struct work_queue_item
*item
= work_queue_last_item(wq
);
2652 pqnode
= item
->data
;
2654 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2655 || pqnode
->bgp
!= bgp
2656 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2657 pqnode
= bgp_processq_alloc(bgp
);
2661 pqnode
= bgp_processq_alloc(bgp
);
2662 /* all unlocked in bgp_process_wq */
2663 bgp_table_lock(bgp_node_table(rn
));
2665 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2668 /* can't be enqueued twice */
2669 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2670 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2674 work_queue_add(wq
, pqnode
);
2679 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2681 struct bgp_process_queue
*pqnode
;
2683 if (bm
->process_main_queue
== NULL
)
2686 pqnode
= bgp_processq_alloc(bgp
);
2688 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2689 work_queue_add(bm
->process_main_queue
, pqnode
);
2692 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2696 peer
= THREAD_ARG(thread
);
2697 peer
->t_pmax_restart
= NULL
;
2699 if (bgp_debug_neighbor_events(peer
))
2701 "%s Maximum-prefix restart timer expired, restore peering",
2704 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2705 zlog_debug("%s: %s peer_clear failed",
2706 __PRETTY_FUNCTION__
, peer
->host
);
2711 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2715 iana_safi_t pkt_safi
;
2717 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2720 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2721 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2722 PEER_STATUS_PREFIX_LIMIT
)
2727 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2729 afi_safi_print(afi
, safi
), peer
->host
,
2730 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2731 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2733 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2734 PEER_FLAG_MAX_PREFIX_WARNING
))
2737 /* Convert AFI, SAFI to values for packet. */
2738 pkt_afi
= afi_int2iana(afi
);
2739 pkt_safi
= safi_int2iana(safi
);
2743 ndata
[0] = (pkt_afi
>> 8);
2745 ndata
[2] = pkt_safi
;
2746 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2747 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2748 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2749 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2751 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2752 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2753 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2757 /* Dynamic peers will just close their connection. */
2758 if (peer_dynamic_neighbor(peer
))
2761 /* restart timer start */
2762 if (peer
->pmax_restart
[afi
][safi
]) {
2763 peer
->v_pmax_restart
=
2764 peer
->pmax_restart
[afi
][safi
] * 60;
2766 if (bgp_debug_neighbor_events(peer
))
2768 "%s Maximum-prefix restart timer started for %d secs",
2769 peer
->host
, peer
->v_pmax_restart
);
2771 BGP_TIMER_ON(peer
->t_pmax_restart
,
2772 bgp_maximum_prefix_restart_timer
,
2773 peer
->v_pmax_restart
);
2778 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2779 PEER_STATUS_PREFIX_LIMIT
);
2781 if (peer
->pcount
[afi
][safi
]
2782 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2783 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2784 PEER_STATUS_PREFIX_THRESHOLD
)
2789 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2790 afi_safi_print(afi
, safi
), peer
->host
,
2791 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2792 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2793 PEER_STATUS_PREFIX_THRESHOLD
);
2795 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2796 PEER_STATUS_PREFIX_THRESHOLD
);
2800 /* Unconditionally remove the route from the RIB, without taking
2801 * damping into consideration (eg, because the session went down)
2803 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2804 struct peer
*peer
, afi_t afi
, safi_t safi
)
2806 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2808 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2809 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2811 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2814 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2815 struct peer
*peer
, afi_t afi
, safi_t safi
,
2816 struct prefix_rd
*prd
)
2818 /* apply dampening, if result is suppressed, we'll be retaining
2819 * the bgp_path_info in the RIB for historical reference.
2821 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2822 && peer
->sort
== BGP_PEER_EBGP
)
2823 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2824 == BGP_DAMP_SUPPRESSED
) {
2825 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2831 if (safi
== SAFI_MPLS_VPN
) {
2832 struct bgp_node
*prn
= NULL
;
2833 struct bgp_table
*table
= NULL
;
2835 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2836 (struct prefix
*)prd
);
2837 if (bgp_node_has_bgp_path_info_data(prn
)) {
2838 table
= bgp_node_get_bgp_table_info(prn
);
2840 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2841 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2843 bgp_unlock_node(prn
);
2845 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2846 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2848 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2849 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2855 /* If this is an EVPN route, process for un-import. */
2856 if (safi
== SAFI_EVPN
)
2857 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2859 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2862 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2863 struct peer
*peer
, struct attr
*attr
,
2864 struct bgp_node
*rn
)
2866 struct bgp_path_info
*new;
2868 /* Make new BGP info. */
2869 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2871 new->instance
= instance
;
2872 new->sub_type
= sub_type
;
2875 new->uptime
= bgp_clock();
2880 static void overlay_index_update(struct attr
*attr
,
2881 struct eth_segment_id
*eth_s_id
,
2882 union gw_addr
*gw_ip
)
2887 if (eth_s_id
== NULL
) {
2888 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2889 sizeof(struct eth_segment_id
));
2891 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2892 sizeof(struct eth_segment_id
));
2894 if (gw_ip
== NULL
) {
2895 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2897 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2898 sizeof(union gw_addr
));
2902 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2903 struct eth_segment_id
*eth_s_id
,
2904 union gw_addr
*gw_ip
)
2906 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2907 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2909 struct eth_segment_id esi
;
2913 if (afi
!= AFI_L2VPN
)
2916 memset(&temp
, 0, sizeof(temp
));
2917 path_eth_s_id
= &temp
.esi
;
2918 path_gw_ip
= &temp
.ip
;
2920 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2923 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2924 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2927 if (gw_ip
== NULL
) {
2928 memset(&temp
, 0, sizeof(temp
));
2929 path_gw_ip_remote
= &temp
.ip
;
2931 path_gw_ip_remote
= gw_ip
;
2933 if (eth_s_id
== NULL
) {
2934 memset(&temp
, 0, sizeof(temp
));
2935 path_eth_s_id_remote
= &temp
.esi
;
2937 path_eth_s_id_remote
= eth_s_id
;
2939 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2942 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2943 sizeof(struct eth_segment_id
));
2946 /* Check if received nexthop is valid or not. */
2947 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2952 /* Only validated for unicast and multicast currently. */
2953 /* Also valid for EVPN where the nexthop is an IP address. */
2954 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2957 /* If NEXT_HOP is present, validate it. */
2958 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2959 if (attr
->nexthop
.s_addr
== 0
2960 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2961 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2965 /* If MP_NEXTHOP is present, validate it. */
2966 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2967 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2968 * it is not an IPv6 link-local address.
2970 if (attr
->mp_nexthop_len
) {
2971 switch (attr
->mp_nexthop_len
) {
2972 case BGP_ATTR_NHLEN_IPV4
:
2973 case BGP_ATTR_NHLEN_VPNV4
:
2974 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2975 || IPV4_CLASS_DE(ntohl(
2976 attr
->mp_nexthop_global_in
.s_addr
))
2977 || bgp_nexthop_self(bgp
,
2978 attr
->mp_nexthop_global_in
));
2981 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2982 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2983 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2984 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2985 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2986 || IN6_IS_ADDR_MULTICAST(
2987 &attr
->mp_nexthop_global
));
2999 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3000 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3001 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3002 uint32_t num_labels
, int soft_reconfig
,
3003 struct bgp_route_evpn
*evpn
)
3006 int aspath_loop_count
= 0;
3007 struct bgp_node
*rn
;
3009 struct attr new_attr
;
3010 struct attr
*attr_new
;
3011 struct bgp_path_info
*pi
;
3012 struct bgp_path_info
*new;
3013 struct bgp_path_info_extra
*extra
;
3015 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3017 int do_loop_check
= 1;
3018 int has_valid_label
= 0;
3020 int vnc_implicit_withdraw
= 0;
3024 memset(&new_attr
, 0, sizeof(struct attr
));
3025 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3026 new_attr
.label
= MPLS_INVALID_LABEL
;
3029 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3030 /* TODO: Check to see if we can get rid of "is_valid_label" */
3031 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3032 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3034 has_valid_label
= bgp_is_valid_label(label
);
3036 /* When peer's soft reconfiguration enabled. Record input packet in
3039 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3040 && peer
!= bgp
->peer_self
)
3041 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3043 /* Check previously received route. */
3044 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3045 if (pi
->peer
== peer
&& pi
->type
== type
3046 && pi
->sub_type
== sub_type
3047 && pi
->addpath_rx_id
== addpath_id
)
3050 /* AS path local-as loop check. */
3051 if (peer
->change_local_as
) {
3052 if (peer
->allowas_in
[afi
][safi
])
3053 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3054 else if (!CHECK_FLAG(peer
->flags
,
3055 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3056 aspath_loop_count
= 1;
3058 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3059 > aspath_loop_count
) {
3060 reason
= "as-path contains our own AS;";
3065 /* If the peer is configured for "allowas-in origin" and the last ASN in
3067 * as-path is our ASN then we do not need to call aspath_loop_check
3069 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3070 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3073 /* AS path loop check. */
3074 if (do_loop_check
) {
3075 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3076 > peer
->allowas_in
[afi
][safi
]
3077 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3078 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3079 > peer
->allowas_in
[afi
][safi
])) {
3080 reason
= "as-path contains our own AS;";
3085 /* Route reflector originator ID check. */
3086 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3087 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3088 reason
= "originator is us;";
3092 /* Route reflector cluster ID check. */
3093 if (bgp_cluster_filter(peer
, attr
)) {
3094 reason
= "reflected from the same cluster;";
3098 /* Apply incoming filter. */
3099 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3104 /* RFC 8212 to prevent route leaks.
3105 * This specification intends to improve this situation by requiring the
3106 * explicit configuration of both BGP Import and Export Policies for any
3107 * External BGP (EBGP) session such as customers, peers, or
3108 * confederation boundaries for all enabled address families. Through
3109 * codification of the aforementioned requirement, operators will
3110 * benefit from consistent behavior across different BGP
3113 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3114 if (!bgp_inbound_policy_exists(peer
,
3115 &peer
->filter
[afi
][safi
])) {
3116 reason
= "inbound policy missing";
3120 bgp_attr_dup(&new_attr
, attr
);
3122 /* Apply incoming route-map.
3123 * NB: new_attr may now contain newly allocated values from route-map
3125 * commands, so we need bgp_attr_flush in the error paths, until we
3127 * the attr (which takes over the memory references) */
3128 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3130 reason
= "route-map;";
3131 bgp_attr_flush(&new_attr
);
3135 if (peer
->sort
== BGP_PEER_EBGP
) {
3137 /* If we receive the graceful-shutdown community from an eBGP
3138 * peer we must lower local-preference */
3139 if (new_attr
.community
3140 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3141 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3142 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3144 /* If graceful-shutdown is configured then add the GSHUT
3145 * community to all paths received from eBGP peers */
3146 } else if (bgp_flag_check(peer
->bgp
,
3147 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3148 bgp_attr_add_gshut_community(&new_attr
);
3152 /* next hop check. */
3153 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3154 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3155 reason
= "martian or self next-hop;";
3156 bgp_attr_flush(&new_attr
);
3160 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3161 reason
= "self mac;";
3165 attr_new
= bgp_attr_intern(&new_attr
);
3167 /* If the update is implicit withdraw. */
3169 pi
->uptime
= bgp_clock();
3170 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3172 /* Same attribute comes in. */
3173 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3174 && attrhash_cmp(pi
->attr
, attr_new
)
3175 && (!has_valid_label
3176 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3177 num_labels
* sizeof(mpls_label_t
))
3179 && (overlay_index_equal(
3180 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3181 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3182 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3183 BGP_CONFIG_DAMPENING
)
3184 && peer
->sort
== BGP_PEER_EBGP
3185 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3186 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3187 bgp_debug_rdpfxpath2str(
3188 afi
, safi
, prd
, p
, label
,
3189 num_labels
, addpath_id
? 1 : 0,
3190 addpath_id
, pfx_buf
,
3192 zlog_debug("%s rcvd %s", peer
->host
,
3196 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3197 != BGP_DAMP_SUPPRESSED
) {
3198 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3200 bgp_process(bgp
, rn
, afi
, safi
);
3202 } else /* Duplicate - odd */
3204 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3205 if (!peer
->rcvd_attr_printed
) {
3207 "%s rcvd UPDATE w/ attr: %s",
3209 peer
->rcvd_attr_str
);
3210 peer
->rcvd_attr_printed
= 1;
3213 bgp_debug_rdpfxpath2str(
3214 afi
, safi
, prd
, p
, label
,
3215 num_labels
, addpath_id
? 1 : 0,
3216 addpath_id
, pfx_buf
,
3219 "%s rcvd %s...duplicate ignored",
3220 peer
->host
, pfx_buf
);
3223 /* graceful restart STALE flag unset. */
3224 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3225 bgp_path_info_unset_flag(
3226 rn
, pi
, BGP_PATH_STALE
);
3227 bgp_process(bgp
, rn
, afi
, safi
);
3231 bgp_unlock_node(rn
);
3232 bgp_attr_unintern(&attr_new
);
3237 /* Withdraw/Announce before we fully processed the withdraw */
3238 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3239 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3240 bgp_debug_rdpfxpath2str(
3241 afi
, safi
, prd
, p
, label
, num_labels
,
3242 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3245 "%s rcvd %s, flapped quicker than processing",
3246 peer
->host
, pfx_buf
);
3249 bgp_path_info_restore(rn
, pi
);
3252 /* Received Logging. */
3253 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3254 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3255 num_labels
, addpath_id
? 1 : 0,
3256 addpath_id
, pfx_buf
,
3258 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3261 /* graceful restart STALE flag unset. */
3262 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3263 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3265 /* The attribute is changed. */
3266 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3268 /* implicit withdraw, decrement aggregate and pcount here.
3269 * only if update is accepted, they'll increment below.
3271 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3273 /* Update bgp route dampening information. */
3274 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3275 && peer
->sort
== BGP_PEER_EBGP
) {
3276 /* This is implicit withdraw so we should update
3279 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3280 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3283 if (safi
== SAFI_MPLS_VPN
) {
3284 struct bgp_node
*prn
= NULL
;
3285 struct bgp_table
*table
= NULL
;
3287 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3288 (struct prefix
*)prd
);
3289 if (bgp_node_has_bgp_path_info_data(prn
)) {
3290 table
= bgp_node_get_bgp_table_info(prn
);
3292 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3293 bgp
, prd
, table
, p
, pi
);
3295 bgp_unlock_node(prn
);
3297 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3298 && (safi
== SAFI_UNICAST
)) {
3299 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3301 * Implicit withdraw case.
3303 ++vnc_implicit_withdraw
;
3304 vnc_import_bgp_del_route(bgp
, p
, pi
);
3305 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3310 /* Special handling for EVPN update of an existing route. If the
3311 * extended community attribute has changed, we need to
3313 * the route using its existing extended community. It will be
3314 * subsequently processed for import with the new extended
3317 if (safi
== SAFI_EVPN
&& !same_attr
) {
3319 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3321 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3324 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3325 attr_new
->ecommunity
);
3327 if (bgp_debug_update(peer
, p
, NULL
, 1))
3329 "Change in EXT-COMM, existing %s new %s",
3331 pi
->attr
->ecommunity
),
3333 attr_new
->ecommunity
));
3334 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3340 /* Update to new attribute. */
3341 bgp_attr_unintern(&pi
->attr
);
3342 pi
->attr
= attr_new
;
3344 /* Update MPLS label */
3345 if (has_valid_label
) {
3346 extra
= bgp_path_info_extra_get(pi
);
3347 if (extra
->label
!= label
) {
3348 memcpy(&extra
->label
, label
,
3349 num_labels
* sizeof(mpls_label_t
));
3350 extra
->num_labels
= num_labels
;
3352 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3353 bgp_set_valid_label(&extra
->label
[0]);
3357 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3358 && (safi
== SAFI_UNICAST
)) {
3359 if (vnc_implicit_withdraw
) {
3361 * Add back the route with its new attributes
3363 * The route is still selected, until the route
3365 * queued by bgp_process actually runs. We have
3367 * update to the VNC side immediately to avoid
3369 * configuration changes (e.g., route-map
3371 * trigger re-importation of the entire RIB.
3373 vnc_import_bgp_add_route(bgp
, p
, pi
);
3374 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3378 /* Update Overlay Index */
3379 if (afi
== AFI_L2VPN
) {
3380 overlay_index_update(
3381 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3382 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3385 /* Update bgp route dampening information. */
3386 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3387 && peer
->sort
== BGP_PEER_EBGP
) {
3388 /* Now we do normal update dampening. */
3389 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3390 if (ret
== BGP_DAMP_SUPPRESSED
) {
3391 bgp_unlock_node(rn
);
3396 /* Nexthop reachability check - for unicast and
3397 * labeled-unicast.. */
3398 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3399 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3400 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3401 && !CHECK_FLAG(peer
->flags
,
3402 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3404 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3409 struct bgp
*bgp_nexthop
= bgp
;
3411 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3412 bgp_nexthop
= pi
->extra
->bgp_orig
;
3414 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3416 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3417 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3419 if (BGP_DEBUG(nht
, NHT
)) {
3420 char buf1
[INET6_ADDRSTRLEN
];
3422 (const void *)&attr_new
3424 buf1
, INET6_ADDRSTRLEN
);
3425 zlog_debug("%s(%s): NH unresolved",
3426 __FUNCTION__
, buf1
);
3428 bgp_path_info_unset_flag(rn
, pi
,
3432 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3435 if (safi
== SAFI_MPLS_VPN
) {
3436 struct bgp_node
*prn
= NULL
;
3437 struct bgp_table
*table
= NULL
;
3439 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3440 (struct prefix
*)prd
);
3441 if (bgp_node_has_bgp_path_info_data(prn
)) {
3442 table
= bgp_node_get_bgp_table_info(prn
);
3444 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3445 bgp
, prd
, table
, p
, pi
);
3447 bgp_unlock_node(prn
);
3451 /* If this is an EVPN route and some attribute has changed,
3453 * route for import. If the extended community has changed, we
3455 * have done the un-import earlier and the import would result
3457 * route getting injected into appropriate L2 VNIs. If it is
3459 * some other attribute change, the import will result in
3461 * the attributes for the route in the VNI(s).
3463 if (safi
== SAFI_EVPN
&& !same_attr
)
3464 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3466 /* Process change. */
3467 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3469 bgp_process(bgp
, rn
, afi
, safi
);
3470 bgp_unlock_node(rn
);
3472 if (SAFI_UNICAST
== safi
3473 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3474 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3476 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3478 if ((SAFI_MPLS_VPN
== safi
)
3479 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3481 vpn_leak_to_vrf_update(bgp
, pi
);
3485 if (SAFI_MPLS_VPN
== safi
) {
3486 mpls_label_t label_decoded
= decode_label(label
);
3488 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3489 type
, sub_type
, &label_decoded
);
3491 if (SAFI_ENCAP
== safi
) {
3492 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3493 type
, sub_type
, NULL
);
3498 } // End of implicit withdraw
3500 /* Received Logging. */
3501 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3502 if (!peer
->rcvd_attr_printed
) {
3503 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3504 peer
->rcvd_attr_str
);
3505 peer
->rcvd_attr_printed
= 1;
3508 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3509 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3511 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3514 /* Make new BGP info. */
3515 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3517 /* Update MPLS label */
3518 if (has_valid_label
) {
3519 extra
= bgp_path_info_extra_get(new);
3520 if (extra
->label
!= label
) {
3521 memcpy(&extra
->label
, label
,
3522 num_labels
* sizeof(mpls_label_t
));
3523 extra
->num_labels
= num_labels
;
3525 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3526 bgp_set_valid_label(&extra
->label
[0]);
3529 /* Update Overlay Index */
3530 if (afi
== AFI_L2VPN
) {
3531 overlay_index_update(new->attr
,
3532 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3533 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3535 /* Nexthop reachability check. */
3536 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3537 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3538 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3539 && !CHECK_FLAG(peer
->flags
,
3540 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3541 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3546 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3547 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3548 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3550 if (BGP_DEBUG(nht
, NHT
)) {
3551 char buf1
[INET6_ADDRSTRLEN
];
3553 (const void *)&attr_new
->nexthop
,
3554 buf1
, INET6_ADDRSTRLEN
);
3555 zlog_debug("%s(%s): NH unresolved",
3556 __FUNCTION__
, buf1
);
3558 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3561 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3564 new->addpath_rx_id
= addpath_id
;
3566 /* Increment prefix */
3567 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3569 /* Register new BGP information. */
3570 bgp_path_info_add(rn
, new);
3572 /* route_node_get lock */
3573 bgp_unlock_node(rn
);
3576 if (safi
== SAFI_MPLS_VPN
) {
3577 struct bgp_node
*prn
= NULL
;
3578 struct bgp_table
*table
= NULL
;
3580 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3581 if (bgp_node_has_bgp_path_info_data(prn
)) {
3582 table
= bgp_node_get_bgp_table_info(prn
);
3584 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3585 bgp
, prd
, table
, p
, new);
3587 bgp_unlock_node(prn
);
3591 /* If maximum prefix count is configured and current prefix
3593 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3596 /* If this is an EVPN route, process for import. */
3597 if (safi
== SAFI_EVPN
)
3598 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3600 /* Process change. */
3601 bgp_process(bgp
, rn
, afi
, safi
);
3603 if (SAFI_UNICAST
== safi
3604 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3605 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3606 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3608 if ((SAFI_MPLS_VPN
== safi
)
3609 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3611 vpn_leak_to_vrf_update(bgp
, new);
3614 if (SAFI_MPLS_VPN
== safi
) {
3615 mpls_label_t label_decoded
= decode_label(label
);
3617 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3618 sub_type
, &label_decoded
);
3620 if (SAFI_ENCAP
== safi
) {
3621 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3628 /* This BGP update is filtered. Log the reason then update BGP
3631 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3632 if (!peer
->rcvd_attr_printed
) {
3633 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3634 peer
->rcvd_attr_str
);
3635 peer
->rcvd_attr_printed
= 1;
3638 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3639 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3641 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3642 peer
->host
, pfx_buf
, reason
);
3646 /* If this is an EVPN route, un-import it as it is now filtered.
3648 if (safi
== SAFI_EVPN
)
3649 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3651 if (SAFI_UNICAST
== safi
3652 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3653 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3655 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3657 if ((SAFI_MPLS_VPN
== safi
)
3658 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3660 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3663 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3666 bgp_unlock_node(rn
);
3670 * Filtered update is treated as an implicit withdrawal (see
3672 * a few lines above)
3674 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3675 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3683 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3684 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3685 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3686 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3689 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3690 struct bgp_node
*rn
;
3691 struct bgp_path_info
*pi
;
3694 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3695 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3703 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3705 /* If peer is soft reconfiguration enabled. Record input packet for
3706 * further calculation.
3708 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3709 * routes that are filtered. This tanks out Quagga RS pretty badly due
3711 * the iteration over all RS clients.
3712 * Since we need to remove the entry from adj_in anyway, do that first
3714 * if there was no entry, we don't need to do anything more.
3716 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3717 && peer
!= bgp
->peer_self
)
3718 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3719 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3720 bgp_debug_rdpfxpath2str(
3721 afi
, safi
, prd
, p
, label
, num_labels
,
3722 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3725 "%s withdrawing route %s not in adj-in",
3726 peer
->host
, pfx_buf
);
3728 bgp_unlock_node(rn
);
3732 /* Lookup withdrawn route. */
3733 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3734 if (pi
->peer
== peer
&& pi
->type
== type
3735 && pi
->sub_type
== sub_type
3736 && pi
->addpath_rx_id
== addpath_id
)
3740 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3741 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3742 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3744 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3748 /* Withdraw specified route from routing table. */
3749 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3750 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3751 if (SAFI_UNICAST
== safi
3752 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3753 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3754 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3756 if ((SAFI_MPLS_VPN
== safi
)
3757 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3759 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3761 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3762 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3763 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3765 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3768 /* Unlock bgp_node_get() lock. */
3769 bgp_unlock_node(rn
);
3774 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3777 struct update_subgroup
*subgrp
;
3778 subgrp
= peer_subgroup(peer
, afi
, safi
);
3779 subgroup_default_originate(subgrp
, withdraw
);
3784 * bgp_stop_announce_route_timer
3786 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3788 if (!paf
->t_announce_route
)
3791 THREAD_TIMER_OFF(paf
->t_announce_route
);
3795 * bgp_announce_route_timer_expired
3797 * Callback that is invoked when the route announcement timer for a
3800 static int bgp_announce_route_timer_expired(struct thread
*t
)
3802 struct peer_af
*paf
;
3805 paf
= THREAD_ARG(t
);
3808 if (peer
->status
!= Established
)
3811 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3814 peer_af_announce_route(paf
, 1);
3819 * bgp_announce_route
3821 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3823 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3825 struct peer_af
*paf
;
3826 struct update_subgroup
*subgrp
;
3828 paf
= peer_af_find(peer
, afi
, safi
);
3831 subgrp
= PAF_SUBGRP(paf
);
3834 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3835 * or a refresh has already been triggered.
3837 if (!subgrp
|| paf
->t_announce_route
)
3841 * Start a timer to stagger/delay the announce. This serves
3842 * two purposes - announcement can potentially be combined for
3843 * multiple peers and the announcement doesn't happen in the
3846 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3847 (subgrp
->peer_count
== 1)
3848 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3849 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3850 &paf
->t_announce_route
);
3854 * Announce routes from all AF tables to a peer.
3856 * This should ONLY be called when there is a need to refresh the
3857 * routes to the peer based on a policy change for this peer alone
3858 * or a route refresh request received from the peer.
3859 * The operation will result in splitting the peer from its existing
3860 * subgroups and putting it in new subgroups.
3862 void bgp_announce_route_all(struct peer
*peer
)
3867 FOREACH_AFI_SAFI (afi
, safi
)
3868 bgp_announce_route(peer
, afi
, safi
);
3871 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3872 struct bgp_table
*table
,
3873 struct prefix_rd
*prd
)
3876 struct bgp_node
*rn
;
3877 struct bgp_adj_in
*ain
;
3880 table
= peer
->bgp
->rib
[afi
][safi
];
3882 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3883 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3884 if (ain
->peer
!= peer
)
3887 struct bgp_path_info
*pi
=
3888 bgp_node_get_bgp_path_info(rn
);
3889 uint32_t num_labels
= 0;
3890 mpls_label_t
*label_pnt
= NULL
;
3891 struct bgp_route_evpn evpn
;
3893 if (pi
&& pi
->extra
)
3894 num_labels
= pi
->extra
->num_labels
;
3896 label_pnt
= &pi
->extra
->label
[0];
3898 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3901 memset(&evpn
, 0, sizeof(evpn
));
3903 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3904 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3905 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3906 num_labels
, 1, &evpn
);
3909 bgp_unlock_node(rn
);
3915 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3917 struct bgp_node
*rn
;
3918 struct bgp_table
*table
;
3920 if (peer
->status
!= Established
)
3923 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3924 && (safi
!= SAFI_EVPN
))
3925 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3927 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3928 rn
= bgp_route_next(rn
)) {
3929 table
= bgp_node_get_bgp_table_info(rn
);
3930 if (table
!= NULL
) {
3931 struct prefix_rd prd
;
3933 prd
.family
= AF_UNSPEC
;
3935 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3937 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3944 struct bgp_clear_node_queue
{
3945 struct bgp_node
*rn
;
3948 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3950 struct bgp_clear_node_queue
*cnq
= data
;
3951 struct bgp_node
*rn
= cnq
->rn
;
3952 struct peer
*peer
= wq
->spec
.data
;
3953 struct bgp_path_info
*pi
;
3955 afi_t afi
= bgp_node_table(rn
)->afi
;
3956 safi_t safi
= bgp_node_table(rn
)->safi
;
3961 /* It is possible that we have multiple paths for a prefix from a peer
3962 * if that peer is using AddPath.
3964 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3965 if (pi
->peer
!= peer
)
3968 /* graceful restart STALE flag set. */
3969 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3970 && peer
->nsf
[afi
][safi
]
3971 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3972 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3973 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3975 /* If this is an EVPN route, process for
3977 if (safi
== SAFI_EVPN
)
3978 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3980 /* Handle withdraw for VRF route-leaking and L3VPN */
3981 if (SAFI_UNICAST
== safi
3982 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3983 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3984 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3987 if (SAFI_MPLS_VPN
== safi
&&
3988 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3989 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3992 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3998 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4000 struct bgp_clear_node_queue
*cnq
= data
;
4001 struct bgp_node
*rn
= cnq
->rn
;
4002 struct bgp_table
*table
= bgp_node_table(rn
);
4004 bgp_unlock_node(rn
);
4005 bgp_table_unlock(table
);
4006 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4009 static void bgp_clear_node_complete(struct work_queue
*wq
)
4011 struct peer
*peer
= wq
->spec
.data
;
4013 /* Tickle FSM to start moving again */
4014 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4016 peer_unlock(peer
); /* bgp_clear_route */
4019 static void bgp_clear_node_queue_init(struct peer
*peer
)
4021 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4023 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4024 #undef CLEAR_QUEUE_NAME_LEN
4026 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4027 peer
->clear_node_queue
->spec
.hold
= 10;
4028 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4029 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4030 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4031 peer
->clear_node_queue
->spec
.max_retries
= 0;
4033 /* we only 'lock' this peer reference when the queue is actually active
4035 peer
->clear_node_queue
->spec
.data
= peer
;
4038 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4039 struct bgp_table
*table
)
4041 struct bgp_node
*rn
;
4042 int force
= bm
->process_main_queue
? 0 : 1;
4045 table
= peer
->bgp
->rib
[afi
][safi
];
4047 /* If still no table => afi/safi isn't configured at all or smth. */
4051 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4052 struct bgp_path_info
*pi
, *next
;
4053 struct bgp_adj_in
*ain
;
4054 struct bgp_adj_in
*ain_next
;
4056 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4057 * queued for every clearing peer, regardless of whether it is
4058 * relevant to the peer at hand.
4060 * Overview: There are 3 different indices which need to be
4061 * scrubbed, potentially, when a peer is removed:
4063 * 1 peer's routes visible via the RIB (ie accepted routes)
4064 * 2 peer's routes visible by the (optional) peer's adj-in index
4065 * 3 other routes visible by the peer's adj-out index
4067 * 3 there is no hurry in scrubbing, once the struct peer is
4068 * removed from bgp->peer, we could just GC such deleted peer's
4069 * adj-outs at our leisure.
4071 * 1 and 2 must be 'scrubbed' in some way, at least made
4072 * invisible via RIB index before peer session is allowed to be
4073 * brought back up. So one needs to know when such a 'search' is
4078 * - there'd be a single global queue or a single RIB walker
4079 * - rather than tracking which route_nodes still need to be
4080 * examined on a peer basis, we'd track which peers still
4083 * Given that our per-peer prefix-counts now should be reliable,
4084 * this may actually be achievable. It doesn't seem to be a huge
4085 * problem at this time,
4087 * It is possible that we have multiple paths for a prefix from
4089 * if that peer is using AddPath.
4093 ain_next
= ain
->next
;
4095 if (ain
->peer
== peer
) {
4096 bgp_adj_in_remove(rn
, ain
);
4097 bgp_unlock_node(rn
);
4103 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4105 if (pi
->peer
!= peer
)
4109 bgp_path_info_reap(rn
, pi
);
4111 struct bgp_clear_node_queue
*cnq
;
4113 /* both unlocked in bgp_clear_node_queue_del */
4114 bgp_table_lock(bgp_node_table(rn
));
4117 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4118 sizeof(struct bgp_clear_node_queue
));
4120 work_queue_add(peer
->clear_node_queue
, cnq
);
4128 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4130 struct bgp_node
*rn
;
4131 struct bgp_table
*table
;
4133 if (peer
->clear_node_queue
== NULL
)
4134 bgp_clear_node_queue_init(peer
);
4136 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4137 * Idle until it receives a Clearing_Completed event. This protects
4138 * against peers which flap faster than we can we clear, which could
4141 * a) race with routes from the new session being installed before
4142 * clear_route_node visits the node (to delete the route of that
4144 * b) resource exhaustion, clear_route_node likely leads to an entry
4145 * on the process_main queue. Fast-flapping could cause that queue
4149 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4150 * the unlock will happen upon work-queue completion; other wise, the
4151 * unlock happens at the end of this function.
4153 if (!peer
->clear_node_queue
->thread
)
4156 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4157 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4159 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4160 rn
= bgp_route_next(rn
)) {
4161 table
= bgp_node_get_bgp_table_info(rn
);
4165 bgp_clear_route_table(peer
, afi
, safi
, table
);
4168 /* unlock if no nodes got added to the clear-node-queue. */
4169 if (!peer
->clear_node_queue
->thread
)
4173 void bgp_clear_route_all(struct peer
*peer
)
4178 FOREACH_AFI_SAFI (afi
, safi
)
4179 bgp_clear_route(peer
, afi
, safi
);
4182 rfapiProcessPeerDown(peer
);
4186 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4188 struct bgp_table
*table
;
4189 struct bgp_node
*rn
;
4190 struct bgp_adj_in
*ain
;
4191 struct bgp_adj_in
*ain_next
;
4193 table
= peer
->bgp
->rib
[afi
][safi
];
4195 /* It is possible that we have multiple paths for a prefix from a peer
4196 * if that peer is using AddPath.
4198 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4202 ain_next
= ain
->next
;
4204 if (ain
->peer
== peer
) {
4205 bgp_adj_in_remove(rn
, ain
);
4206 bgp_unlock_node(rn
);
4214 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4216 struct bgp_node
*rn
;
4217 struct bgp_path_info
*pi
;
4218 struct bgp_table
*table
;
4220 if (safi
== SAFI_MPLS_VPN
) {
4221 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4222 rn
= bgp_route_next(rn
)) {
4223 struct bgp_node
*rm
;
4225 /* look for neighbor in tables */
4226 table
= bgp_node_get_bgp_table_info(rn
);
4230 for (rm
= bgp_table_top(table
); rm
;
4231 rm
= bgp_route_next(rm
))
4232 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4234 if (pi
->peer
!= peer
)
4236 if (!CHECK_FLAG(pi
->flags
,
4240 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4245 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4246 rn
= bgp_route_next(rn
))
4247 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4249 if (pi
->peer
!= peer
)
4251 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4253 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4259 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4261 if (peer
->sort
== BGP_PEER_EBGP
4262 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4263 || FILTER_LIST_OUT_NAME(filter
)
4264 || DISTRIBUTE_OUT_NAME(filter
)))
4269 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4271 if (peer
->sort
== BGP_PEER_EBGP
4272 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4273 || FILTER_LIST_IN_NAME(filter
)
4274 || DISTRIBUTE_IN_NAME(filter
)))
4279 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4282 struct bgp_node
*rn
;
4283 struct bgp_path_info
*pi
;
4284 struct bgp_path_info
*next
;
4286 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4287 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4290 /* Unimport EVPN routes from VRFs */
4291 if (safi
== SAFI_EVPN
)
4292 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4296 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4297 && pi
->type
== ZEBRA_ROUTE_BGP
4298 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4299 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4300 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4302 if (bgp_fibupd_safi(safi
))
4303 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4305 bgp_path_info_reap(rn
, pi
);
4310 /* Delete all kernel routes. */
4311 void bgp_cleanup_routes(struct bgp
*bgp
)
4314 struct bgp_node
*rn
;
4315 struct bgp_table
*table
;
4317 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4318 if (afi
== AFI_L2VPN
)
4320 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4323 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4325 if (afi
!= AFI_L2VPN
) {
4327 safi
= SAFI_MPLS_VPN
;
4328 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4329 rn
= bgp_route_next(rn
)) {
4330 table
= bgp_node_get_bgp_table_info(rn
);
4331 if (table
!= NULL
) {
4332 bgp_cleanup_table(bgp
, table
, safi
);
4333 bgp_table_finish(&table
);
4334 bgp_node_set_bgp_table_info(rn
, NULL
);
4335 bgp_unlock_node(rn
);
4339 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4340 rn
= bgp_route_next(rn
)) {
4341 table
= bgp_node_get_bgp_table_info(rn
);
4342 if (table
!= NULL
) {
4343 bgp_cleanup_table(bgp
, table
, safi
);
4344 bgp_table_finish(&table
);
4345 bgp_node_set_bgp_table_info(rn
, NULL
);
4346 bgp_unlock_node(rn
);
4351 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4352 rn
= bgp_route_next(rn
)) {
4353 table
= bgp_node_get_bgp_table_info(rn
);
4354 if (table
!= NULL
) {
4355 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4356 bgp_table_finish(&table
);
4357 bgp_node_set_bgp_table_info(rn
, NULL
);
4358 bgp_unlock_node(rn
);
4363 void bgp_reset(void)
4366 bgp_zclient_reset();
4367 access_list_reset();
4368 prefix_list_reset();
4371 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4373 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4374 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4375 PEER_CAP_ADDPATH_AF_TX_RCV
));
4378 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4380 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4381 struct bgp_nlri
*packet
)
4390 int addpath_encoded
;
4391 uint32_t addpath_id
;
4394 lim
= pnt
+ packet
->length
;
4396 safi
= packet
->safi
;
4398 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4400 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4401 syntactic validity. If the field is syntactically incorrect,
4402 then the Error Subcode is set to Invalid Network Field. */
4403 for (; pnt
< lim
; pnt
+= psize
) {
4404 /* Clear prefix structure. */
4405 memset(&p
, 0, sizeof(struct prefix
));
4407 if (addpath_encoded
) {
4409 /* When packet overflow occurs return immediately. */
4410 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4411 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4413 addpath_id
= ntohl(*((uint32_t *)pnt
));
4414 pnt
+= BGP_ADDPATH_ID_LEN
;
4417 /* Fetch prefix length. */
4418 p
.prefixlen
= *pnt
++;
4419 /* afi/safi validity already verified by caller,
4420 * bgp_update_receive */
4421 p
.family
= afi2family(afi
);
4423 /* Prefix length check. */
4424 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4427 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4428 peer
->host
, p
.prefixlen
, packet
->afi
);
4429 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4432 /* Packet size overflow check. */
4433 psize
= PSIZE(p
.prefixlen
);
4435 /* When packet overflow occur return immediately. */
4436 if (pnt
+ psize
> lim
) {
4439 "%s [Error] Update packet error (prefix length %d overflows packet)",
4440 peer
->host
, p
.prefixlen
);
4441 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4444 /* Defensive coding, double-check the psize fits in a struct
4446 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4449 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4450 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4451 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4454 /* Fetch prefix from NLRI packet. */
4455 memcpy(p
.u
.val
, pnt
, psize
);
4457 /* Check address. */
4458 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4459 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4460 /* From RFC4271 Section 6.3:
4462 * If a prefix in the NLRI field is semantically
4464 * (e.g., an unexpected multicast IP address),
4466 * be logged locally, and the prefix SHOULD be
4471 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4472 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4477 /* Check address. */
4478 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4479 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4484 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4486 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4491 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4496 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4498 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4505 /* Normal process. */
4507 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4508 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4509 NULL
, NULL
, 0, 0, NULL
);
4511 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4512 safi
, ZEBRA_ROUTE_BGP
,
4513 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4516 /* Do not send BGP notification twice when maximum-prefix count
4518 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4519 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4521 /* Address family configuration mismatch. */
4523 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4526 /* Packet length consistency check. */
4530 "%s [Error] Update packet error (prefix length mismatch with total length)",
4532 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4535 return BGP_NLRI_PARSE_OK
;
4538 static struct bgp_static
*bgp_static_new(void)
4540 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4543 static void bgp_static_free(struct bgp_static
*bgp_static
)
4545 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4546 route_map_counter_decrement(bgp_static
->rmap
.map
);
4548 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4549 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4552 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4553 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4555 struct bgp_node
*rn
;
4556 struct bgp_path_info
*pi
;
4557 struct bgp_path_info
*new;
4558 struct bgp_path_info rmap_path
;
4560 struct attr
*attr_new
;
4563 int vnc_implicit_withdraw
= 0;
4570 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4572 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4574 attr
.nexthop
= bgp_static
->igpnexthop
;
4575 attr
.med
= bgp_static
->igpmetric
;
4576 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4578 if (bgp_static
->atomic
)
4579 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4581 /* Store label index, if required. */
4582 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4583 attr
.label_index
= bgp_static
->label_index
;
4584 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4587 /* Apply route-map. */
4588 if (bgp_static
->rmap
.name
) {
4589 struct attr attr_tmp
= attr
;
4591 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4592 rmap_path
.peer
= bgp
->peer_self
;
4593 rmap_path
.attr
= &attr_tmp
;
4595 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4597 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4600 bgp
->peer_self
->rmap_type
= 0;
4602 if (ret
== RMAP_DENYMATCH
) {
4603 /* Free uninterned attribute. */
4604 bgp_attr_flush(&attr_tmp
);
4606 /* Unintern original. */
4607 aspath_unintern(&attr
.aspath
);
4608 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4612 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4613 bgp_attr_add_gshut_community(&attr_tmp
);
4615 attr_new
= bgp_attr_intern(&attr_tmp
);
4618 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4619 bgp_attr_add_gshut_community(&attr
);
4621 attr_new
= bgp_attr_intern(&attr
);
4624 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4625 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4626 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4630 if (attrhash_cmp(pi
->attr
, attr_new
)
4631 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4632 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4633 bgp_unlock_node(rn
);
4634 bgp_attr_unintern(&attr_new
);
4635 aspath_unintern(&attr
.aspath
);
4638 /* The attribute is changed. */
4639 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4641 /* Rewrite BGP route information. */
4642 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4643 bgp_path_info_restore(rn
, pi
);
4645 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4647 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4648 && (safi
== SAFI_UNICAST
)) {
4649 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4651 * Implicit withdraw case.
4652 * We have to do this before pi is
4655 ++vnc_implicit_withdraw
;
4656 vnc_import_bgp_del_route(bgp
, p
, pi
);
4657 vnc_import_bgp_exterior_del_route(
4662 bgp_attr_unintern(&pi
->attr
);
4663 pi
->attr
= attr_new
;
4664 pi
->uptime
= bgp_clock();
4666 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4667 && (safi
== SAFI_UNICAST
)) {
4668 if (vnc_implicit_withdraw
) {
4669 vnc_import_bgp_add_route(bgp
, p
, pi
);
4670 vnc_import_bgp_exterior_add_route(
4676 /* Nexthop reachability check. */
4677 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4678 && (safi
== SAFI_UNICAST
4679 || safi
== SAFI_LABELED_UNICAST
)) {
4681 struct bgp
*bgp_nexthop
= bgp
;
4683 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4684 bgp_nexthop
= pi
->extra
->bgp_orig
;
4686 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4688 bgp_path_info_set_flag(rn
, pi
,
4691 if (BGP_DEBUG(nht
, NHT
)) {
4692 char buf1
[INET6_ADDRSTRLEN
];
4693 inet_ntop(p
->family
,
4697 "%s(%s): Route not in table, not advertising",
4698 __FUNCTION__
, buf1
);
4700 bgp_path_info_unset_flag(
4701 rn
, pi
, BGP_PATH_VALID
);
4704 /* Delete the NHT structure if any, if we're
4706 * enabling/disabling import check. We
4707 * deregister the route
4708 * from NHT to avoid overloading NHT and the
4709 * process interaction
4711 bgp_unlink_nexthop(pi
);
4712 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4714 /* Process change. */
4715 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4716 bgp_process(bgp
, rn
, afi
, safi
);
4718 if (SAFI_UNICAST
== safi
4719 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4721 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4722 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4726 bgp_unlock_node(rn
);
4727 aspath_unintern(&attr
.aspath
);
4732 /* Make new BGP info. */
4733 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4735 /* Nexthop reachability check. */
4736 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4737 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4738 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4739 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4741 if (BGP_DEBUG(nht
, NHT
)) {
4742 char buf1
[INET6_ADDRSTRLEN
];
4743 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4746 "%s(%s): Route not in table, not advertising",
4747 __FUNCTION__
, buf1
);
4749 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4752 /* Delete the NHT structure if any, if we're toggling between
4753 * enabling/disabling import check. We deregister the route
4754 * from NHT to avoid overloading NHT and the process interaction
4756 bgp_unlink_nexthop(new);
4758 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4761 /* Aggregate address increment. */
4762 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4764 /* Register new BGP information. */
4765 bgp_path_info_add(rn
, new);
4767 /* route_node_get lock */
4768 bgp_unlock_node(rn
);
4770 /* Process change. */
4771 bgp_process(bgp
, rn
, afi
, safi
);
4773 if (SAFI_UNICAST
== safi
4774 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4775 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4776 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4779 /* Unintern original. */
4780 aspath_unintern(&attr
.aspath
);
4783 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4786 struct bgp_node
*rn
;
4787 struct bgp_path_info
*pi
;
4789 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4791 /* Check selected route and self inserted route. */
4792 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4793 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4794 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4797 /* Withdraw static BGP route from routing table. */
4799 if (SAFI_UNICAST
== safi
4800 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4801 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4802 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4804 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4805 bgp_unlink_nexthop(pi
);
4806 bgp_path_info_delete(rn
, pi
);
4807 bgp_process(bgp
, rn
, afi
, safi
);
4810 /* Unlock bgp_node_lookup. */
4811 bgp_unlock_node(rn
);
4815 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4817 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4818 afi_t afi
, safi_t safi
,
4819 struct prefix_rd
*prd
)
4821 struct bgp_node
*rn
;
4822 struct bgp_path_info
*pi
;
4824 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4826 /* Check selected route and self inserted route. */
4827 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4828 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4829 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4832 /* Withdraw static BGP route from routing table. */
4835 rfapiProcessWithdraw(
4836 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4837 1); /* Kill, since it is an administrative change */
4839 if (SAFI_MPLS_VPN
== safi
4840 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4841 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4843 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4844 bgp_path_info_delete(rn
, pi
);
4845 bgp_process(bgp
, rn
, afi
, safi
);
4848 /* Unlock bgp_node_lookup. */
4849 bgp_unlock_node(rn
);
4852 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4853 struct bgp_static
*bgp_static
, afi_t afi
,
4856 struct bgp_node
*rn
;
4857 struct bgp_path_info
*new;
4858 struct attr
*attr_new
;
4859 struct attr attr
= {0};
4860 struct bgp_path_info
*pi
;
4862 mpls_label_t label
= 0;
4864 uint32_t num_labels
= 0;
4869 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4871 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4874 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4876 attr
.nexthop
= bgp_static
->igpnexthop
;
4877 attr
.med
= bgp_static
->igpmetric
;
4878 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4880 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4881 || (safi
== SAFI_ENCAP
)) {
4882 if (afi
== AFI_IP
) {
4883 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4884 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4887 if (afi
== AFI_L2VPN
) {
4888 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4890 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4891 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4892 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4893 sizeof(struct in6_addr
));
4894 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4895 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4896 struct bgp_encap_type_vxlan bet
;
4897 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4898 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4899 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4901 if (bgp_static
->router_mac
) {
4902 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4905 /* Apply route-map. */
4906 if (bgp_static
->rmap
.name
) {
4907 struct attr attr_tmp
= attr
;
4908 struct bgp_path_info rmap_path
;
4911 rmap_path
.peer
= bgp
->peer_self
;
4912 rmap_path
.attr
= &attr_tmp
;
4914 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4916 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4919 bgp
->peer_self
->rmap_type
= 0;
4921 if (ret
== RMAP_DENYMATCH
) {
4922 /* Free uninterned attribute. */
4923 bgp_attr_flush(&attr_tmp
);
4925 /* Unintern original. */
4926 aspath_unintern(&attr
.aspath
);
4927 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4932 attr_new
= bgp_attr_intern(&attr_tmp
);
4934 attr_new
= bgp_attr_intern(&attr
);
4937 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4938 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4939 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4943 memset(&add
, 0, sizeof(union gw_addr
));
4944 if (attrhash_cmp(pi
->attr
, attr_new
)
4945 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4946 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4947 bgp_unlock_node(rn
);
4948 bgp_attr_unintern(&attr_new
);
4949 aspath_unintern(&attr
.aspath
);
4952 /* The attribute is changed. */
4953 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4955 /* Rewrite BGP route information. */
4956 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4957 bgp_path_info_restore(rn
, pi
);
4959 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4960 bgp_attr_unintern(&pi
->attr
);
4961 pi
->attr
= attr_new
;
4962 pi
->uptime
= bgp_clock();
4965 label
= decode_label(&pi
->extra
->label
[0]);
4968 /* Process change. */
4969 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4970 bgp_process(bgp
, rn
, afi
, safi
);
4972 if (SAFI_MPLS_VPN
== safi
4973 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4974 vpn_leak_to_vrf_update(bgp
, pi
);
4977 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4978 pi
->attr
, afi
, safi
, pi
->type
,
4979 pi
->sub_type
, &label
);
4981 bgp_unlock_node(rn
);
4982 aspath_unintern(&attr
.aspath
);
4988 /* Make new BGP info. */
4989 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4991 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4992 new->extra
= bgp_path_info_extra_new();
4994 new->extra
->label
[0] = bgp_static
->label
;
4995 new->extra
->num_labels
= num_labels
;
4998 label
= decode_label(&bgp_static
->label
);
5001 /* Aggregate address increment. */
5002 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5004 /* Register new BGP information. */
5005 bgp_path_info_add(rn
, new);
5006 /* route_node_get lock */
5007 bgp_unlock_node(rn
);
5009 /* Process change. */
5010 bgp_process(bgp
, rn
, afi
, safi
);
5012 if (SAFI_MPLS_VPN
== safi
5013 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5014 vpn_leak_to_vrf_update(bgp
, new);
5017 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5018 safi
, new->type
, new->sub_type
, &label
);
5021 /* Unintern original. */
5022 aspath_unintern(&attr
.aspath
);
5025 /* Configure static BGP network. When user don't run zebra, static
5026 route should be installed as valid. */
5027 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5028 const char *ip_str
, afi_t afi
, safi_t safi
,
5029 const char *rmap
, int backdoor
, uint32_t label_index
)
5031 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5034 struct bgp_static
*bgp_static
;
5035 struct bgp_node
*rn
;
5036 uint8_t need_update
= 0;
5038 /* Convert IP prefix string to struct prefix. */
5039 ret
= str2prefix(ip_str
, &p
);
5041 vty_out(vty
, "%% Malformed prefix\n");
5042 return CMD_WARNING_CONFIG_FAILED
;
5044 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5045 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5046 return CMD_WARNING_CONFIG_FAILED
;
5053 /* Set BGP static route configuration. */
5054 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5057 vty_out(vty
, "%% Can't find static route specified\n");
5058 return CMD_WARNING_CONFIG_FAILED
;
5061 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5063 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5064 && (label_index
!= bgp_static
->label_index
)) {
5066 "%% label-index doesn't match static route\n");
5067 return CMD_WARNING_CONFIG_FAILED
;
5070 if ((rmap
&& bgp_static
->rmap
.name
)
5071 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5073 "%% route-map name doesn't match static route\n");
5074 return CMD_WARNING_CONFIG_FAILED
;
5077 /* Update BGP RIB. */
5078 if (!bgp_static
->backdoor
)
5079 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5081 /* Clear configuration. */
5082 bgp_static_free(bgp_static
);
5083 bgp_node_set_bgp_static_info(rn
, NULL
);
5084 bgp_unlock_node(rn
);
5085 bgp_unlock_node(rn
);
5088 /* Set BGP static route configuration. */
5089 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5091 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5093 /* Configuration change. */
5094 /* Label index cannot be changed. */
5095 if (bgp_static
->label_index
!= label_index
) {
5096 vty_out(vty
, "%% cannot change label-index\n");
5097 return CMD_WARNING_CONFIG_FAILED
;
5100 /* Check previous routes are installed into BGP. */
5101 if (bgp_static
->valid
5102 && bgp_static
->backdoor
!= backdoor
)
5105 bgp_static
->backdoor
= backdoor
;
5108 XFREE(MTYPE_ROUTE_MAP_NAME
,
5109 bgp_static
->rmap
.name
);
5110 route_map_counter_decrement(
5111 bgp_static
->rmap
.map
);
5112 bgp_static
->rmap
.name
=
5113 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5114 bgp_static
->rmap
.map
=
5115 route_map_lookup_by_name(rmap
);
5116 route_map_counter_increment(
5117 bgp_static
->rmap
.map
);
5119 XFREE(MTYPE_ROUTE_MAP_NAME
,
5120 bgp_static
->rmap
.name
);
5121 route_map_counter_decrement(
5122 bgp_static
->rmap
.map
);
5123 bgp_static
->rmap
.name
= NULL
;
5124 bgp_static
->rmap
.map
= NULL
;
5125 bgp_static
->valid
= 0;
5127 bgp_unlock_node(rn
);
5129 /* New configuration. */
5130 bgp_static
= bgp_static_new();
5131 bgp_static
->backdoor
= backdoor
;
5132 bgp_static
->valid
= 0;
5133 bgp_static
->igpmetric
= 0;
5134 bgp_static
->igpnexthop
.s_addr
= 0;
5135 bgp_static
->label_index
= label_index
;
5138 XFREE(MTYPE_ROUTE_MAP_NAME
,
5139 bgp_static
->rmap
.name
);
5140 route_map_counter_decrement(
5141 bgp_static
->rmap
.map
);
5142 bgp_static
->rmap
.name
=
5143 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5144 bgp_static
->rmap
.map
=
5145 route_map_lookup_by_name(rmap
);
5146 route_map_counter_increment(
5147 bgp_static
->rmap
.map
);
5149 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5152 bgp_static
->valid
= 1;
5154 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5156 if (!bgp_static
->backdoor
)
5157 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5163 void bgp_static_add(struct bgp
*bgp
)
5167 struct bgp_node
*rn
;
5168 struct bgp_node
*rm
;
5169 struct bgp_table
*table
;
5170 struct bgp_static
*bgp_static
;
5172 FOREACH_AFI_SAFI (afi
, safi
)
5173 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5174 rn
= bgp_route_next(rn
)) {
5175 if (!bgp_node_has_bgp_path_info_data(rn
))
5178 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5179 || (safi
== SAFI_EVPN
)) {
5180 table
= bgp_node_get_bgp_table_info(rn
);
5182 for (rm
= bgp_table_top(table
); rm
;
5183 rm
= bgp_route_next(rm
)) {
5185 bgp_node_get_bgp_static_info(
5187 bgp_static_update_safi(bgp
, &rm
->p
,
5194 bgp_node_get_bgp_static_info(rn
), afi
,
5200 /* Called from bgp_delete(). Delete all static routes from the BGP
5202 void bgp_static_delete(struct bgp
*bgp
)
5206 struct bgp_node
*rn
;
5207 struct bgp_node
*rm
;
5208 struct bgp_table
*table
;
5209 struct bgp_static
*bgp_static
;
5211 FOREACH_AFI_SAFI (afi
, safi
)
5212 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5213 rn
= bgp_route_next(rn
)) {
5214 if (!bgp_node_has_bgp_path_info_data(rn
))
5217 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5218 || (safi
== SAFI_EVPN
)) {
5219 table
= bgp_node_get_bgp_table_info(rn
);
5221 for (rm
= bgp_table_top(table
); rm
;
5222 rm
= bgp_route_next(rm
)) {
5224 bgp_node_get_bgp_static_info(
5229 bgp_static_withdraw_safi(
5230 bgp
, &rm
->p
, AFI_IP
, safi
,
5231 (struct prefix_rd
*)&rn
->p
);
5232 bgp_static_free(bgp_static
);
5233 bgp_node_set_bgp_static_info(rn
, NULL
);
5234 bgp_unlock_node(rn
);
5237 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5238 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5239 bgp_static_free(bgp_static
);
5240 bgp_node_set_bgp_static_info(rn
, NULL
);
5241 bgp_unlock_node(rn
);
5246 void bgp_static_redo_import_check(struct bgp
*bgp
)
5250 struct bgp_node
*rn
;
5251 struct bgp_node
*rm
;
5252 struct bgp_table
*table
;
5253 struct bgp_static
*bgp_static
;
5255 /* Use this flag to force reprocessing of the route */
5256 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5257 FOREACH_AFI_SAFI (afi
, safi
) {
5258 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5259 rn
= bgp_route_next(rn
)) {
5260 if (!bgp_node_has_bgp_path_info_data(rn
))
5263 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5264 || (safi
== SAFI_EVPN
)) {
5265 table
= bgp_node_get_bgp_table_info(rn
);
5267 for (rm
= bgp_table_top(table
); rm
;
5268 rm
= bgp_route_next(rm
)) {
5270 bgp_node_get_bgp_static_info(
5272 bgp_static_update_safi(bgp
, &rm
->p
,
5277 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5278 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5283 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5286 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5289 struct bgp_table
*table
;
5290 struct bgp_node
*rn
;
5291 struct bgp_path_info
*pi
;
5293 table
= bgp
->rib
[afi
][safi
];
5294 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5295 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5296 if (pi
->peer
== bgp
->peer_self
5297 && ((pi
->type
== ZEBRA_ROUTE_BGP
5298 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5299 || (pi
->type
!= ZEBRA_ROUTE_BGP
5301 == BGP_ROUTE_REDISTRIBUTE
))) {
5302 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5304 bgp_unlink_nexthop(pi
);
5305 bgp_path_info_delete(rn
, pi
);
5306 bgp_process(bgp
, rn
, afi
, safi
);
5313 * Purge all networks and redistributed routes from routing table.
5314 * Invoked upon the instance going down.
5316 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5321 FOREACH_AFI_SAFI (afi
, safi
)
5322 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5327 * Currently this is used to set static routes for VPN and ENCAP.
5328 * I think it can probably be factored with bgp_static_set.
5330 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5331 const char *ip_str
, const char *rd_str
,
5332 const char *label_str
, const char *rmap_str
,
5333 int evpn_type
, const char *esi
, const char *gwip
,
5334 const char *ethtag
, const char *routermac
)
5336 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5339 struct prefix_rd prd
;
5340 struct bgp_node
*prn
;
5341 struct bgp_node
*rn
;
5342 struct bgp_table
*table
;
5343 struct bgp_static
*bgp_static
;
5344 mpls_label_t label
= MPLS_INVALID_LABEL
;
5345 struct prefix gw_ip
;
5347 /* validate ip prefix */
5348 ret
= str2prefix(ip_str
, &p
);
5350 vty_out(vty
, "%% Malformed prefix\n");
5351 return CMD_WARNING_CONFIG_FAILED
;
5354 if ((afi
== AFI_L2VPN
)
5355 && (bgp_build_evpn_prefix(evpn_type
,
5356 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5357 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5358 return CMD_WARNING_CONFIG_FAILED
;
5361 ret
= str2prefix_rd(rd_str
, &prd
);
5363 vty_out(vty
, "%% Malformed rd\n");
5364 return CMD_WARNING_CONFIG_FAILED
;
5368 unsigned long label_val
;
5369 label_val
= strtoul(label_str
, NULL
, 10);
5370 encode_label(label_val
, &label
);
5373 if (safi
== SAFI_EVPN
) {
5374 if (esi
&& str2esi(esi
, NULL
) == 0) {
5375 vty_out(vty
, "%% Malformed ESI\n");
5376 return CMD_WARNING_CONFIG_FAILED
;
5378 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5379 vty_out(vty
, "%% Malformed Router MAC\n");
5380 return CMD_WARNING_CONFIG_FAILED
;
5383 memset(&gw_ip
, 0, sizeof(struct prefix
));
5384 ret
= str2prefix(gwip
, &gw_ip
);
5386 vty_out(vty
, "%% Malformed GatewayIp\n");
5387 return CMD_WARNING_CONFIG_FAILED
;
5389 if ((gw_ip
.family
== AF_INET
5390 && is_evpn_prefix_ipaddr_v6(
5391 (struct prefix_evpn
*)&p
))
5392 || (gw_ip
.family
== AF_INET6
5393 && is_evpn_prefix_ipaddr_v4(
5394 (struct prefix_evpn
*)&p
))) {
5396 "%% GatewayIp family differs with IP prefix\n");
5397 return CMD_WARNING_CONFIG_FAILED
;
5401 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5402 if (!bgp_node_has_bgp_path_info_data(prn
))
5403 bgp_node_set_bgp_table_info(prn
,
5404 bgp_table_init(bgp
, afi
, safi
));
5405 table
= bgp_node_get_bgp_table_info(prn
);
5407 rn
= bgp_node_get(table
, &p
);
5409 if (bgp_node_has_bgp_path_info_data(rn
)) {
5410 vty_out(vty
, "%% Same network configuration exists\n");
5411 bgp_unlock_node(rn
);
5413 /* New configuration. */
5414 bgp_static
= bgp_static_new();
5415 bgp_static
->backdoor
= 0;
5416 bgp_static
->valid
= 0;
5417 bgp_static
->igpmetric
= 0;
5418 bgp_static
->igpnexthop
.s_addr
= 0;
5419 bgp_static
->label
= label
;
5420 bgp_static
->prd
= prd
;
5423 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5424 route_map_counter_decrement(bgp_static
->rmap
.map
);
5425 bgp_static
->rmap
.name
=
5426 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5427 bgp_static
->rmap
.map
=
5428 route_map_lookup_by_name(rmap_str
);
5429 route_map_counter_increment(bgp_static
->rmap
.map
);
5432 if (safi
== SAFI_EVPN
) {
5434 bgp_static
->eth_s_id
=
5436 sizeof(struct eth_segment_id
));
5437 str2esi(esi
, bgp_static
->eth_s_id
);
5440 bgp_static
->router_mac
=
5441 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5442 (void)prefix_str2mac(routermac
,
5443 bgp_static
->router_mac
);
5446 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5448 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5450 bgp_static
->valid
= 1;
5451 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5457 /* Configure static BGP network. */
5458 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5459 const char *ip_str
, const char *rd_str
,
5460 const char *label_str
, int evpn_type
, const char *esi
,
5461 const char *gwip
, const char *ethtag
)
5463 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5466 struct prefix_rd prd
;
5467 struct bgp_node
*prn
;
5468 struct bgp_node
*rn
;
5469 struct bgp_table
*table
;
5470 struct bgp_static
*bgp_static
;
5471 mpls_label_t label
= MPLS_INVALID_LABEL
;
5473 /* Convert IP prefix string to struct prefix. */
5474 ret
= str2prefix(ip_str
, &p
);
5476 vty_out(vty
, "%% Malformed prefix\n");
5477 return CMD_WARNING_CONFIG_FAILED
;
5480 if ((afi
== AFI_L2VPN
)
5481 && (bgp_build_evpn_prefix(evpn_type
,
5482 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5483 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5484 return CMD_WARNING_CONFIG_FAILED
;
5486 ret
= str2prefix_rd(rd_str
, &prd
);
5488 vty_out(vty
, "%% Malformed rd\n");
5489 return CMD_WARNING_CONFIG_FAILED
;
5493 unsigned long label_val
;
5494 label_val
= strtoul(label_str
, NULL
, 10);
5495 encode_label(label_val
, &label
);
5498 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5499 if (!bgp_node_has_bgp_path_info_data(prn
))
5500 bgp_node_set_bgp_table_info(prn
,
5501 bgp_table_init(bgp
, afi
, safi
));
5503 bgp_unlock_node(prn
);
5504 table
= bgp_node_get_bgp_table_info(prn
);
5506 rn
= bgp_node_lookup(table
, &p
);
5509 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5511 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5512 bgp_static_free(bgp_static
);
5513 bgp_node_set_bgp_static_info(rn
, NULL
);
5514 bgp_unlock_node(rn
);
5515 bgp_unlock_node(rn
);
5517 vty_out(vty
, "%% Can't find the route\n");
5522 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5523 const char *rmap_name
)
5525 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5526 struct bgp_rmap
*rmap
;
5528 rmap
= &bgp
->table_map
[afi
][safi
];
5530 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5531 route_map_counter_decrement(rmap
->map
);
5532 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5533 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5534 route_map_counter_increment(rmap
->map
);
5536 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5537 route_map_counter_decrement(rmap
->map
);
5542 if (bgp_fibupd_safi(safi
))
5543 bgp_zebra_announce_table(bgp
, afi
, safi
);
5548 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5549 const char *rmap_name
)
5551 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5552 struct bgp_rmap
*rmap
;
5554 rmap
= &bgp
->table_map
[afi
][safi
];
5555 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5556 route_map_counter_decrement(rmap
->map
);
5560 if (bgp_fibupd_safi(safi
))
5561 bgp_zebra_announce_table(bgp
, afi
, safi
);
5566 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5569 if (bgp
->table_map
[afi
][safi
].name
) {
5570 vty_out(vty
, " table-map %s\n",
5571 bgp
->table_map
[afi
][safi
].name
);
5575 DEFUN (bgp_table_map
,
5578 "BGP table to RIB route download filter\n"
5579 "Name of the route map\n")
5582 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5583 argv
[idx_word
]->arg
);
5585 DEFUN (no_bgp_table_map
,
5586 no_bgp_table_map_cmd
,
5587 "no table-map WORD",
5589 "BGP table to RIB route download filter\n"
5590 "Name of the route map\n")
5593 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5594 argv
[idx_word
]->arg
);
5600 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5601 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5602 backdoor$backdoor}]",
5604 "Specify a network to announce via BGP\n"
5609 "Route-map to modify the attributes\n"
5610 "Name of the route map\n"
5611 "Label index to associate with the prefix\n"
5612 "Label index value\n"
5613 "Specify a BGP backdoor route\n")
5615 char addr_prefix_str
[BUFSIZ
];
5620 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5623 vty_out(vty
, "%% Inconsistent address and mask\n");
5624 return CMD_WARNING_CONFIG_FAILED
;
5628 return bgp_static_set(
5629 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5630 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5631 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5634 DEFPY(ipv6_bgp_network
,
5635 ipv6_bgp_network_cmd
,
5636 "[no] network X:X::X:X/M$prefix \
5637 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5639 "Specify a network to announce via BGP\n"
5641 "Route-map to modify the attributes\n"
5642 "Name of the route map\n"
5643 "Label index to associate with the prefix\n"
5644 "Label index value\n")
5646 return bgp_static_set(
5647 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5648 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5651 static struct bgp_aggregate
*bgp_aggregate_new(void)
5653 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5656 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5658 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5661 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5662 struct aspath
*aspath
,
5663 struct community
*comm
,
5664 struct ecommunity
*ecomm
,
5665 struct lcommunity
*lcomm
)
5667 static struct aspath
*ae
= NULL
;
5670 ae
= aspath_empty();
5675 if (origin
!= pi
->attr
->origin
)
5678 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5681 if (!community_cmp(pi
->attr
->community
, comm
))
5684 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5687 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5690 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5696 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5697 struct prefix
*p
, uint8_t origin
,
5698 struct aspath
*aspath
,
5699 struct community
*community
,
5700 struct ecommunity
*ecommunity
,
5701 struct lcommunity
*lcommunity
,
5702 uint8_t atomic_aggregate
,
5703 struct bgp_aggregate
*aggregate
)
5705 struct bgp_node
*rn
;
5706 struct bgp_table
*table
;
5707 struct bgp_path_info
*pi
, *orig
, *new;
5709 table
= bgp
->rib
[afi
][safi
];
5711 rn
= bgp_node_get(table
, p
);
5713 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5714 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5715 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5718 if (aggregate
->count
> 0) {
5720 * If the aggregate information has not changed
5721 * no need to re-install it again.
5723 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5724 ecommunity
, lcommunity
)) {
5725 bgp_unlock_node(rn
);
5728 aspath_free(aspath
);
5730 community_free(&community
);
5732 ecommunity_free(&ecommunity
);
5734 lcommunity_free(&lcommunity
);
5740 * Mark the old as unusable
5743 bgp_path_info_delete(rn
, pi
);
5745 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5747 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5748 community
, ecommunity
,
5753 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5755 bgp_path_info_add(rn
, new);
5756 bgp_process(bgp
, rn
, afi
, safi
);
5758 for (pi
= orig
; pi
; pi
= pi
->next
)
5759 if (pi
->peer
== bgp
->peer_self
5760 && pi
->type
== ZEBRA_ROUTE_BGP
5761 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5764 /* Withdraw static BGP route from routing table. */
5766 bgp_path_info_delete(rn
, pi
);
5767 bgp_process(bgp
, rn
, afi
, safi
);
5771 bgp_unlock_node(rn
);
5774 /* Update an aggregate as routes are added/removed from the BGP table */
5775 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5776 afi_t afi
, safi_t safi
,
5777 struct bgp_aggregate
*aggregate
)
5779 struct bgp_table
*table
;
5780 struct bgp_node
*top
;
5781 struct bgp_node
*rn
;
5783 struct aspath
*aspath
= NULL
;
5784 struct community
*community
= NULL
;
5785 struct ecommunity
*ecommunity
= NULL
;
5786 struct lcommunity
*lcommunity
= NULL
;
5787 struct bgp_path_info
*pi
;
5788 unsigned long match
= 0;
5789 uint8_t atomic_aggregate
= 0;
5791 /* If the bgp instance is being deleted or self peer is deleted
5792 * then do not create aggregate route
5794 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5795 (bgp
->peer_self
== NULL
))
5798 /* ORIGIN attribute: If at least one route among routes that are
5799 aggregated has ORIGIN with the value INCOMPLETE, then the
5800 aggregated route must have the ORIGIN attribute with the value
5801 INCOMPLETE. Otherwise, if at least one route among routes that
5802 are aggregated has ORIGIN with the value EGP, then the aggregated
5803 route must have the origin attribute with the value EGP. In all
5804 other case the value of the ORIGIN attribute of the aggregated
5805 route is INTERNAL. */
5806 origin
= BGP_ORIGIN_IGP
;
5808 table
= bgp
->rib
[afi
][safi
];
5810 top
= bgp_node_get(table
, p
);
5811 for (rn
= bgp_node_get(table
, p
); rn
;
5812 rn
= bgp_route_next_until(rn
, top
)) {
5813 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5818 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5819 if (BGP_PATH_HOLDDOWN(pi
))
5823 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5824 atomic_aggregate
= 1;
5826 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5830 * summary-only aggregate route suppress
5831 * aggregated route announcements.
5833 if (aggregate
->summary_only
) {
5834 (bgp_path_info_extra_get(pi
))->suppress
++;
5835 bgp_path_info_set_flag(rn
, pi
,
5836 BGP_PATH_ATTR_CHANGED
);
5843 * If at least one route among routes that are
5844 * aggregated has ORIGIN with the value INCOMPLETE,
5845 * then the aggregated route MUST have the ORIGIN
5846 * attribute with the value INCOMPLETE. Otherwise, if
5847 * at least one route among routes that are aggregated
5848 * has ORIGIN with the value EGP, then the aggregated
5849 * route MUST have the ORIGIN attribute with the value
5852 switch (pi
->attr
->origin
) {
5853 case BGP_ORIGIN_INCOMPLETE
:
5854 aggregate
->incomplete_origin_count
++;
5856 case BGP_ORIGIN_EGP
:
5857 aggregate
->egp_origin_count
++;
5865 if (!aggregate
->as_set
)
5869 * as-set aggregate route generate origin, as path,
5870 * and community aggregation.
5872 /* Compute aggregate route's as-path.
5874 bgp_compute_aggregate_aspath(aggregate
,
5877 /* Compute aggregate route's community.
5879 if (pi
->attr
->community
)
5880 bgp_compute_aggregate_community(
5882 pi
->attr
->community
);
5884 /* Compute aggregate route's extended community.
5886 if (pi
->attr
->ecommunity
)
5887 bgp_compute_aggregate_ecommunity(
5889 pi
->attr
->ecommunity
);
5891 /* Compute aggregate route's large community.
5893 if (pi
->attr
->lcommunity
)
5894 bgp_compute_aggregate_lcommunity(
5896 pi
->attr
->lcommunity
);
5899 bgp_process(bgp
, rn
, afi
, safi
);
5901 bgp_unlock_node(top
);
5904 if (aggregate
->incomplete_origin_count
> 0)
5905 origin
= BGP_ORIGIN_INCOMPLETE
;
5906 else if (aggregate
->egp_origin_count
> 0)
5907 origin
= BGP_ORIGIN_EGP
;
5909 if (aggregate
->as_set
) {
5910 if (aggregate
->aspath
)
5911 /* Retrieve aggregate route's as-path.
5913 aspath
= aspath_dup(aggregate
->aspath
);
5915 if (aggregate
->community
)
5916 /* Retrieve aggregate route's community.
5918 community
= community_dup(aggregate
->community
);
5920 if (aggregate
->ecommunity
)
5921 /* Retrieve aggregate route's ecommunity.
5923 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
5925 if (aggregate
->lcommunity
)
5926 /* Retrieve aggregate route's lcommunity.
5928 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
5931 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5932 ecommunity
, lcommunity
, atomic_aggregate
,
5936 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5937 safi_t safi
, struct bgp_aggregate
*aggregate
)
5939 struct bgp_table
*table
;
5940 struct bgp_node
*top
;
5941 struct bgp_node
*rn
;
5942 struct bgp_path_info
*pi
;
5943 unsigned long match
;
5945 table
= bgp
->rib
[afi
][safi
];
5947 /* If routes exists below this node, generate aggregate routes. */
5948 top
= bgp_node_get(table
, p
);
5949 for (rn
= bgp_node_get(table
, p
); rn
;
5950 rn
= bgp_route_next_until(rn
, top
)) {
5951 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5955 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5956 if (BGP_PATH_HOLDDOWN(pi
))
5959 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5962 if (aggregate
->summary_only
&& pi
->extra
) {
5963 pi
->extra
->suppress
--;
5965 if (pi
->extra
->suppress
== 0) {
5966 bgp_path_info_set_flag(
5967 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5973 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
5974 aggregate
->incomplete_origin_count
--;
5975 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
5976 aggregate
->egp_origin_count
--;
5978 if (aggregate
->as_set
) {
5979 /* Remove as-path from aggregate.
5981 bgp_remove_aspath_from_aggregate(
5985 if (pi
->attr
->community
)
5986 /* Remove community from aggregate.
5988 bgp_remove_community_from_aggregate(
5990 pi
->attr
->community
);
5992 if (pi
->attr
->ecommunity
)
5993 /* Remove ecommunity from aggregate.
5995 bgp_remove_ecommunity_from_aggregate(
5997 pi
->attr
->ecommunity
);
5999 if (pi
->attr
->lcommunity
)
6000 /* Remove lcommunity from aggregate.
6002 bgp_remove_lcommunity_from_aggregate(
6004 pi
->attr
->lcommunity
);
6009 /* If this node was suppressed, process the change. */
6011 bgp_process(bgp
, rn
, afi
, safi
);
6013 bgp_unlock_node(top
);
6016 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6017 struct bgp_path_info
*pinew
, afi_t afi
,
6019 struct bgp_aggregate
*aggregate
)
6022 struct aspath
*aspath
= NULL
;
6023 uint8_t atomic_aggregate
= 0;
6024 struct community
*community
= NULL
;
6025 struct ecommunity
*ecommunity
= NULL
;
6026 struct lcommunity
*lcommunity
= NULL
;
6028 /* ORIGIN attribute: If at least one route among routes that are
6029 * aggregated has ORIGIN with the value INCOMPLETE, then the
6030 * aggregated route must have the ORIGIN attribute with the value
6031 * INCOMPLETE. Otherwise, if at least one route among routes that
6032 * are aggregated has ORIGIN with the value EGP, then the aggregated
6033 * route must have the origin attribute with the value EGP. In all
6034 * other case the value of the ORIGIN attribute of the aggregated
6035 * route is INTERNAL.
6037 origin
= BGP_ORIGIN_IGP
;
6041 if (aggregate
->summary_only
)
6042 (bgp_path_info_extra_get(pinew
))->suppress
++;
6044 switch (pinew
->attr
->origin
) {
6045 case BGP_ORIGIN_INCOMPLETE
:
6046 aggregate
->incomplete_origin_count
++;
6048 case BGP_ORIGIN_EGP
:
6049 aggregate
->egp_origin_count
++;
6057 if (aggregate
->incomplete_origin_count
> 0)
6058 origin
= BGP_ORIGIN_INCOMPLETE
;
6059 else if (aggregate
->egp_origin_count
> 0)
6060 origin
= BGP_ORIGIN_EGP
;
6062 if (aggregate
->as_set
) {
6063 /* Compute aggregate route's as-path.
6065 bgp_compute_aggregate_aspath(aggregate
,
6066 pinew
->attr
->aspath
);
6068 /* Compute aggregate route's community.
6070 if (pinew
->attr
->community
)
6071 bgp_compute_aggregate_community(
6073 pinew
->attr
->community
);
6075 /* Compute aggregate route's extended community.
6077 if (pinew
->attr
->ecommunity
)
6078 bgp_compute_aggregate_ecommunity(
6080 pinew
->attr
->ecommunity
);
6082 /* Compute aggregate route's large community.
6084 if (pinew
->attr
->lcommunity
)
6085 bgp_compute_aggregate_lcommunity(
6087 pinew
->attr
->lcommunity
);
6089 /* Retrieve aggregate route's as-path.
6091 if (aggregate
->aspath
)
6092 aspath
= aspath_dup(aggregate
->aspath
);
6094 /* Retrieve aggregate route's community.
6096 if (aggregate
->community
)
6097 community
= community_dup(aggregate
->community
);
6099 /* Retrieve aggregate route's ecommunity.
6101 if (aggregate
->ecommunity
)
6102 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6104 /* Retrieve aggregate route's lcommunity.
6106 if (aggregate
->lcommunity
)
6107 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6110 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6111 aspath
, community
, ecommunity
,
6112 lcommunity
, atomic_aggregate
, aggregate
);
6115 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6117 struct bgp_path_info
*pi
,
6118 struct bgp_aggregate
*aggregate
,
6119 struct prefix
*aggr_p
)
6122 struct aspath
*aspath
= NULL
;
6123 uint8_t atomic_aggregate
= 0;
6124 struct community
*community
= NULL
;
6125 struct ecommunity
*ecommunity
= NULL
;
6126 struct lcommunity
*lcommunity
= NULL
;
6127 unsigned long match
= 0;
6129 if (BGP_PATH_HOLDDOWN(pi
))
6132 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6135 if (aggregate
->summary_only
6137 && pi
->extra
->suppress
> 0) {
6138 pi
->extra
->suppress
--;
6140 if (pi
->extra
->suppress
== 0) {
6141 bgp_path_info_set_flag(pi
->net
, pi
,
6142 BGP_PATH_ATTR_CHANGED
);
6147 if (aggregate
->count
> 0)
6150 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6151 aggregate
->incomplete_origin_count
--;
6152 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6153 aggregate
->egp_origin_count
--;
6155 if (aggregate
->as_set
) {
6156 /* Remove as-path from aggregate.
6158 bgp_remove_aspath_from_aggregate(aggregate
,
6161 if (pi
->attr
->community
)
6162 /* Remove community from aggregate.
6164 bgp_remove_community_from_aggregate(
6166 pi
->attr
->community
);
6168 if (pi
->attr
->ecommunity
)
6169 /* Remove ecommunity from aggregate.
6171 bgp_remove_ecommunity_from_aggregate(
6173 pi
->attr
->ecommunity
);
6175 if (pi
->attr
->lcommunity
)
6176 /* Remove lcommunity from aggregate.
6178 bgp_remove_lcommunity_from_aggregate(
6180 pi
->attr
->lcommunity
);
6183 /* If this node was suppressed, process the change. */
6185 bgp_process(bgp
, pi
->net
, afi
, safi
);
6187 origin
= BGP_ORIGIN_IGP
;
6188 if (aggregate
->incomplete_origin_count
> 0)
6189 origin
= BGP_ORIGIN_INCOMPLETE
;
6190 else if (aggregate
->egp_origin_count
> 0)
6191 origin
= BGP_ORIGIN_EGP
;
6193 if (aggregate
->as_set
) {
6194 /* Retrieve aggregate route's as-path.
6196 if (aggregate
->aspath
)
6197 aspath
= aspath_dup(aggregate
->aspath
);
6199 /* Retrieve aggregate route's community.
6201 if (aggregate
->community
)
6202 community
= community_dup(aggregate
->community
);
6204 /* Retrieve aggregate route's ecommunity.
6206 if (aggregate
->ecommunity
)
6207 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6209 /* Retrieve aggregate route's lcommunity.
6211 if (aggregate
->lcommunity
)
6212 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6215 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6216 aspath
, community
, ecommunity
,
6217 lcommunity
, atomic_aggregate
, aggregate
);
6220 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6221 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6223 struct bgp_node
*child
;
6224 struct bgp_node
*rn
;
6225 struct bgp_aggregate
*aggregate
;
6226 struct bgp_table
*table
;
6228 table
= bgp
->aggregate
[afi
][safi
];
6230 /* No aggregates configured. */
6231 if (bgp_table_top_nolock(table
) == NULL
)
6234 if (p
->prefixlen
== 0)
6237 if (BGP_PATH_HOLDDOWN(pi
))
6240 child
= bgp_node_get(table
, p
);
6242 /* Aggregate address configuration check. */
6243 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6244 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6245 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6246 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6250 bgp_unlock_node(child
);
6253 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6254 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6256 struct bgp_node
*child
;
6257 struct bgp_node
*rn
;
6258 struct bgp_aggregate
*aggregate
;
6259 struct bgp_table
*table
;
6261 table
= bgp
->aggregate
[afi
][safi
];
6263 /* No aggregates configured. */
6264 if (bgp_table_top_nolock(table
) == NULL
)
6267 if (p
->prefixlen
== 0)
6270 child
= bgp_node_get(table
, p
);
6272 /* Aggregate address configuration check. */
6273 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6274 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6275 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6276 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6277 del
, aggregate
, &rn
->p
);
6280 bgp_unlock_node(child
);
6283 /* Aggregate route attribute. */
6284 #define AGGREGATE_SUMMARY_ONLY 1
6285 #define AGGREGATE_AS_SET 1
6287 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6288 afi_t afi
, safi_t safi
)
6290 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6293 struct bgp_node
*rn
;
6294 struct bgp_aggregate
*aggregate
;
6296 /* Convert string to prefix structure. */
6297 ret
= str2prefix(prefix_str
, &p
);
6299 vty_out(vty
, "Malformed prefix\n");
6300 return CMD_WARNING_CONFIG_FAILED
;
6304 /* Old configuration check. */
6305 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6308 "%% There is no aggregate-address configuration.\n");
6309 return CMD_WARNING_CONFIG_FAILED
;
6312 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6313 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6314 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6315 NULL
, NULL
, 0, aggregate
);
6317 /* Unlock aggregate address configuration. */
6318 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6320 if (aggregate
->community
)
6321 community_free(&aggregate
->community
);
6323 if (aggregate
->community_hash
) {
6324 /* Delete all communities in the hash.
6326 hash_clean(aggregate
->community_hash
,
6327 bgp_aggr_community_remove
);
6328 /* Free up the community_hash.
6330 hash_free(aggregate
->community_hash
);
6333 if (aggregate
->ecommunity
)
6334 ecommunity_free(&aggregate
->ecommunity
);
6336 if (aggregate
->ecommunity_hash
) {
6337 /* Delete all ecommunities in the hash.
6339 hash_clean(aggregate
->ecommunity_hash
,
6340 bgp_aggr_ecommunity_remove
);
6341 /* Free up the ecommunity_hash.
6343 hash_free(aggregate
->ecommunity_hash
);
6346 if (aggregate
->lcommunity
)
6347 lcommunity_free(&aggregate
->lcommunity
);
6349 if (aggregate
->lcommunity_hash
) {
6350 /* Delete all lcommunities in the hash.
6352 hash_clean(aggregate
->lcommunity_hash
,
6353 bgp_aggr_lcommunity_remove
);
6354 /* Free up the lcommunity_hash.
6356 hash_free(aggregate
->lcommunity_hash
);
6359 if (aggregate
->aspath
)
6360 aspath_free(aggregate
->aspath
);
6362 if (aggregate
->aspath_hash
) {
6363 /* Delete all as-paths in the hash.
6365 hash_clean(aggregate
->aspath_hash
,
6366 bgp_aggr_aspath_remove
);
6367 /* Free up the aspath_hash.
6369 hash_free(aggregate
->aspath_hash
);
6372 bgp_aggregate_free(aggregate
);
6373 bgp_unlock_node(rn
);
6374 bgp_unlock_node(rn
);
6379 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6380 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6382 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6385 struct bgp_node
*rn
;
6386 struct bgp_aggregate
*aggregate
;
6388 /* Convert string to prefix structure. */
6389 ret
= str2prefix(prefix_str
, &p
);
6391 vty_out(vty
, "Malformed prefix\n");
6392 return CMD_WARNING_CONFIG_FAILED
;
6396 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6397 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6398 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6400 return CMD_WARNING_CONFIG_FAILED
;
6403 /* Old configuration check. */
6404 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6406 if (bgp_node_has_bgp_path_info_data(rn
)) {
6407 vty_out(vty
, "There is already same aggregate network.\n");
6408 /* try to remove the old entry */
6409 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6411 vty_out(vty
, "Error deleting aggregate.\n");
6412 bgp_unlock_node(rn
);
6413 return CMD_WARNING_CONFIG_FAILED
;
6417 /* Make aggregate address structure. */
6418 aggregate
= bgp_aggregate_new();
6419 aggregate
->summary_only
= summary_only
;
6420 aggregate
->as_set
= as_set
;
6421 aggregate
->safi
= safi
;
6422 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6424 /* Aggregate address insert into BGP routing table. */
6425 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6430 DEFUN (aggregate_address
,
6431 aggregate_address_cmd
,
6432 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6433 "Configure BGP aggregate entries\n"
6434 "Aggregate prefix\n"
6435 "Generate AS set path information\n"
6436 "Filter more specific routes from updates\n"
6437 "Filter more specific routes from updates\n"
6438 "Generate AS set path information\n")
6441 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6442 char *prefix
= argv
[idx
]->arg
;
6444 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6446 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6447 ? AGGREGATE_SUMMARY_ONLY
6450 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6451 summary_only
, as_set
);
6454 DEFUN (aggregate_address_mask
,
6455 aggregate_address_mask_cmd
,
6456 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6457 "Configure BGP aggregate entries\n"
6458 "Aggregate address\n"
6460 "Generate AS set path information\n"
6461 "Filter more specific routes from updates\n"
6462 "Filter more specific routes from updates\n"
6463 "Generate AS set path information\n")
6466 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6467 char *prefix
= argv
[idx
]->arg
;
6468 char *mask
= argv
[idx
+ 1]->arg
;
6470 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6472 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6473 ? AGGREGATE_SUMMARY_ONLY
6476 char prefix_str
[BUFSIZ
];
6477 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6480 vty_out(vty
, "%% Inconsistent address and mask\n");
6481 return CMD_WARNING_CONFIG_FAILED
;
6484 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6485 summary_only
, as_set
);
6488 DEFUN (no_aggregate_address
,
6489 no_aggregate_address_cmd
,
6490 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6492 "Configure BGP aggregate entries\n"
6493 "Aggregate prefix\n"
6494 "Generate AS set path information\n"
6495 "Filter more specific routes from updates\n"
6496 "Filter more specific routes from updates\n"
6497 "Generate AS set path information\n")
6500 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6501 char *prefix
= argv
[idx
]->arg
;
6502 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6505 DEFUN (no_aggregate_address_mask
,
6506 no_aggregate_address_mask_cmd
,
6507 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6509 "Configure BGP aggregate entries\n"
6510 "Aggregate address\n"
6512 "Generate AS set path information\n"
6513 "Filter more specific routes from updates\n"
6514 "Filter more specific routes from updates\n"
6515 "Generate AS set path information\n")
6518 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6519 char *prefix
= argv
[idx
]->arg
;
6520 char *mask
= argv
[idx
+ 1]->arg
;
6522 char prefix_str
[BUFSIZ
];
6523 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6526 vty_out(vty
, "%% Inconsistent address and mask\n");
6527 return CMD_WARNING_CONFIG_FAILED
;
6530 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6533 DEFUN (ipv6_aggregate_address
,
6534 ipv6_aggregate_address_cmd
,
6535 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>]",
6536 "Configure BGP aggregate entries\n"
6537 "Aggregate prefix\n"
6538 "Generate AS set path information\n"
6539 "Filter more specific routes from updates\n"
6540 "Filter more specific routes from updates\n"
6541 "Generate AS set path information\n")
6544 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6545 char *prefix
= argv
[idx
]->arg
;
6547 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6550 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6551 ? AGGREGATE_SUMMARY_ONLY
6553 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6557 DEFUN (no_ipv6_aggregate_address
,
6558 no_ipv6_aggregate_address_cmd
,
6559 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>]",
6561 "Configure BGP aggregate entries\n"
6562 "Aggregate prefix\n"
6563 "Generate AS set path information\n"
6564 "Filter more specific routes from updates\n"
6565 "Filter more specific routes from updates\n"
6566 "Generate AS set path information\n")
6569 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6570 char *prefix
= argv
[idx
]->arg
;
6571 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6574 /* Redistribute route treatment. */
6575 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6576 const union g_addr
*nexthop
, ifindex_t ifindex
,
6577 enum nexthop_types_t nhtype
, uint32_t metric
,
6578 uint8_t type
, unsigned short instance
,
6581 struct bgp_path_info
*new;
6582 struct bgp_path_info
*bpi
;
6583 struct bgp_path_info rmap_path
;
6584 struct bgp_node
*bn
;
6586 struct attr
*new_attr
;
6589 struct bgp_redist
*red
;
6591 /* Make default attribute. */
6592 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6595 case NEXTHOP_TYPE_IFINDEX
:
6597 case NEXTHOP_TYPE_IPV4
:
6598 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6599 attr
.nexthop
= nexthop
->ipv4
;
6601 case NEXTHOP_TYPE_IPV6
:
6602 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6603 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6604 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6606 case NEXTHOP_TYPE_BLACKHOLE
:
6607 switch (p
->family
) {
6609 attr
.nexthop
.s_addr
= INADDR_ANY
;
6612 memset(&attr
.mp_nexthop_global
, 0,
6613 sizeof(attr
.mp_nexthop_global
));
6614 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6619 attr
.nh_ifindex
= ifindex
;
6622 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6625 afi
= family2afi(p
->family
);
6627 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6629 struct attr attr_new
;
6631 /* Copy attribute for modification. */
6632 bgp_attr_dup(&attr_new
, &attr
);
6634 if (red
->redist_metric_flag
)
6635 attr_new
.med
= red
->redist_metric
;
6637 /* Apply route-map. */
6638 if (red
->rmap
.name
) {
6639 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6640 rmap_path
.peer
= bgp
->peer_self
;
6641 rmap_path
.attr
= &attr_new
;
6643 SET_FLAG(bgp
->peer_self
->rmap_type
,
6644 PEER_RMAP_TYPE_REDISTRIBUTE
);
6646 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6649 bgp
->peer_self
->rmap_type
= 0;
6651 if (ret
== RMAP_DENYMATCH
) {
6652 /* Free uninterned attribute. */
6653 bgp_attr_flush(&attr_new
);
6655 /* Unintern original. */
6656 aspath_unintern(&attr
.aspath
);
6657 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6662 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6663 bgp_attr_add_gshut_community(&attr_new
);
6665 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6666 SAFI_UNICAST
, p
, NULL
);
6668 new_attr
= bgp_attr_intern(&attr_new
);
6670 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6672 if (bpi
->peer
== bgp
->peer_self
6673 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6677 /* Ensure the (source route) type is updated. */
6679 if (attrhash_cmp(bpi
->attr
, new_attr
)
6680 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6681 bgp_attr_unintern(&new_attr
);
6682 aspath_unintern(&attr
.aspath
);
6683 bgp_unlock_node(bn
);
6686 /* The attribute is changed. */
6687 bgp_path_info_set_flag(bn
, bpi
,
6688 BGP_PATH_ATTR_CHANGED
);
6690 /* Rewrite BGP route information. */
6691 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6692 bgp_path_info_restore(bn
, bpi
);
6694 bgp_aggregate_decrement(
6695 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6696 bgp_attr_unintern(&bpi
->attr
);
6697 bpi
->attr
= new_attr
;
6698 bpi
->uptime
= bgp_clock();
6700 /* Process change. */
6701 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6703 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6704 bgp_unlock_node(bn
);
6705 aspath_unintern(&attr
.aspath
);
6707 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6709 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6711 vpn_leak_from_vrf_update(
6712 bgp_get_default(), bgp
, bpi
);
6718 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6719 bgp
->peer_self
, new_attr
, bn
);
6720 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6722 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6723 bgp_path_info_add(bn
, new);
6724 bgp_unlock_node(bn
);
6725 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6727 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6728 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6730 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6734 /* Unintern original. */
6735 aspath_unintern(&attr
.aspath
);
6738 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6739 unsigned short instance
)
6742 struct bgp_node
*rn
;
6743 struct bgp_path_info
*pi
;
6744 struct bgp_redist
*red
;
6746 afi
= family2afi(p
->family
);
6748 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6750 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6751 SAFI_UNICAST
, p
, NULL
);
6753 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6754 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6758 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6759 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6761 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6764 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6765 bgp_path_info_delete(rn
, pi
);
6766 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6768 bgp_unlock_node(rn
);
6772 /* Withdraw specified route type's route. */
6773 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6774 unsigned short instance
)
6776 struct bgp_node
*rn
;
6777 struct bgp_path_info
*pi
;
6778 struct bgp_table
*table
;
6780 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6782 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6783 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6784 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6785 && pi
->instance
== instance
)
6789 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6790 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6792 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6795 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6797 bgp_path_info_delete(rn
, pi
);
6798 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6803 /* Static function to display route. */
6804 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6811 if (p
->family
== AF_INET
) {
6815 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6818 json_object_string_add(json
, "prefix",
6819 inet_ntop(p
->family
,
6822 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6823 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6824 json_object_string_add(json
, "network", buf2
);
6826 } else if (p
->family
== AF_ETHERNET
) {
6827 prefix2str(p
, buf
, PREFIX_STRLEN
);
6828 len
= vty_out(vty
, "%s", buf
);
6829 } else if (p
->family
== AF_EVPN
) {
6833 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6836 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6837 } else if (p
->family
== AF_FLOWSPEC
) {
6838 route_vty_out_flowspec(vty
, p
, NULL
,
6840 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6841 NLRI_STRING_FORMAT_MIN
, json
);
6846 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6849 json_object_string_add(json
, "prefix",
6850 inet_ntop(p
->family
,
6853 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6854 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6855 json_object_string_add(json
, "network", buf2
);
6862 vty_out(vty
, "\n%*s", 20, " ");
6864 vty_out(vty
, "%*s", len
, " ");
6868 enum bgp_display_type
{
6872 /* Print the short form route status for a bgp_path_info */
6873 static void route_vty_short_status_out(struct vty
*vty
,
6874 struct bgp_path_info
*path
,
6875 json_object
*json_path
)
6879 /* Route status display. */
6880 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6881 json_object_boolean_true_add(json_path
, "removed");
6883 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6884 json_object_boolean_true_add(json_path
, "stale");
6886 if (path
->extra
&& path
->extra
->suppress
)
6887 json_object_boolean_true_add(json_path
, "suppressed");
6889 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6890 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6891 json_object_boolean_true_add(json_path
, "valid");
6894 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6895 json_object_boolean_true_add(json_path
, "history");
6897 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6898 json_object_boolean_true_add(json_path
, "damped");
6900 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6901 json_object_boolean_true_add(json_path
, "bestpath");
6903 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6904 json_object_boolean_true_add(json_path
, "multipath");
6906 /* Internal route. */
6907 if ((path
->peer
->as
)
6908 && (path
->peer
->as
== path
->peer
->local_as
))
6909 json_object_string_add(json_path
, "pathFrom",
6912 json_object_string_add(json_path
, "pathFrom",
6918 /* Route status display. */
6919 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6921 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6923 else if (path
->extra
&& path
->extra
->suppress
)
6925 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6926 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6932 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6934 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6936 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6938 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6943 /* Internal route. */
6944 if (path
->peer
&& (path
->peer
->as
)
6945 && (path
->peer
->as
== path
->peer
->local_as
))
6951 static char *bgp_nexthop_fqdn(struct peer
*peer
)
6953 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
))
6954 return peer
->hostname
;
6958 /* called from terminal list command */
6959 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6960 struct bgp_path_info
*path
, int display
, safi_t safi
,
6961 json_object
*json_paths
)
6964 json_object
*json_path
= NULL
;
6965 json_object
*json_nexthops
= NULL
;
6966 json_object
*json_nexthop_global
= NULL
;
6967 json_object
*json_nexthop_ll
= NULL
;
6968 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6970 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6971 bool nexthop_othervrf
= false;
6972 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6973 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6974 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
6977 json_path
= json_object_new_object();
6979 /* short status lead text */
6980 route_vty_short_status_out(vty
, path
, json_path
);
6983 /* print prefix and mask */
6985 route_vty_out_route(p
, vty
, json_path
);
6987 vty_out(vty
, "%*s", 17, " ");
6989 route_vty_out_route(p
, vty
, json_path
);
6992 /* Print attribute */
6996 json_object_array_add(json_paths
, json_path
);
7004 * If vrf id of nexthop is different from that of prefix,
7005 * set up printable string to append
7007 if (path
->extra
&& path
->extra
->bgp_orig
) {
7008 const char *self
= "";
7013 nexthop_othervrf
= true;
7014 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7016 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7017 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7018 "@%s%s", VRFID_NONE_STR
, self
);
7020 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7021 path
->extra
->bgp_orig
->vrf_id
, self
);
7023 if (path
->extra
->bgp_orig
->inst_type
7024 != BGP_INSTANCE_TYPE_DEFAULT
)
7026 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7028 const char *self
= "";
7033 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7037 * For ENCAP and EVPN routes, nexthop address family is not
7038 * neccessarily the same as the prefix address family.
7039 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7040 * EVPN routes are also exchanged with a MP nexthop. Currently,
7042 * is only IPv4, the value will be present in either
7044 * attr->mp_nexthop_global_in
7046 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7049 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7053 sprintf(nexthop
, "%s",
7054 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7058 sprintf(nexthop
, "%s",
7059 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7063 sprintf(nexthop
, "?");
7068 json_nexthop_global
= json_object_new_object();
7070 json_object_string_add(
7071 json_nexthop_global
, "afi",
7072 nexthop_fqdn
? "fqdn"
7073 : (af
== AF_INET
) ? "ip" : "ipv6");
7074 json_object_string_add(
7075 json_nexthop_global
,
7076 nexthop_fqdn
? "fqdn"
7077 : (af
== AF_INET
) ? "ip" : "ipv6",
7078 nexthop_fqdn
? nexthop_fqdn
: nexthop
);
7079 json_object_boolean_true_add(json_nexthop_global
,
7082 vty_out(vty
, "%s%s",
7083 nexthop_fqdn
? nexthop_fqdn
: nexthop
,
7085 } else if (safi
== SAFI_EVPN
) {
7087 json_nexthop_global
= json_object_new_object();
7089 json_object_string_add(
7090 json_nexthop_global
,
7091 nexthop_fqdn
? "fqdn" : "ip",
7092 nexthop_fqdn
? nexthop_fqdn
7093 : inet_ntoa(attr
->nexthop
));
7094 json_object_string_add(json_nexthop_global
, "afi",
7096 json_object_boolean_true_add(json_nexthop_global
,
7099 vty_out(vty
, "%-16s%s",
7100 nexthop_fqdn
?: inet_ntoa(attr
->nexthop
),
7102 } else if (safi
== SAFI_FLOWSPEC
) {
7103 if (attr
->nexthop
.s_addr
!= 0) {
7105 json_nexthop_global
= json_object_new_object();
7106 json_object_string_add(
7107 json_nexthop_global
,
7108 nexthop_fqdn
? "fqdn" : "ip",
7111 : inet_ntoa(attr
->nexthop
));
7112 json_object_string_add(json_nexthop_global
,
7114 json_object_boolean_true_add(
7115 json_nexthop_global
,
7118 vty_out(vty
, "%-16s",
7121 : inet_ntoa(attr
->nexthop
));
7124 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7126 json_nexthop_global
= json_object_new_object();
7128 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
7129 json_object_string_add(
7130 json_nexthop_global
,
7131 nexthop_fqdn
? "fqdn" : "ip",
7135 attr
->mp_nexthop_global_in
));
7137 json_object_string_add(
7138 json_nexthop_global
,
7139 nexthop_fqdn
? "fqdn" : "ip",
7142 : inet_ntoa(attr
->nexthop
));
7144 json_object_string_add(json_nexthop_global
, "afi",
7146 json_object_boolean_true_add(json_nexthop_global
,
7151 snprintf(buf
, sizeof(buf
), "%s%s",
7152 nexthop_fqdn
? nexthop_fqdn
7153 : inet_ntoa(attr
->nexthop
),
7155 vty_out(vty
, "%-16s", buf
);
7160 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7165 json_nexthop_global
= json_object_new_object();
7166 json_object_string_add(
7167 json_nexthop_global
,
7168 nexthop_fqdn
? "fqdn" : "ip",
7171 : inet_ntop(AF_INET6
,
7172 &attr
->mp_nexthop_global
,
7174 json_object_string_add(json_nexthop_global
, "afi",
7176 json_object_string_add(json_nexthop_global
, "scope",
7179 /* We display both LL & GL if both have been
7181 if ((attr
->mp_nexthop_len
== 32)
7182 || (path
->peer
->conf_if
)) {
7183 json_nexthop_ll
= json_object_new_object();
7184 json_object_string_add(
7186 nexthop_fqdn
? "fqdn" : "ip",
7191 &attr
->mp_nexthop_local
,
7193 json_object_string_add(json_nexthop_ll
, "afi",
7195 json_object_string_add(json_nexthop_ll
, "scope",
7198 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7199 &attr
->mp_nexthop_local
)
7201 && !attr
->mp_nexthop_prefer_global
)
7202 json_object_boolean_true_add(
7203 json_nexthop_ll
, "used");
7205 json_object_boolean_true_add(
7206 json_nexthop_global
, "used");
7208 json_object_boolean_true_add(
7209 json_nexthop_global
, "used");
7211 /* Display LL if LL/Global both in table unless
7212 * prefer-global is set */
7213 if (((attr
->mp_nexthop_len
== 32)
7214 && !attr
->mp_nexthop_prefer_global
)
7215 || (path
->peer
->conf_if
)) {
7216 if (path
->peer
->conf_if
) {
7217 len
= vty_out(vty
, "%s",
7218 path
->peer
->conf_if
);
7219 len
= 16 - len
; /* len of IPv6
7225 vty_out(vty
, "\n%*s", 36, " ");
7227 vty_out(vty
, "%*s", len
, " ");
7235 &attr
->mp_nexthop_local
,
7241 vty_out(vty
, "\n%*s", 36, " ");
7243 vty_out(vty
, "%*s", len
, " ");
7252 &attr
->mp_nexthop_global
,
7258 vty_out(vty
, "\n%*s", 36, " ");
7260 vty_out(vty
, "%*s", len
, " ");
7266 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7270 * Adding "metric" field to match with corresponding
7271 * CLI. "med" will be deprecated in future.
7273 json_object_int_add(json_path
, "med", attr
->med
);
7274 json_object_int_add(json_path
, "metric", attr
->med
);
7276 vty_out(vty
, "%10u", attr
->med
);
7277 else if (!json_paths
)
7281 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7285 * Adding "locPrf" field to match with corresponding
7286 * CLI. "localPref" will be deprecated in future.
7288 json_object_int_add(json_path
, "localpref",
7290 json_object_int_add(json_path
, "locPrf",
7293 vty_out(vty
, "%7u", attr
->local_pref
);
7294 else if (!json_paths
)
7298 json_object_int_add(json_path
, "weight", attr
->weight
);
7300 vty_out(vty
, "%7u ", attr
->weight
);
7304 json_object_string_add(
7305 json_path
, "peerId",
7306 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7314 * Adding "path" field to match with corresponding
7315 * CLI. "aspath" will be deprecated in future.
7317 json_object_string_add(json_path
, "aspath",
7319 json_object_string_add(json_path
, "path",
7322 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7327 json_object_string_add(json_path
, "origin",
7328 bgp_origin_long_str
[attr
->origin
]);
7330 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7334 json_object_boolean_true_add(json_path
,
7335 "announceNexthopSelf");
7336 if (nexthop_othervrf
) {
7337 json_object_string_add(json_path
, "nhVrfName",
7340 json_object_int_add(json_path
, "nhVrfId",
7341 ((nexthop_vrfid
== VRF_UNKNOWN
)
7343 : (int)nexthop_vrfid
));
7348 if (json_nexthop_global
|| json_nexthop_ll
) {
7349 json_nexthops
= json_object_new_array();
7351 if (json_nexthop_global
)
7352 json_object_array_add(json_nexthops
,
7353 json_nexthop_global
);
7355 if (json_nexthop_ll
)
7356 json_object_array_add(json_nexthops
,
7359 json_object_object_add(json_path
, "nexthops",
7363 json_object_array_add(json_paths
, json_path
);
7367 /* prints an additional line, indented, with VNC info, if
7369 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7370 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7375 /* called from terminal list command */
7376 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7377 safi_t safi
, bool use_json
, json_object
*json_ar
)
7379 json_object
*json_status
= NULL
;
7380 json_object
*json_net
= NULL
;
7383 /* Route status display. */
7385 json_status
= json_object_new_object();
7386 json_net
= json_object_new_object();
7393 /* print prefix and mask */
7395 json_object_string_add(
7396 json_net
, "addrPrefix",
7397 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
7398 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
7399 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7400 json_object_string_add(json_net
, "network", buf2
);
7402 route_vty_out_route(p
, vty
, NULL
);
7404 /* Print attribute */
7407 if (p
->family
== AF_INET
7408 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7409 || safi
== SAFI_EVPN
7410 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7411 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7412 || safi
== SAFI_EVPN
)
7413 json_object_string_add(
7414 json_net
, "nextHop",
7416 attr
->mp_nexthop_global_in
));
7418 json_object_string_add(
7419 json_net
, "nextHop",
7420 inet_ntoa(attr
->nexthop
));
7421 } else if (p
->family
== AF_INET6
7422 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7425 json_object_string_add(
7426 json_net
, "nextHopGlobal",
7428 &attr
->mp_nexthop_global
, buf
,
7433 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7434 json_object_int_add(json_net
, "metric",
7437 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7440 * Adding "locPrf" field to match with
7441 * corresponding CLI. "localPref" will be
7442 * deprecated in future.
7444 json_object_int_add(json_net
, "localPref",
7446 json_object_int_add(json_net
, "locPrf",
7450 json_object_int_add(json_net
, "weight", attr
->weight
);
7456 * Adding "path" field to match with
7457 * corresponding CLI. "localPref" will be
7458 * deprecated in future.
7460 json_object_string_add(json_net
, "asPath",
7462 json_object_string_add(json_net
, "path",
7467 json_object_string_add(json_net
, "bgpOriginCode",
7468 bgp_origin_str
[attr
->origin
]);
7470 if (p
->family
== AF_INET
7471 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7472 || safi
== SAFI_EVPN
7473 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7474 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7475 || safi
== SAFI_EVPN
)
7476 vty_out(vty
, "%-16s",
7478 attr
->mp_nexthop_global_in
));
7480 vty_out(vty
, "%-16s",
7481 inet_ntoa(attr
->nexthop
));
7482 } else if (p
->family
== AF_INET6
7483 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7490 &attr
->mp_nexthop_global
, buf
,
7494 vty_out(vty
, "\n%*s", 36, " ");
7496 vty_out(vty
, "%*s", len
, " ");
7499 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7500 vty_out(vty
, "%10u", attr
->med
);
7504 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7505 vty_out(vty
, "%7u", attr
->local_pref
);
7509 vty_out(vty
, "%7u ", attr
->weight
);
7513 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7516 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7520 json_object_boolean_true_add(json_status
, "*");
7521 json_object_boolean_true_add(json_status
, ">");
7522 json_object_object_add(json_net
, "appliedStatusSymbols",
7524 char buf_cut
[BUFSIZ
];
7525 json_object_object_add(
7527 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7533 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7534 struct bgp_path_info
*path
, int display
, safi_t safi
,
7537 json_object
*json_out
= NULL
;
7539 mpls_label_t label
= MPLS_INVALID_LABEL
;
7545 json_out
= json_object_new_object();
7547 /* short status lead text */
7548 route_vty_short_status_out(vty
, path
, json_out
);
7550 /* print prefix and mask */
7553 route_vty_out_route(p
, vty
, NULL
);
7555 vty_out(vty
, "%*s", 17, " ");
7558 /* Print attribute */
7561 if (((p
->family
== AF_INET
)
7562 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7563 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7564 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7565 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7566 || safi
== SAFI_EVPN
) {
7568 json_object_string_add(
7569 json_out
, "mpNexthopGlobalIn",
7571 attr
->mp_nexthop_global_in
));
7573 vty_out(vty
, "%-16s",
7575 attr
->mp_nexthop_global_in
));
7578 json_object_string_add(
7579 json_out
, "nexthop",
7580 inet_ntoa(attr
->nexthop
));
7582 vty_out(vty
, "%-16s",
7583 inet_ntoa(attr
->nexthop
));
7585 } else if (((p
->family
== AF_INET6
)
7586 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7587 || (safi
== SAFI_EVPN
7588 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7589 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7591 if (attr
->mp_nexthop_len
7592 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7594 json_object_string_add(
7595 json_out
, "mpNexthopGlobalIn",
7598 &attr
->mp_nexthop_global
,
7599 buf_a
, sizeof(buf_a
)));
7604 &attr
->mp_nexthop_global
,
7605 buf_a
, sizeof(buf_a
)));
7606 } else if (attr
->mp_nexthop_len
7607 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7608 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
7609 &attr
->mp_nexthop_global
,
7610 &attr
->mp_nexthop_local
);
7612 json_object_string_add(
7614 "mpNexthopGlobalLocal", buf_a
);
7616 vty_out(vty
, "%s", buf_a
);
7621 label
= decode_label(&path
->extra
->label
[0]);
7623 if (bgp_is_valid_label(&label
)) {
7625 json_object_int_add(json_out
, "notag", label
);
7626 json_object_array_add(json
, json_out
);
7628 vty_out(vty
, "notag/%d", label
);
7634 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7635 struct bgp_path_info
*path
, int display
,
7636 json_object
*json_paths
)
7639 char buf
[BUFSIZ
] = {0};
7640 json_object
*json_path
= NULL
;
7641 json_object
*json_nexthop
= NULL
;
7642 json_object
*json_overlay
= NULL
;
7648 json_path
= json_object_new_object();
7649 json_overlay
= json_object_new_object();
7650 json_nexthop
= json_object_new_object();
7653 /* short status lead text */
7654 route_vty_short_status_out(vty
, path
, json_path
);
7656 /* print prefix and mask */
7658 route_vty_out_route(p
, vty
, json_path
);
7660 vty_out(vty
, "%*s", 17, " ");
7662 /* Print attribute */
7666 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7670 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
7672 vty_out(vty
, "%-16s", buf
);
7674 json_object_string_add(json_nexthop
, "ip", buf
);
7676 json_object_string_add(json_nexthop
, "afi",
7679 json_object_object_add(json_path
, "nexthop",
7684 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
7685 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
7687 vty_out(vty
, "%s(%s)", buf
, buf1
);
7689 json_object_string_add(json_nexthop
,
7692 json_object_string_add(json_nexthop
,
7693 "ipv6LinkLocal", buf1
);
7695 json_object_string_add(json_nexthop
, "afi",
7698 json_object_object_add(json_path
, "nexthop",
7706 json_object_string_add(json_nexthop
, "Error",
7707 "Unsupported address-family");
7711 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7714 vty_out(vty
, "%s", str
);
7716 json_object_string_add(json_overlay
, "esi", str
);
7718 XFREE(MTYPE_TMP
, str
);
7720 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7721 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
),
7723 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7724 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
),
7729 vty_out(vty
, "/%s", buf
);
7731 json_object_string_add(json_overlay
, "gw", buf
);
7733 if (attr
->ecommunity
) {
7735 struct ecommunity_val
*routermac
= ecommunity_lookup(
7736 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7737 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7739 mac
= ecom_mac2str((char *)routermac
->val
);
7742 vty_out(vty
, "/%s", (char *)mac
);
7744 json_object_string_add(json_overlay
,
7747 XFREE(MTYPE_TMP
, mac
);
7754 json_object_object_add(json_path
, "overlay",
7757 json_object_array_add(json_paths
, json_path
);
7762 /* dampening route */
7763 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7764 struct bgp_path_info
*path
, int display
,
7765 safi_t safi
, bool use_json
, json_object
*json
)
7769 char timebuf
[BGP_UPTIME_LEN
];
7771 /* short status lead text */
7772 route_vty_short_status_out(vty
, path
, json
);
7774 /* print prefix and mask */
7777 route_vty_out_route(p
, vty
, NULL
);
7779 vty_out(vty
, "%*s", 17, " ");
7782 len
= vty_out(vty
, "%s", path
->peer
->host
);
7786 vty_out(vty
, "\n%*s", 34, " ");
7789 json_object_int_add(json
, "peerHost", len
);
7791 vty_out(vty
, "%*s", len
, " ");
7795 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7799 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7800 BGP_UPTIME_LEN
, use_json
,
7803 /* Print attribute */
7809 json_object_string_add(json
, "asPath",
7812 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7817 json_object_string_add(json
, "origin",
7818 bgp_origin_str
[attr
->origin
]);
7820 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7827 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7828 struct bgp_path_info
*path
, int display
,
7829 safi_t safi
, bool use_json
, json_object
*json
)
7832 struct bgp_damp_info
*bdi
;
7833 char timebuf
[BGP_UPTIME_LEN
];
7839 bdi
= path
->extra
->damp_info
;
7841 /* short status lead text */
7842 route_vty_short_status_out(vty
, path
, json
);
7844 /* print prefix and mask */
7847 route_vty_out_route(p
, vty
, NULL
);
7849 vty_out(vty
, "%*s", 17, " ");
7852 len
= vty_out(vty
, "%s", path
->peer
->host
);
7856 vty_out(vty
, "\n%*s", 33, " ");
7859 json_object_int_add(json
, "peerHost", len
);
7861 vty_out(vty
, "%*s", len
, " ");
7864 len
= vty_out(vty
, "%d", bdi
->flap
);
7871 json_object_int_add(json
, "bdiFlap", len
);
7873 vty_out(vty
, "%*s", len
, " ");
7877 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7880 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7881 BGP_UPTIME_LEN
, 0, NULL
));
7883 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7884 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7886 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7887 BGP_UPTIME_LEN
, use_json
, json
);
7890 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7895 vty_out(vty
, "%*s ", 8, " ");
7898 /* Print attribute */
7904 json_object_string_add(json
, "asPath",
7907 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7912 json_object_string_add(json
, "origin",
7913 bgp_origin_str
[attr
->origin
]);
7915 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7921 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7922 int *first
, const char *header
,
7923 json_object
*json_adv_to
)
7925 char buf1
[INET6_ADDRSTRLEN
];
7926 json_object
*json_peer
= NULL
;
7929 /* 'advertised-to' is a dictionary of peers we have advertised
7931 * prefix too. The key is the peer's IP or swpX, the value is
7933 * hostname if we know it and "" if not.
7935 json_peer
= json_object_new_object();
7938 json_object_string_add(json_peer
, "hostname",
7942 json_object_object_add(json_adv_to
, peer
->conf_if
,
7945 json_object_object_add(
7947 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7951 vty_out(vty
, "%s", header
);
7956 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7958 vty_out(vty
, " %s(%s)", peer
->hostname
,
7961 vty_out(vty
, " %s(%s)", peer
->hostname
,
7962 sockunion2str(&peer
->su
, buf1
,
7966 vty_out(vty
, " %s", peer
->conf_if
);
7969 sockunion2str(&peer
->su
, buf1
,
7975 static void route_vty_out_tx_ids(struct vty
*vty
,
7976 struct bgp_addpath_info_data
*d
)
7980 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7981 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7982 d
->addpath_tx_id
[i
],
7983 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7987 static const char *bgp_path_selection_reason2str(
7988 enum bgp_path_selection_reason reason
)
7991 case bgp_path_selection_none
:
7992 return "Nothing to Select";
7994 case bgp_path_selection_first
:
7995 return "First path received";
7997 case bgp_path_selection_evpn_sticky_mac
:
7998 return "EVPN Sticky Mac";
8000 case bgp_path_selection_evpn_seq
:
8001 return "EVPN sequence number";
8003 case bgp_path_selection_evpn_lower_ip
:
8004 return "EVPN lower IP";
8006 case bgp_path_selection_weight
:
8009 case bgp_path_selection_local_pref
:
8010 return "Local Pref";
8012 case bgp_path_selection_local_route
:
8013 return "Local Route";
8015 case bgp_path_selection_confed_as_path
:
8016 return "Confederation based AS Path";
8018 case bgp_path_selection_as_path
:
8021 case bgp_path_selection_origin
:
8024 case bgp_path_selection_med
:
8027 case bgp_path_selection_peer
:
8030 case bgp_path_selection_confed
:
8031 return "Confed Peer Type";
8033 case bgp_path_selection_igp_metric
:
8034 return "IGP Metric";
8036 case bgp_path_selection_older
:
8037 return "Older Path";
8039 case bgp_path_selection_router_id
:
8042 case bgp_path_selection_cluster_length
:
8043 return "Cluser length";
8045 case bgp_path_selection_stale
:
8046 return "Path Staleness";
8048 case bgp_path_selection_local_configured
:
8049 return "Locally configured route";
8051 case bgp_path_selection_neighbor_ip
:
8052 return "Neighbor IP";
8054 case bgp_path_selection_default
:
8055 return "Nothing left to compare";
8058 return "Invalid (internal error)";
8061 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8062 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8063 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8065 char buf
[INET6_ADDRSTRLEN
];
8067 char buf2
[EVPN_ROUTE_STRLEN
];
8069 int sockunion_vty_out(struct vty
*, union sockunion
*);
8071 json_object
*json_bestpath
= NULL
;
8072 json_object
*json_cluster_list
= NULL
;
8073 json_object
*json_cluster_list_list
= NULL
;
8074 json_object
*json_ext_community
= NULL
;
8075 json_object
*json_last_update
= NULL
;
8076 json_object
*json_pmsi
= NULL
;
8077 json_object
*json_nexthop_global
= NULL
;
8078 json_object
*json_nexthop_ll
= NULL
;
8079 json_object
*json_nexthops
= NULL
;
8080 json_object
*json_path
= NULL
;
8081 json_object
*json_peer
= NULL
;
8082 json_object
*json_string
= NULL
;
8083 json_object
*json_adv_to
= NULL
;
8085 struct listnode
*node
, *nnode
;
8087 int addpath_capable
;
8089 unsigned int first_as
;
8091 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8093 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
8096 json_path
= json_object_new_object();
8097 json_peer
= json_object_new_object();
8098 json_nexthop_global
= json_object_new_object();
8101 if (!json_paths
&& safi
== SAFI_EVPN
) {
8104 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8105 buf2
, sizeof(buf2
));
8106 vty_out(vty
, " Route %s", buf2
);
8108 if (path
->extra
&& path
->extra
->num_labels
) {
8109 bgp_evpn_label2str(path
->extra
->label
,
8110 path
->extra
->num_labels
, tag_buf
,
8112 vty_out(vty
, " VNI %s", tag_buf
);
8115 if (path
->extra
&& path
->extra
->parent
) {
8116 struct bgp_path_info
*parent_ri
;
8117 struct bgp_node
*rn
, *prn
;
8119 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8120 rn
= parent_ri
->net
;
8121 if (rn
&& rn
->prn
) {
8123 vty_out(vty
, " Imported from %s:%s\n",
8125 (struct prefix_rd
*)&prn
->p
,
8126 buf1
, sizeof(buf1
)),
8135 /* Line1 display AS-path, Aggregator */
8138 if (!attr
->aspath
->json
)
8139 aspath_str_update(attr
->aspath
, true);
8140 json_object_lock(attr
->aspath
->json
);
8141 json_object_object_add(json_path
, "aspath",
8142 attr
->aspath
->json
);
8144 if (attr
->aspath
->segments
)
8145 aspath_print_vty(vty
, " %s",
8148 vty_out(vty
, " Local");
8152 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8154 json_object_boolean_true_add(json_path
,
8157 vty_out(vty
, ", (removed)");
8160 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8162 json_object_boolean_true_add(json_path
,
8165 vty_out(vty
, ", (stale)");
8168 if (CHECK_FLAG(attr
->flag
,
8169 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8171 json_object_int_add(json_path
, "aggregatorAs",
8172 attr
->aggregator_as
);
8173 json_object_string_add(
8174 json_path
, "aggregatorId",
8175 inet_ntoa(attr
->aggregator_addr
));
8177 vty_out(vty
, ", (aggregated by %u %s)",
8178 attr
->aggregator_as
,
8179 inet_ntoa(attr
->aggregator_addr
));
8183 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8184 PEER_FLAG_REFLECTOR_CLIENT
)) {
8186 json_object_boolean_true_add(
8187 json_path
, "rxedFromRrClient");
8189 vty_out(vty
, ", (Received from a RR-client)");
8192 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8193 PEER_FLAG_RSERVER_CLIENT
)) {
8195 json_object_boolean_true_add(
8196 json_path
, "rxedFromRsClient");
8198 vty_out(vty
, ", (Received from a RS-client)");
8201 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8203 json_object_boolean_true_add(
8204 json_path
, "dampeningHistoryEntry");
8206 vty_out(vty
, ", (history entry)");
8207 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8209 json_object_boolean_true_add(
8210 json_path
, "dampeningSuppressed");
8212 vty_out(vty
, ", (suppressed due to dampening)");
8218 /* Line2 display Next-hop, Neighbor, Router-id */
8219 /* Display the nexthop */
8220 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8221 || bn
->p
.family
== AF_EVPN
)
8222 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8223 || safi
== SAFI_EVPN
8224 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8225 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8226 || safi
== SAFI_EVPN
) {
8228 json_object_string_add(
8229 json_nexthop_global
,
8230 nexthop_fqdn
? "fqdn" : "ip",
8234 attr
->mp_nexthop_global_in
));
8240 attr
->mp_nexthop_global_in
));
8243 json_object_string_add(
8244 json_nexthop_global
,
8245 nexthop_fqdn
? "fqdn" : "ip",
8259 json_object_string_add(json_nexthop_global
,
8263 json_object_string_add(
8264 json_nexthop_global
,
8265 nexthop_fqdn
? "fqdn" : "ip",
8270 &attr
->mp_nexthop_global
,
8273 json_object_string_add(json_nexthop_global
,
8275 json_object_string_add(json_nexthop_global
,
8283 &attr
->mp_nexthop_global
,
8289 /* Display the IGP cost or 'inaccessible' */
8290 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8292 json_object_boolean_false_add(
8293 json_nexthop_global
, "accessible");
8295 vty_out(vty
, " (inaccessible)");
8297 if (path
->extra
&& path
->extra
->igpmetric
) {
8299 json_object_int_add(
8300 json_nexthop_global
, "metric",
8301 path
->extra
->igpmetric
);
8303 vty_out(vty
, " (metric %u)",
8304 path
->extra
->igpmetric
);
8307 /* IGP cost is 0, display this only for json */
8310 json_object_int_add(json_nexthop_global
,
8315 json_object_boolean_true_add(
8316 json_nexthop_global
, "accessible");
8319 /* Display peer "from" output */
8320 /* This path was originated locally */
8321 if (path
->peer
== bgp
->peer_self
) {
8323 if (safi
== SAFI_EVPN
8324 || (bn
->p
.family
== AF_INET
8325 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8327 json_object_string_add(
8328 json_peer
, "peerId", "0.0.0.0");
8330 vty_out(vty
, " from 0.0.0.0 ");
8333 json_object_string_add(json_peer
,
8336 vty_out(vty
, " from :: ");
8340 json_object_string_add(
8341 json_peer
, "routerId",
8342 inet_ntoa(bgp
->router_id
));
8344 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8347 /* We RXed this path from one of our peers */
8351 json_object_string_add(
8352 json_peer
, "peerId",
8353 sockunion2str(&path
->peer
->su
, buf
,
8355 json_object_string_add(
8356 json_peer
, "routerId",
8358 &path
->peer
->remote_id
, buf1
,
8361 if (path
->peer
->hostname
)
8362 json_object_string_add(
8363 json_peer
, "hostname",
8364 path
->peer
->hostname
);
8366 if (path
->peer
->domainname
)
8367 json_object_string_add(
8368 json_peer
, "domainname",
8369 path
->peer
->domainname
);
8371 if (path
->peer
->conf_if
)
8372 json_object_string_add(
8373 json_peer
, "interface",
8374 path
->peer
->conf_if
);
8376 if (path
->peer
->conf_if
) {
8377 if (path
->peer
->hostname
8380 BGP_FLAG_SHOW_HOSTNAME
))
8381 vty_out(vty
, " from %s(%s)",
8382 path
->peer
->hostname
,
8383 path
->peer
->conf_if
);
8385 vty_out(vty
, " from %s",
8386 path
->peer
->conf_if
);
8388 if (path
->peer
->hostname
8391 BGP_FLAG_SHOW_HOSTNAME
))
8392 vty_out(vty
, " from %s(%s)",
8393 path
->peer
->hostname
,
8396 vty_out(vty
, " from %s",
8404 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8405 vty_out(vty
, " (%s)",
8406 inet_ntoa(attr
->originator_id
));
8408 vty_out(vty
, " (%s)",
8411 &path
->peer
->remote_id
,
8412 buf1
, sizeof(buf1
)));
8417 * Note when vrfid of nexthop is different from that of prefix
8419 if (path
->extra
&& path
->extra
->bgp_orig
) {
8420 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8425 if (path
->extra
->bgp_orig
->inst_type
8426 == BGP_INSTANCE_TYPE_DEFAULT
)
8428 vn
= VRF_DEFAULT_NAME
;
8430 vn
= path
->extra
->bgp_orig
->name
;
8432 json_object_string_add(json_path
, "nhVrfName",
8435 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8436 json_object_int_add(json_path
,
8439 json_object_int_add(json_path
,
8440 "nhVrfId", (int)nexthop_vrfid
);
8443 if (nexthop_vrfid
== VRF_UNKNOWN
)
8444 vty_out(vty
, " vrf ?");
8446 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8452 json_object_boolean_true_add(json_path
,
8453 "announceNexthopSelf");
8455 vty_out(vty
, " announce-nh-self");
8462 /* display the link-local nexthop */
8463 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8465 json_nexthop_ll
= json_object_new_object();
8466 json_object_string_add(
8468 nexthop_fqdn
? "fqdn" : "ip",
8473 &attr
->mp_nexthop_local
,
8476 json_object_string_add(json_nexthop_ll
, "afi",
8478 json_object_string_add(json_nexthop_ll
, "scope",
8481 json_object_boolean_true_add(json_nexthop_ll
,
8484 if (!attr
->mp_nexthop_prefer_global
)
8485 json_object_boolean_true_add(
8486 json_nexthop_ll
, "used");
8488 json_object_boolean_true_add(
8489 json_nexthop_global
, "used");
8491 vty_out(vty
, " (%s) %s\n",
8493 &attr
->mp_nexthop_local
, buf
,
8495 attr
->mp_nexthop_prefer_global
8500 /* If we do not have a link-local nexthop then we must flag the
8504 json_object_boolean_true_add(
8505 json_nexthop_global
, "used");
8508 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8509 * Int/Ext/Local, Atomic, best */
8511 json_object_string_add(
8512 json_path
, "origin",
8513 bgp_origin_long_str
[attr
->origin
]);
8515 vty_out(vty
, " Origin %s",
8516 bgp_origin_long_str
[attr
->origin
]);
8518 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8522 * Adding "metric" field to match with
8523 * corresponding CLI. "med" will be
8524 * deprecated in future.
8526 json_object_int_add(json_path
, "med",
8528 json_object_int_add(json_path
, "metric",
8531 vty_out(vty
, ", metric %u", attr
->med
);
8534 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8536 json_object_int_add(json_path
, "localpref",
8539 vty_out(vty
, ", localpref %u",
8543 if (attr
->weight
!= 0) {
8545 json_object_int_add(json_path
, "weight",
8548 vty_out(vty
, ", weight %u", attr
->weight
);
8551 if (attr
->tag
!= 0) {
8553 json_object_int_add(json_path
, "tag",
8556 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8560 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8562 json_object_boolean_false_add(json_path
,
8565 vty_out(vty
, ", invalid");
8566 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8568 json_object_boolean_true_add(json_path
,
8571 vty_out(vty
, ", valid");
8574 if (path
->peer
!= bgp
->peer_self
) {
8575 if (path
->peer
->as
== path
->peer
->local_as
) {
8576 if (CHECK_FLAG(bgp
->config
,
8577 BGP_CONFIG_CONFEDERATION
)) {
8579 json_object_string_add(
8584 ", confed-internal");
8587 json_object_string_add(
8591 vty_out(vty
, ", internal");
8594 if (bgp_confederation_peers_check(
8595 bgp
, path
->peer
->as
)) {
8597 json_object_string_add(
8602 ", confed-external");
8605 json_object_string_add(
8609 vty_out(vty
, ", external");
8612 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8614 json_object_boolean_true_add(json_path
,
8616 json_object_boolean_true_add(json_path
,
8619 vty_out(vty
, ", aggregated, local");
8621 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8623 json_object_boolean_true_add(json_path
,
8626 vty_out(vty
, ", sourced");
8629 json_object_boolean_true_add(json_path
,
8631 json_object_boolean_true_add(json_path
,
8634 vty_out(vty
, ", sourced, local");
8638 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8640 json_object_boolean_true_add(json_path
,
8643 vty_out(vty
, ", atomic-aggregate");
8646 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8647 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8648 && bgp_path_info_mpath_count(path
))) {
8650 json_object_boolean_true_add(json_path
,
8653 vty_out(vty
, ", multipath");
8656 // Mark the bestpath(s)
8657 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8658 first_as
= aspath_get_first_as(attr
->aspath
);
8663 json_object_new_object();
8664 json_object_int_add(json_bestpath
,
8665 "bestpathFromAs", first_as
);
8668 vty_out(vty
, ", bestpath-from-AS %u",
8672 ", bestpath-from-AS Local");
8676 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8680 json_object_new_object();
8681 json_object_boolean_true_add(json_bestpath
,
8683 json_object_string_add(json_bestpath
,
8685 bgp_path_selection_reason2str(bn
->reason
));
8687 vty_out(vty
, ", best");
8688 vty_out(vty
, " (%s)",
8689 bgp_path_selection_reason2str(bn
->reason
));
8694 json_object_object_add(json_path
, "bestpath",
8700 /* Line 4 display Community */
8701 if (attr
->community
) {
8703 if (!attr
->community
->json
)
8704 community_str(attr
->community
, true);
8705 json_object_lock(attr
->community
->json
);
8706 json_object_object_add(json_path
, "community",
8707 attr
->community
->json
);
8709 vty_out(vty
, " Community: %s\n",
8710 attr
->community
->str
);
8714 /* Line 5 display Extended-community */
8715 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8717 json_ext_community
= json_object_new_object();
8718 json_object_string_add(json_ext_community
,
8720 attr
->ecommunity
->str
);
8721 json_object_object_add(json_path
,
8722 "extendedCommunity",
8723 json_ext_community
);
8725 vty_out(vty
, " Extended Community: %s\n",
8726 attr
->ecommunity
->str
);
8730 /* Line 6 display Large community */
8731 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8733 if (!attr
->lcommunity
->json
)
8734 lcommunity_str(attr
->lcommunity
, true);
8735 json_object_lock(attr
->lcommunity
->json
);
8736 json_object_object_add(json_path
,
8738 attr
->lcommunity
->json
);
8740 vty_out(vty
, " Large Community: %s\n",
8741 attr
->lcommunity
->str
);
8745 /* Line 7 display Originator, Cluster-id */
8746 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8747 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8749 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8751 json_object_string_add(
8752 json_path
, "originatorId",
8753 inet_ntoa(attr
->originator_id
));
8755 vty_out(vty
, " Originator: %s",
8756 inet_ntoa(attr
->originator_id
));
8759 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8764 json_object_new_object();
8765 json_cluster_list_list
=
8766 json_object_new_array();
8769 i
< attr
->cluster
->length
/ 4;
8771 json_string
= json_object_new_string(
8775 json_object_array_add(
8776 json_cluster_list_list
,
8780 /* struct cluster_list does not have
8782 * aspath and community do. Add this
8785 json_object_string_add(json_cluster_list,
8786 "string", attr->cluster->str);
8788 json_object_object_add(
8789 json_cluster_list
, "list",
8790 json_cluster_list_list
);
8791 json_object_object_add(
8792 json_path
, "clusterList",
8795 vty_out(vty
, ", Cluster list: ");
8798 i
< attr
->cluster
->length
/ 4;
8812 if (path
->extra
&& path
->extra
->damp_info
)
8813 bgp_damp_info_vty(vty
, path
, json_path
);
8816 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8817 && safi
!= SAFI_EVPN
) {
8818 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8821 json_object_int_add(json_path
, "remoteLabel",
8824 vty_out(vty
, " Remote label: %d\n", label
);
8828 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8830 json_object_int_add(json_path
, "labelIndex",
8833 vty_out(vty
, " Label Index: %d\n",
8837 /* Line 8 display Addpath IDs */
8838 if (path
->addpath_rx_id
8839 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8841 json_object_int_add(json_path
, "addpathRxId",
8842 path
->addpath_rx_id
);
8844 /* Keep backwards compatibility with the old API
8845 * by putting TX All's ID in the old field
8847 json_object_int_add(
8848 json_path
, "addpathTxId",
8849 path
->tx_addpath
.addpath_tx_id
8852 /* ... but create a specific field for each
8855 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8856 json_object_int_add(
8858 bgp_addpath_names(i
)
8864 vty_out(vty
, " AddPath ID: RX %u, ",
8865 path
->addpath_rx_id
);
8867 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8871 /* If we used addpath to TX a non-bestpath we need to display
8872 * "Advertised to" on a path-by-path basis
8874 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8877 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8879 bgp_addpath_encode_tx(peer
, afi
, safi
);
8880 has_adj
= bgp_adj_out_lookup(
8882 bgp_addpath_id_for_peer(
8884 &path
->tx_addpath
));
8886 if ((addpath_capable
&& has_adj
)
8887 || (!addpath_capable
&& has_adj
8888 && CHECK_FLAG(path
->flags
,
8889 BGP_PATH_SELECTED
))) {
8890 if (json_path
&& !json_adv_to
)
8892 json_object_new_object();
8894 route_vty_out_advertised_to(
8903 json_object_object_add(json_path
,
8914 /* Line 9 display Uptime */
8915 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8917 json_last_update
= json_object_new_object();
8918 json_object_int_add(json_last_update
, "epoch", tbuf
);
8919 json_object_string_add(json_last_update
, "string",
8921 json_object_object_add(json_path
, "lastUpdate",
8924 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8926 /* Line 10 display PMSI tunnel attribute, if present */
8927 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8928 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8929 attr
->pmsi_tnl_type
,
8930 PMSI_TNLTYPE_STR_DEFAULT
);
8933 json_pmsi
= json_object_new_object();
8934 json_object_string_add(json_pmsi
,
8936 json_object_int_add(json_pmsi
,
8938 label2vni(&attr
->label
));
8939 json_object_object_add(json_path
, "pmsi",
8943 " PMSI Tunnel Type: %s, label: %d\n",
8944 str
, label2vni(&attr
->label
));
8949 /* We've constructed the json object for this path, add it to the json
8953 if (json_nexthop_global
|| json_nexthop_ll
) {
8954 json_nexthops
= json_object_new_array();
8956 if (json_nexthop_global
)
8957 json_object_array_add(json_nexthops
,
8958 json_nexthop_global
);
8960 if (json_nexthop_ll
)
8961 json_object_array_add(json_nexthops
,
8964 json_object_object_add(json_path
, "nexthops",
8968 json_object_object_add(json_path
, "peer", json_peer
);
8969 json_object_array_add(json_paths
, json_path
);
8974 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8975 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8976 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8978 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8979 const char *prefix_list_str
, afi_t afi
,
8980 safi_t safi
, enum bgp_show_type type
);
8981 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8982 const char *filter
, afi_t afi
, safi_t safi
,
8983 enum bgp_show_type type
);
8984 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8985 const char *rmap_str
, afi_t afi
, safi_t safi
,
8986 enum bgp_show_type type
);
8987 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8988 const char *com
, int exact
, afi_t afi
,
8990 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8991 const char *prefix
, afi_t afi
, safi_t safi
,
8992 enum bgp_show_type type
);
8993 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8994 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8995 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8996 const char *comstr
, int exact
, afi_t afi
,
8997 safi_t safi
, bool use_json
);
9000 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9001 struct bgp_table
*table
, enum bgp_show_type type
,
9002 void *output_arg
, bool use_json
, char *rd
,
9003 int is_last
, unsigned long *output_cum
,
9004 unsigned long *total_cum
,
9005 unsigned long *json_header_depth
)
9007 struct bgp_path_info
*pi
;
9008 struct bgp_node
*rn
;
9011 unsigned long output_count
= 0;
9012 unsigned long total_count
= 0;
9015 json_object
*json_paths
= NULL
;
9018 if (output_cum
&& *output_cum
!= 0)
9021 if (use_json
&& !*json_header_depth
) {
9023 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9024 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9025 " \"localAS\": %u,\n \"routes\": { ",
9026 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9027 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9030 table
->version
, inet_ntoa(bgp
->router_id
),
9031 bgp
->default_local_pref
, bgp
->as
);
9032 *json_header_depth
= 2;
9034 vty_out(vty
, " \"routeDistinguishers\" : {");
9035 ++*json_header_depth
;
9039 if (use_json
&& rd
) {
9040 vty_out(vty
, " \"%s\" : { ", rd
);
9043 /* Start processing of routes. */
9044 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9045 pi
= bgp_node_get_bgp_path_info(rn
);
9051 json_paths
= json_object_new_array();
9055 for (; pi
; pi
= pi
->next
) {
9057 if (type
== bgp_show_type_flap_statistics
9058 || type
== bgp_show_type_flap_neighbor
9059 || type
== bgp_show_type_dampend_paths
9060 || type
== bgp_show_type_damp_neighbor
) {
9061 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9064 if (type
== bgp_show_type_regexp
) {
9065 regex_t
*regex
= output_arg
;
9067 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9071 if (type
== bgp_show_type_prefix_list
) {
9072 struct prefix_list
*plist
= output_arg
;
9074 if (prefix_list_apply(plist
, &rn
->p
)
9078 if (type
== bgp_show_type_filter_list
) {
9079 struct as_list
*as_list
= output_arg
;
9081 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9082 != AS_FILTER_PERMIT
)
9085 if (type
== bgp_show_type_route_map
) {
9086 struct route_map
*rmap
= output_arg
;
9087 struct bgp_path_info path
;
9088 struct attr dummy_attr
;
9091 bgp_attr_dup(&dummy_attr
, pi
->attr
);
9093 path
.peer
= pi
->peer
;
9094 path
.attr
= &dummy_attr
;
9096 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9098 if (ret
== RMAP_DENYMATCH
)
9101 if (type
== bgp_show_type_neighbor
9102 || type
== bgp_show_type_flap_neighbor
9103 || type
== bgp_show_type_damp_neighbor
) {
9104 union sockunion
*su
= output_arg
;
9106 if (pi
->peer
== NULL
9107 || pi
->peer
->su_remote
== NULL
9108 || !sockunion_same(pi
->peer
->su_remote
, su
))
9111 if (type
== bgp_show_type_cidr_only
) {
9112 uint32_t destination
;
9114 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9115 if (IN_CLASSC(destination
)
9116 && rn
->p
.prefixlen
== 24)
9118 if (IN_CLASSB(destination
)
9119 && rn
->p
.prefixlen
== 16)
9121 if (IN_CLASSA(destination
)
9122 && rn
->p
.prefixlen
== 8)
9125 if (type
== bgp_show_type_prefix_longer
) {
9127 if (!prefix_match(p
, &rn
->p
))
9130 if (type
== bgp_show_type_community_all
) {
9131 if (!pi
->attr
->community
)
9134 if (type
== bgp_show_type_community
) {
9135 struct community
*com
= output_arg
;
9137 if (!pi
->attr
->community
9138 || !community_match(pi
->attr
->community
,
9142 if (type
== bgp_show_type_community_exact
) {
9143 struct community
*com
= output_arg
;
9145 if (!pi
->attr
->community
9146 || !community_cmp(pi
->attr
->community
, com
))
9149 if (type
== bgp_show_type_community_list
) {
9150 struct community_list
*list
= output_arg
;
9152 if (!community_list_match(pi
->attr
->community
,
9156 if (type
== bgp_show_type_community_list_exact
) {
9157 struct community_list
*list
= output_arg
;
9159 if (!community_list_exact_match(
9160 pi
->attr
->community
, list
))
9163 if (type
== bgp_show_type_lcommunity
) {
9164 struct lcommunity
*lcom
= output_arg
;
9166 if (!pi
->attr
->lcommunity
9167 || !lcommunity_match(pi
->attr
->lcommunity
,
9171 if (type
== bgp_show_type_lcommunity_list
) {
9172 struct community_list
*list
= output_arg
;
9174 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9178 if (type
== bgp_show_type_lcommunity_all
) {
9179 if (!pi
->attr
->lcommunity
)
9182 if (type
== bgp_show_type_dampend_paths
9183 || type
== bgp_show_type_damp_neighbor
) {
9184 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9185 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9189 if (!use_json
&& header
) {
9190 vty_out(vty
, "BGP table version is %" PRIu64
9191 ", local router ID is %s, vrf id ",
9193 inet_ntoa(bgp
->router_id
));
9194 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9195 vty_out(vty
, "%s", VRFID_NONE_STR
);
9197 vty_out(vty
, "%u", bgp
->vrf_id
);
9199 vty_out(vty
, "Default local pref %u, ",
9200 bgp
->default_local_pref
);
9201 vty_out(vty
, "local AS %u\n", bgp
->as
);
9202 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9203 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9204 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9205 if (type
== bgp_show_type_dampend_paths
9206 || type
== bgp_show_type_damp_neighbor
)
9207 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9208 else if (type
== bgp_show_type_flap_statistics
9209 || type
== bgp_show_type_flap_neighbor
)
9210 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9212 vty_out(vty
, BGP_SHOW_HEADER
);
9215 if (rd
!= NULL
&& !display
&& !output_count
) {
9218 "Route Distinguisher: %s\n",
9221 if (type
== bgp_show_type_dampend_paths
9222 || type
== bgp_show_type_damp_neighbor
)
9223 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
9224 safi
, use_json
, json_paths
);
9225 else if (type
== bgp_show_type_flap_statistics
9226 || type
== bgp_show_type_flap_neighbor
)
9227 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
9228 safi
, use_json
, json_paths
);
9230 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9242 if (p
->family
== AF_FLOWSPEC
) {
9243 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9245 bgp_fs_nlri_get_string((unsigned char *)
9246 p
->u
.prefix_flowspec
.ptr
,
9247 p
->u
.prefix_flowspec
9250 NLRI_STRING_FORMAT_MIN
,
9253 vty_out(vty
, "\"%s/%d\": ",
9255 p
->u
.prefix_flowspec
.prefixlen
);
9257 vty_out(vty
, ",\"%s/%d\": ",
9259 p
->u
.prefix_flowspec
.prefixlen
);
9261 prefix2str(p
, buf2
, sizeof(buf2
));
9263 vty_out(vty
, "\"%s\": ", buf2
);
9265 vty_out(vty
, ",\"%s\": ", buf2
);
9268 json_object_to_json_string(json_paths
));
9269 json_object_free(json_paths
);
9276 output_count
+= *output_cum
;
9277 *output_cum
= output_count
;
9280 total_count
+= *total_cum
;
9281 *total_cum
= total_count
;
9285 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9289 for (i
= 0; i
< *json_header_depth
; ++i
)
9290 vty_out(vty
, " } ");
9295 /* No route is displayed */
9296 if (output_count
== 0) {
9297 if (type
== bgp_show_type_normal
)
9299 "No BGP prefixes displayed, %ld exist\n",
9303 "\nDisplayed %ld routes and %ld total paths\n",
9304 output_count
, total_count
);
9311 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9312 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9313 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9315 struct bgp_node
*rn
, *next
;
9316 unsigned long output_cum
= 0;
9317 unsigned long total_cum
= 0;
9318 unsigned long json_header_depth
= 0;
9319 struct bgp_table
*itable
;
9322 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9324 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9325 next
= bgp_route_next(rn
);
9326 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9329 itable
= bgp_node_get_bgp_table_info(rn
);
9330 if (itable
!= NULL
) {
9331 struct prefix_rd prd
;
9332 char rd
[RD_ADDRSTRLEN
];
9334 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9335 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9336 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9337 use_json
, rd
, next
== NULL
, &output_cum
,
9338 &total_cum
, &json_header_depth
);
9344 if (output_cum
== 0)
9345 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9349 "\nDisplayed %ld routes and %ld total paths\n",
9350 output_cum
, total_cum
);
9354 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9355 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9357 struct bgp_table
*table
;
9358 unsigned long json_header_depth
= 0;
9361 bgp
= bgp_get_default();
9366 vty_out(vty
, "No BGP process is configured\n");
9368 vty_out(vty
, "{}\n");
9372 table
= bgp
->rib
[afi
][safi
];
9373 /* use MPLS and ENCAP specific shows until they are merged */
9374 if (safi
== SAFI_MPLS_VPN
) {
9375 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9376 output_arg
, use_json
);
9379 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9380 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9381 output_arg
, use_json
,
9384 /* labeled-unicast routes live in the unicast table */
9385 else if (safi
== SAFI_LABELED_UNICAST
)
9386 safi
= SAFI_UNICAST
;
9388 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9389 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9392 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9393 safi_t safi
, bool use_json
)
9395 struct listnode
*node
, *nnode
;
9398 bool route_output
= false;
9401 vty_out(vty
, "{\n");
9403 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9404 route_output
= true;
9407 vty_out(vty
, ",\n");
9411 vty_out(vty
, "\"%s\":",
9412 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9416 vty_out(vty
, "\nInstance %s:\n",
9417 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9421 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9426 vty_out(vty
, "}\n");
9427 else if (!route_output
)
9428 vty_out(vty
, "%% BGP instance not found\n");
9431 /* Header of detailed BGP route information */
9432 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9433 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9434 afi_t afi
, safi_t safi
, json_object
*json
)
9436 struct bgp_path_info
*pi
;
9439 struct listnode
*node
, *nnode
;
9440 char buf1
[RD_ADDRSTRLEN
];
9441 char buf2
[INET6_ADDRSTRLEN
];
9442 char buf3
[EVPN_ROUTE_STRLEN
];
9443 char prefix_str
[BUFSIZ
];
9448 int route_filter_translated_v4
= 0;
9449 int route_filter_v4
= 0;
9450 int route_filter_translated_v6
= 0;
9451 int route_filter_v6
= 0;
9454 int accept_own_nexthop
= 0;
9457 int no_advertise
= 0;
9461 int has_valid_label
= 0;
9462 mpls_label_t label
= 0;
9463 json_object
*json_adv_to
= NULL
;
9466 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9468 if (has_valid_label
)
9469 label
= label_pton(&rn
->local_label
);
9472 if (has_valid_label
)
9473 json_object_int_add(json
, "localLabel", label
);
9475 json_object_string_add(
9477 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9479 if (safi
== SAFI_EVPN
)
9480 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9481 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9484 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9485 buf3
, sizeof(buf3
)));
9487 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9488 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9489 ? prefix_rd2str(prd
, buf1
,
9492 safi
== SAFI_MPLS_VPN
? ":" : "",
9493 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9497 if (has_valid_label
)
9498 vty_out(vty
, "Local label: %d\n", label
);
9499 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9500 vty_out(vty
, "not allocated\n");
9503 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9505 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9507 if (pi
->extra
&& pi
->extra
->suppress
)
9510 if (pi
->attr
->community
== NULL
)
9513 no_advertise
+= community_include(
9514 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9515 no_export
+= community_include(pi
->attr
->community
,
9516 COMMUNITY_NO_EXPORT
);
9517 local_as
+= community_include(pi
->attr
->community
,
9518 COMMUNITY_LOCAL_AS
);
9519 accept_own
+= community_include(pi
->attr
->community
,
9520 COMMUNITY_ACCEPT_OWN
);
9521 route_filter_translated_v4
+= community_include(
9522 pi
->attr
->community
,
9523 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9524 route_filter_translated_v6
+= community_include(
9525 pi
->attr
->community
,
9526 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9527 route_filter_v4
+= community_include(
9528 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9529 route_filter_v6
+= community_include(
9530 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9531 llgr_stale
+= community_include(pi
->attr
->community
,
9532 COMMUNITY_LLGR_STALE
);
9533 no_llgr
+= community_include(pi
->attr
->community
,
9535 accept_own_nexthop
+=
9536 community_include(pi
->attr
->community
,
9537 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9538 blackhole
+= community_include(pi
->attr
->community
,
9539 COMMUNITY_BLACKHOLE
);
9540 no_peer
+= community_include(pi
->attr
->community
,
9546 vty_out(vty
, "Paths: (%d available", count
);
9548 vty_out(vty
, ", best #%d", best
);
9549 if (safi
== SAFI_UNICAST
) {
9550 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9551 vty_out(vty
, ", table %s",
9554 vty_out(vty
, ", vrf %s",
9558 vty_out(vty
, ", no best path");
9562 ", accept own local route exported and imported in different VRF");
9563 else if (route_filter_translated_v4
)
9565 ", mark translated RTs for VPNv4 route filtering");
9566 else if (route_filter_v4
)
9568 ", attach RT as-is for VPNv4 route filtering");
9569 else if (route_filter_translated_v6
)
9571 ", mark translated RTs for VPNv6 route filtering");
9572 else if (route_filter_v6
)
9574 ", attach RT as-is for VPNv6 route filtering");
9575 else if (llgr_stale
)
9577 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9580 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9581 else if (accept_own_nexthop
)
9583 ", accept local nexthop");
9585 vty_out(vty
, ", inform peer to blackhole prefix");
9587 vty_out(vty
, ", not advertised to EBGP peer");
9588 else if (no_advertise
)
9589 vty_out(vty
, ", not advertised to any peer");
9591 vty_out(vty
, ", not advertised outside local AS");
9594 ", inform EBGP peer not to advertise to their EBGP peers");
9598 ", Advertisements suppressed by an aggregate.");
9599 vty_out(vty
, ")\n");
9602 /* If we are not using addpath then we can display Advertised to and
9604 * show what peers we advertised the bestpath to. If we are using
9606 * though then we must display Advertised to on a path-by-path basis. */
9607 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9608 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9609 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9610 if (json
&& !json_adv_to
)
9611 json_adv_to
= json_object_new_object();
9613 route_vty_out_advertised_to(
9615 " Advertised to non peer-group peers:\n ",
9622 json_object_object_add(json
, "advertisedTo",
9627 vty_out(vty
, " Not advertised to any peer");
9633 /* Display specified route of BGP table. */
9634 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9635 struct bgp_table
*rib
, const char *ip_str
,
9636 afi_t afi
, safi_t safi
,
9637 struct prefix_rd
*prd
, int prefix_check
,
9638 enum bgp_path_type pathtype
, bool use_json
)
9643 struct prefix match
;
9644 struct bgp_node
*rn
;
9645 struct bgp_node
*rm
;
9646 struct bgp_path_info
*pi
;
9647 struct bgp_table
*table
;
9648 json_object
*json
= NULL
;
9649 json_object
*json_paths
= NULL
;
9651 /* Check IP address argument. */
9652 ret
= str2prefix(ip_str
, &match
);
9654 vty_out(vty
, "address is malformed\n");
9658 match
.family
= afi2family(afi
);
9661 json
= json_object_new_object();
9662 json_paths
= json_object_new_array();
9665 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9666 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9667 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9669 table
= bgp_node_get_bgp_table_info(rn
);
9675 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9679 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9680 bgp_unlock_node(rm
);
9684 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9687 route_vty_out_detail_header(
9689 (struct prefix_rd
*)&rn
->p
,
9690 AFI_IP
, safi
, json
);
9695 if (pathtype
== BGP_PATH_SHOW_ALL
9696 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9697 && CHECK_FLAG(pi
->flags
,
9699 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9700 && (CHECK_FLAG(pi
->flags
,
9702 || CHECK_FLAG(pi
->flags
,
9703 BGP_PATH_SELECTED
))))
9704 route_vty_out_detail(vty
, bgp
, rm
,
9709 bgp_unlock_node(rm
);
9711 } else if (safi
== SAFI_FLOWSPEC
) {
9712 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9713 &match
, prefix_check
,
9720 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9722 || rn
->p
.prefixlen
== match
.prefixlen
) {
9723 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9726 route_vty_out_detail_header(
9727 vty
, bgp
, rn
, NULL
, afi
,
9733 if (pathtype
== BGP_PATH_SHOW_ALL
9735 == BGP_PATH_SHOW_BESTPATH
9740 == BGP_PATH_SHOW_MULTIPATH
9746 BGP_PATH_SELECTED
))))
9747 route_vty_out_detail(
9749 afi
, safi
, json_paths
);
9753 bgp_unlock_node(rn
);
9759 json_object_object_add(json
, "paths", json_paths
);
9761 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9762 json
, JSON_C_TO_STRING_PRETTY
));
9763 json_object_free(json
);
9766 vty_out(vty
, "%% Network not in table\n");
9774 /* Display specified route of Main RIB */
9775 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9776 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9777 int prefix_check
, enum bgp_path_type pathtype
,
9781 bgp
= bgp_get_default();
9784 vty_out(vty
, "No BGP process is configured\n");
9786 vty_out(vty
, "{}\n");
9791 /* labeled-unicast routes live in the unicast table */
9792 if (safi
== SAFI_LABELED_UNICAST
)
9793 safi
= SAFI_UNICAST
;
9795 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9796 afi
, safi
, prd
, prefix_check
, pathtype
,
9800 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9801 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9804 struct lcommunity
*lcom
;
9810 b
= buffer_new(1024);
9811 for (i
= 0; i
< argc
; i
++) {
9813 buffer_putc(b
, ' ');
9815 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9817 buffer_putstr(b
, argv
[i
]->arg
);
9821 buffer_putc(b
, '\0');
9823 str
= buffer_getstr(b
);
9826 lcom
= lcommunity_str2com(str
);
9827 XFREE(MTYPE_TMP
, str
);
9829 vty_out(vty
, "%% Large-community malformed\n");
9833 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9837 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9838 const char *lcom
, afi_t afi
, safi_t safi
,
9841 struct community_list
*list
;
9843 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9844 LARGE_COMMUNITY_LIST_MASTER
);
9846 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9851 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9855 DEFUN (show_ip_bgp_large_community_list
,
9856 show_ip_bgp_large_community_list_cmd
,
9857 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9861 BGP_INSTANCE_HELP_STR
9863 BGP_SAFI_WITH_LABEL_HELP_STR
9864 "Display routes matching the large-community-list\n"
9865 "large-community-list number\n"
9866 "large-community-list name\n"
9870 afi_t afi
= AFI_IP6
;
9871 safi_t safi
= SAFI_UNICAST
;
9874 if (argv_find(argv
, argc
, "ip", &idx
))
9876 if (argv_find(argv
, argc
, "view", &idx
)
9877 || argv_find(argv
, argc
, "vrf", &idx
))
9878 vrf
= argv
[++idx
]->arg
;
9879 if (argv_find(argv
, argc
, "ipv4", &idx
)
9880 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9881 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9882 if (argv_find(argv
, argc
, "unicast", &idx
)
9883 || argv_find(argv
, argc
, "multicast", &idx
))
9884 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9887 bool uj
= use_json(argc
, argv
);
9889 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9891 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9895 argv_find(argv
, argc
, "large-community-list", &idx
);
9896 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9899 DEFUN (show_ip_bgp_large_community
,
9900 show_ip_bgp_large_community_cmd
,
9901 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9905 BGP_INSTANCE_HELP_STR
9907 BGP_SAFI_WITH_LABEL_HELP_STR
9908 "Display routes matching the large-communities\n"
9909 "List of large-community numbers\n"
9913 afi_t afi
= AFI_IP6
;
9914 safi_t safi
= SAFI_UNICAST
;
9917 if (argv_find(argv
, argc
, "ip", &idx
))
9919 if (argv_find(argv
, argc
, "view", &idx
)
9920 || argv_find(argv
, argc
, "vrf", &idx
))
9921 vrf
= argv
[++idx
]->arg
;
9922 if (argv_find(argv
, argc
, "ipv4", &idx
)
9923 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9924 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9925 if (argv_find(argv
, argc
, "unicast", &idx
)
9926 || argv_find(argv
, argc
, "multicast", &idx
))
9927 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9930 bool uj
= use_json(argc
, argv
);
9932 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9934 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9938 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9939 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9941 return bgp_show(vty
, bgp
, afi
, safi
,
9942 bgp_show_type_lcommunity_all
, NULL
, uj
);
9945 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9949 /* BGP route print out function without JSON */
9952 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9953 <dampening <parameters>\
9958 |community-list <(1-500)|WORD> [exact-match]\
9959 |A.B.C.D/M longer-prefixes\
9960 |X:X::X:X/M longer-prefixes\
9965 BGP_INSTANCE_HELP_STR
9967 BGP_SAFI_WITH_LABEL_HELP_STR
9968 "Display detailed information about dampening\n"
9969 "Display detail of configured dampening parameters\n"
9970 "Display routes matching the route-map\n"
9971 "A route-map to match on\n"
9972 "Display routes conforming to the prefix-list\n"
9973 "Prefix-list name\n"
9974 "Display routes conforming to the filter-list\n"
9975 "Regular expression access list name\n"
9976 "BGP RIB advertisement statistics\n"
9977 "Display routes matching the community-list\n"
9978 "community-list number\n"
9979 "community-list name\n"
9980 "Exact match of the communities\n"
9982 "Display route and more specific routes\n"
9984 "Display route and more specific routes\n")
9986 afi_t afi
= AFI_IP6
;
9987 safi_t safi
= SAFI_UNICAST
;
9988 int exact_match
= 0;
9989 struct bgp
*bgp
= NULL
;
9992 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9997 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9998 if (argv_find(argv
, argc
, "parameters", &idx
))
9999 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10002 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10003 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10004 safi
, bgp_show_type_prefix_list
);
10006 if (argv_find(argv
, argc
, "filter-list", &idx
))
10007 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10008 safi
, bgp_show_type_filter_list
);
10010 if (argv_find(argv
, argc
, "statistics", &idx
))
10011 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10013 if (argv_find(argv
, argc
, "route-map", &idx
))
10014 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10015 safi
, bgp_show_type_route_map
);
10017 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10018 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10019 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10021 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10022 exact_match
, afi
, safi
);
10024 /* prefix-longer */
10025 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10026 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10027 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10029 bgp_show_type_prefix_longer
);
10031 return CMD_WARNING
;
10034 /* BGP route print out function with JSON */
10035 DEFUN (show_ip_bgp_json
,
10036 show_ip_bgp_json_cmd
,
10037 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10039 |dampening <flap-statistics|dampened-paths>\
10040 |community [AA:NN|local-AS|no-advertise|no-export\
10041 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10042 |accept-own|accept-own-nexthop|route-filter-v6\
10043 |route-filter-v4|route-filter-translated-v6\
10044 |route-filter-translated-v4] [exact-match]\
10049 BGP_INSTANCE_HELP_STR
10051 BGP_SAFI_WITH_LABEL_HELP_STR
10052 "Display only routes with non-natural netmasks\n"
10053 "Display detailed information about dampening\n"
10054 "Display flap statistics of routes\n"
10055 "Display paths suppressed due to dampening\n"
10056 "Display routes matching the communities\n"
10058 "Do not send outside local AS (well-known community)\n"
10059 "Do not advertise to any peer (well-known community)\n"
10060 "Do not export to next AS (well-known community)\n"
10061 "Graceful shutdown (well-known community)\n"
10062 "Do not export to any peer (well-known community)\n"
10063 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10064 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10065 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10066 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10067 "Should accept VPN route with local nexthop (well-known community)\n"
10068 "RT VPNv6 route filtering (well-known community)\n"
10069 "RT VPNv4 route filtering (well-known community)\n"
10070 "RT translated VPNv6 route filtering (well-known community)\n"
10071 "RT translated VPNv4 route filtering (well-known community)\n"
10072 "Exact match of the communities\n"
10075 afi_t afi
= AFI_IP6
;
10076 safi_t safi
= SAFI_UNICAST
;
10077 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10078 struct bgp
*bgp
= NULL
;
10080 int exact_match
= 0;
10081 bool uj
= use_json(argc
, argv
);
10086 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10089 return CMD_WARNING
;
10091 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10092 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10095 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10096 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10097 return bgp_show(vty
, bgp
, afi
, safi
,
10098 bgp_show_type_dampend_paths
, NULL
, uj
);
10099 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10100 return bgp_show(vty
, bgp
, afi
, safi
,
10101 bgp_show_type_flap_statistics
, NULL
,
10105 if (argv_find(argv
, argc
, "community", &idx
)) {
10106 char *maybecomm
= NULL
;
10107 char *community
= NULL
;
10109 if (idx
+ 1 < argc
) {
10110 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10111 maybecomm
= argv
[idx
+ 1]->arg
;
10113 maybecomm
= argv
[idx
+ 1]->text
;
10116 if (maybecomm
&& !strmatch(maybecomm
, "json")
10117 && !strmatch(maybecomm
, "exact-match"))
10118 community
= maybecomm
;
10120 if (argv_find(argv
, argc
, "exact-match", &idx
))
10124 return bgp_show_community(vty
, bgp
, community
,
10125 exact_match
, afi
, safi
, uj
);
10127 return (bgp_show(vty
, bgp
, afi
, safi
,
10128 bgp_show_type_community_all
, NULL
,
10132 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10135 DEFUN (show_ip_bgp_route
,
10136 show_ip_bgp_route_cmd
,
10137 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10138 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10142 BGP_INSTANCE_HELP_STR
10144 BGP_SAFI_WITH_LABEL_HELP_STR
10145 "Network in the BGP routing table to display\n"
10147 "Network in the BGP routing table to display\n"
10149 "Display only the bestpath\n"
10150 "Display only multipaths\n"
10153 int prefix_check
= 0;
10155 afi_t afi
= AFI_IP6
;
10156 safi_t safi
= SAFI_UNICAST
;
10157 char *prefix
= NULL
;
10158 struct bgp
*bgp
= NULL
;
10159 enum bgp_path_type path_type
;
10160 bool uj
= use_json(argc
, argv
);
10164 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10167 return CMD_WARNING
;
10171 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10172 return CMD_WARNING
;
10175 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10176 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10177 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10179 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10180 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10183 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10184 && afi
!= AFI_IP6
) {
10186 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10187 return CMD_WARNING
;
10189 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10190 && afi
!= AFI_IP
) {
10192 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10193 return CMD_WARNING
;
10196 prefix
= argv
[idx
]->arg
;
10198 /* [<bestpath|multipath>] */
10199 if (argv_find(argv
, argc
, "bestpath", &idx
))
10200 path_type
= BGP_PATH_SHOW_BESTPATH
;
10201 else if (argv_find(argv
, argc
, "multipath", &idx
))
10202 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10204 path_type
= BGP_PATH_SHOW_ALL
;
10206 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10210 DEFUN (show_ip_bgp_regexp
,
10211 show_ip_bgp_regexp_cmd
,
10212 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10216 BGP_INSTANCE_HELP_STR
10218 BGP_SAFI_WITH_LABEL_HELP_STR
10219 "Display routes matching the AS path regular expression\n"
10220 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10222 afi_t afi
= AFI_IP6
;
10223 safi_t safi
= SAFI_UNICAST
;
10224 struct bgp
*bgp
= NULL
;
10227 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10230 return CMD_WARNING
;
10232 // get index of regex
10233 argv_find(argv
, argc
, "regexp", &idx
);
10236 char *regstr
= argv_concat(argv
, argc
, idx
);
10237 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10238 bgp_show_type_regexp
);
10239 XFREE(MTYPE_TMP
, regstr
);
10243 DEFUN (show_ip_bgp_instance_all
,
10244 show_ip_bgp_instance_all_cmd
,
10245 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10249 BGP_INSTANCE_ALL_HELP_STR
10251 BGP_SAFI_WITH_LABEL_HELP_STR
10254 afi_t afi
= AFI_IP
;
10255 safi_t safi
= SAFI_UNICAST
;
10256 struct bgp
*bgp
= NULL
;
10258 bool uj
= use_json(argc
, argv
);
10263 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10266 return CMD_WARNING
;
10268 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10269 return CMD_SUCCESS
;
10272 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10273 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10278 if (!config_bgp_aspath_validate(regstr
)) {
10279 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10281 return CMD_WARNING_CONFIG_FAILED
;
10284 regex
= bgp_regcomp(regstr
);
10286 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10287 return CMD_WARNING
;
10290 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10291 bgp_regex_free(regex
);
10295 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10296 const char *prefix_list_str
, afi_t afi
,
10297 safi_t safi
, enum bgp_show_type type
)
10299 struct prefix_list
*plist
;
10301 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10302 if (plist
== NULL
) {
10303 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10305 return CMD_WARNING
;
10308 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10311 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10312 const char *filter
, afi_t afi
, safi_t safi
,
10313 enum bgp_show_type type
)
10315 struct as_list
*as_list
;
10317 as_list
= as_list_lookup(filter
);
10318 if (as_list
== NULL
) {
10319 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10321 return CMD_WARNING
;
10324 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10327 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10328 const char *rmap_str
, afi_t afi
, safi_t safi
,
10329 enum bgp_show_type type
)
10331 struct route_map
*rmap
;
10333 rmap
= route_map_lookup_by_name(rmap_str
);
10335 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10336 return CMD_WARNING
;
10339 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10342 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10343 const char *comstr
, int exact
, afi_t afi
,
10344 safi_t safi
, bool use_json
)
10346 struct community
*com
;
10349 com
= community_str2com(comstr
);
10351 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10352 return CMD_WARNING
;
10355 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10356 (exact
? bgp_show_type_community_exact
10357 : bgp_show_type_community
),
10359 community_free(&com
);
10364 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10365 const char *com
, int exact
, afi_t afi
,
10368 struct community_list
*list
;
10370 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10371 if (list
== NULL
) {
10372 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10373 return CMD_WARNING
;
10376 return bgp_show(vty
, bgp
, afi
, safi
,
10377 (exact
? bgp_show_type_community_list_exact
10378 : bgp_show_type_community_list
),
10382 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10383 const char *prefix
, afi_t afi
, safi_t safi
,
10384 enum bgp_show_type type
)
10391 ret
= str2prefix(prefix
, p
);
10393 vty_out(vty
, "%% Malformed Prefix\n");
10394 return CMD_WARNING
;
10397 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10402 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
10403 const char *ip_str
, bool use_json
)
10407 union sockunion su
;
10409 /* Get peer sockunion. */
10410 ret
= str2sockunion(ip_str
, &su
);
10412 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
10414 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
10418 json_object
*json_no
= NULL
;
10419 json_no
= json_object_new_object();
10420 json_object_string_add(
10422 "malformedAddressOrName",
10424 vty_out(vty
, "%s\n",
10425 json_object_to_json_string_ext(
10427 JSON_C_TO_STRING_PRETTY
));
10428 json_object_free(json_no
);
10431 "%% Malformed address or name: %s\n",
10439 /* Peer structure lookup. */
10440 peer
= peer_lookup(bgp
, &su
);
10443 json_object
*json_no
= NULL
;
10444 json_no
= json_object_new_object();
10445 json_object_string_add(json_no
, "warning",
10446 "No such neighbor in this view/vrf");
10447 vty_out(vty
, "%s\n",
10448 json_object_to_json_string_ext(
10449 json_no
, JSON_C_TO_STRING_PRETTY
));
10450 json_object_free(json_no
);
10452 vty_out(vty
, "No such neighbor in this view/vrf\n");
10460 BGP_STATS_MAXBITLEN
= 0,
10462 BGP_STATS_PREFIXES
,
10464 BGP_STATS_UNAGGREGATEABLE
,
10465 BGP_STATS_MAX_AGGREGATEABLE
,
10466 BGP_STATS_AGGREGATES
,
10468 BGP_STATS_ASPATH_COUNT
,
10469 BGP_STATS_ASPATH_MAXHOPS
,
10470 BGP_STATS_ASPATH_TOTHOPS
,
10471 BGP_STATS_ASPATH_MAXSIZE
,
10472 BGP_STATS_ASPATH_TOTSIZE
,
10473 BGP_STATS_ASN_HIGHEST
,
10477 static const char *table_stats_strs
[] = {
10478 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10479 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10480 [BGP_STATS_RIB
] = "Total Advertisements",
10481 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10482 [BGP_STATS_MAX_AGGREGATEABLE
] =
10483 "Maximum aggregateable prefixes",
10484 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10485 [BGP_STATS_SPACE
] = "Address space advertised",
10486 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10487 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10488 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10489 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10490 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10491 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10492 [BGP_STATS_MAX
] = NULL
,
10495 struct bgp_table_stats
{
10496 struct bgp_table
*table
;
10497 unsigned long long counts
[BGP_STATS_MAX
];
10498 double total_space
;
10502 #define TALLY_SIGFIG 100000
10503 static unsigned long
10504 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10506 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10507 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10508 unsigned long ret
= newtot
/ count
;
10510 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10517 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10518 struct bgp_table_stats
*ts
, unsigned int space
)
10520 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10521 struct bgp_path_info
*pi
;
10526 if (!bgp_node_has_bgp_path_info_data(rn
))
10529 ts
->counts
[BGP_STATS_PREFIXES
]++;
10530 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10533 ts
->counts
[BGP_STATS_AVGPLEN
]
10534 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10535 ts
->counts
[BGP_STATS_AVGPLEN
],
10539 /* check if the prefix is included by any other announcements */
10540 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10541 prn
= bgp_node_parent_nolock(prn
);
10543 if (prn
== NULL
|| prn
== top
) {
10544 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10545 /* announced address space */
10547 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10548 } else if (bgp_node_has_bgp_path_info_data(prn
))
10549 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10552 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10553 ts
->counts
[BGP_STATS_RIB
]++;
10556 && (CHECK_FLAG(pi
->attr
->flag
,
10557 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))))
10558 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10560 /* as-path stats */
10561 if (pi
->attr
&& pi
->attr
->aspath
) {
10562 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10563 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10564 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10566 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10568 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10569 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10571 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10572 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10574 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10575 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10577 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10578 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10579 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10581 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10582 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10583 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10586 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10587 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10592 static int bgp_table_stats_walker(struct thread
*t
)
10594 struct bgp_node
*rn
, *nrn
;
10595 struct bgp_node
*top
;
10596 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10597 unsigned int space
= 0;
10599 if (!(top
= bgp_table_top(ts
->table
)))
10602 switch (ts
->table
->afi
) {
10604 space
= IPV4_MAX_BITLEN
;
10607 space
= IPV6_MAX_BITLEN
;
10613 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10615 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10616 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10617 struct bgp_table
*table
;
10619 table
= bgp_node_get_bgp_table_info(rn
);
10623 top
= bgp_table_top(table
);
10624 for (nrn
= bgp_table_top(table
); nrn
;
10625 nrn
= bgp_route_next(nrn
))
10626 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10628 bgp_table_stats_rn(rn
, top
, ts
, space
);
10635 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10638 struct bgp_table_stats ts
;
10641 if (!bgp
->rib
[afi
][safi
]) {
10642 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10644 return CMD_WARNING
;
10647 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10649 /* labeled-unicast routes live in the unicast table */
10650 if (safi
== SAFI_LABELED_UNICAST
)
10651 safi
= SAFI_UNICAST
;
10653 memset(&ts
, 0, sizeof(ts
));
10654 ts
.table
= bgp
->rib
[afi
][safi
];
10655 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10657 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10658 if (!table_stats_strs
[i
])
10663 case BGP_STATS_ASPATH_AVGHOPS
:
10664 case BGP_STATS_ASPATH_AVGSIZE
:
10665 case BGP_STATS_AVGPLEN
:
10666 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10667 vty_out (vty
, "%12.2f",
10668 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10671 case BGP_STATS_ASPATH_TOTHOPS
:
10672 case BGP_STATS_ASPATH_TOTSIZE
:
10673 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10674 vty_out(vty
, "%12.2f",
10676 ? (float)ts
.counts
[i
]
10678 [BGP_STATS_ASPATH_COUNT
]
10681 case BGP_STATS_TOTPLEN
:
10682 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10683 vty_out(vty
, "%12.2f",
10685 ? (float)ts
.counts
[i
]
10687 [BGP_STATS_PREFIXES
]
10690 case BGP_STATS_SPACE
:
10691 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10692 vty_out(vty
, "%12g\n", ts
.total_space
);
10694 if (afi
== AFI_IP6
) {
10695 vty_out(vty
, "%30s: ", "/32 equivalent ");
10696 vty_out(vty
, "%12g\n",
10697 ts
.total_space
* pow(2.0, -128 + 32));
10698 vty_out(vty
, "%30s: ", "/48 equivalent ");
10699 vty_out(vty
, "%12g\n",
10700 ts
.total_space
* pow(2.0, -128 + 48));
10702 vty_out(vty
, "%30s: ", "% announced ");
10703 vty_out(vty
, "%12.2f\n",
10704 ts
.total_space
* 100. * pow(2.0, -32));
10705 vty_out(vty
, "%30s: ", "/8 equivalent ");
10706 vty_out(vty
, "%12.2f\n",
10707 ts
.total_space
* pow(2.0, -32 + 8));
10708 vty_out(vty
, "%30s: ", "/24 equivalent ");
10709 vty_out(vty
, "%12.2f\n",
10710 ts
.total_space
* pow(2.0, -32 + 24));
10714 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10715 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10718 vty_out(vty
, "\n");
10720 return CMD_SUCCESS
;
10732 PCOUNT_PFCNT
, /* the figure we display to users */
10736 static const char *pcount_strs
[] = {
10737 [PCOUNT_ADJ_IN
] = "Adj-in",
10738 [PCOUNT_DAMPED
] = "Damped",
10739 [PCOUNT_REMOVED
] = "Removed",
10740 [PCOUNT_HISTORY
] = "History",
10741 [PCOUNT_STALE
] = "Stale",
10742 [PCOUNT_VALID
] = "Valid",
10743 [PCOUNT_ALL
] = "All RIB",
10744 [PCOUNT_COUNTED
] = "PfxCt counted",
10745 [PCOUNT_PFCNT
] = "Useable",
10746 [PCOUNT_MAX
] = NULL
,
10749 struct peer_pcounts
{
10750 unsigned int count
[PCOUNT_MAX
];
10751 const struct peer
*peer
;
10752 const struct bgp_table
*table
;
10755 static int bgp_peer_count_walker(struct thread
*t
)
10757 struct bgp_node
*rn
;
10758 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10759 const struct peer
*peer
= pc
->peer
;
10761 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10762 struct bgp_adj_in
*ain
;
10763 struct bgp_path_info
*pi
;
10765 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10766 if (ain
->peer
== peer
)
10767 pc
->count
[PCOUNT_ADJ_IN
]++;
10769 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10771 if (pi
->peer
!= peer
)
10774 pc
->count
[PCOUNT_ALL
]++;
10776 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10777 pc
->count
[PCOUNT_DAMPED
]++;
10778 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10779 pc
->count
[PCOUNT_HISTORY
]++;
10780 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10781 pc
->count
[PCOUNT_REMOVED
]++;
10782 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10783 pc
->count
[PCOUNT_STALE
]++;
10784 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10785 pc
->count
[PCOUNT_VALID
]++;
10786 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10787 pc
->count
[PCOUNT_PFCNT
]++;
10789 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10790 pc
->count
[PCOUNT_COUNTED
]++;
10791 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10793 EC_LIB_DEVELOPMENT
,
10794 "Attempting to count but flags say it is unusable");
10796 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10798 EC_LIB_DEVELOPMENT
,
10799 "Not counted but flags say we should");
10806 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10807 safi_t safi
, bool use_json
)
10809 struct peer_pcounts pcounts
= {.peer
= peer
};
10811 json_object
*json
= NULL
;
10812 json_object
*json_loop
= NULL
;
10815 json
= json_object_new_object();
10816 json_loop
= json_object_new_object();
10819 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10820 || !peer
->bgp
->rib
[afi
][safi
]) {
10822 json_object_string_add(
10824 "No such neighbor or address family");
10825 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10826 json_object_free(json
);
10828 vty_out(vty
, "%% No such neighbor or address family\n");
10830 return CMD_WARNING
;
10833 memset(&pcounts
, 0, sizeof(pcounts
));
10834 pcounts
.peer
= peer
;
10835 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10837 /* in-place call via thread subsystem so as to record execution time
10838 * stats for the thread-walk (i.e. ensure this can't be blamed on
10839 * on just vty_read()).
10841 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10844 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10845 json_object_string_add(json
, "multiProtocol",
10846 afi_safi_print(afi
, safi
));
10847 json_object_int_add(json
, "pfxCounter",
10848 peer
->pcount
[afi
][safi
]);
10850 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10851 json_object_int_add(json_loop
, pcount_strs
[i
],
10854 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10856 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10857 json_object_string_add(json
, "pfxctDriftFor",
10859 json_object_string_add(
10860 json
, "recommended",
10861 "Please report this bug, with the above command output");
10863 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10864 json
, JSON_C_TO_STRING_PRETTY
));
10865 json_object_free(json
);
10869 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10870 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10871 peer
->hostname
, peer
->host
,
10872 afi_safi_print(afi
, safi
));
10874 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10875 afi_safi_print(afi
, safi
));
10878 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10879 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10881 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10882 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10885 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10886 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10888 "Please report this bug, with the above command output\n");
10892 return CMD_SUCCESS
;
10895 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10896 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10897 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10898 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10902 BGP_INSTANCE_HELP_STR
10905 "Detailed information on TCP and BGP neighbor connections\n"
10906 "Neighbor to display information about\n"
10907 "Neighbor to display information about\n"
10908 "Neighbor on BGP configured interface\n"
10909 "Display detailed prefix count information\n"
10912 afi_t afi
= AFI_IP6
;
10913 safi_t safi
= SAFI_UNICAST
;
10916 struct bgp
*bgp
= NULL
;
10917 bool uj
= use_json(argc
, argv
);
10922 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10925 return CMD_WARNING
;
10927 argv_find(argv
, argc
, "neighbors", &idx
);
10928 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10930 return CMD_WARNING
;
10932 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10935 #ifdef KEEP_OLD_VPN_COMMANDS
10936 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10937 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10938 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10943 "Display information about all VPNv4 NLRIs\n"
10944 "Detailed information on TCP and BGP neighbor connections\n"
10945 "Neighbor to display information about\n"
10946 "Neighbor to display information about\n"
10947 "Neighbor on BGP configured interface\n"
10948 "Display detailed prefix count information\n"
10953 bool uj
= use_json(argc
, argv
);
10955 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10957 return CMD_WARNING
;
10959 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10962 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10963 show_ip_bgp_vpn_all_route_prefix_cmd
,
10964 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10969 "Display information about all VPNv4 NLRIs\n"
10970 "Network in the BGP routing table to display\n"
10971 "Network in the BGP routing table to display\n"
10975 char *network
= NULL
;
10976 struct bgp
*bgp
= bgp_get_default();
10978 vty_out(vty
, "Can't find default instance\n");
10979 return CMD_WARNING
;
10982 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10983 network
= argv
[idx
]->arg
;
10984 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10985 network
= argv
[idx
]->arg
;
10987 vty_out(vty
, "Unable to figure out Network\n");
10988 return CMD_WARNING
;
10991 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10992 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10994 #endif /* KEEP_OLD_VPN_COMMANDS */
10996 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10997 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10998 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
11004 "Display information about all EVPN NLRIs\n"
11005 "Network in the BGP routing table to display\n"
11006 "Network in the BGP routing table to display\n"
11010 char *network
= NULL
;
11012 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11013 network
= argv
[idx
]->arg
;
11014 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11015 network
= argv
[idx
]->arg
;
11017 vty_out(vty
, "Unable to figure out Network\n");
11018 return CMD_WARNING
;
11020 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
11021 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11024 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11025 safi_t safi
, enum bgp_show_adj_route_type type
,
11026 const char *rmap_name
, bool use_json
,
11029 struct bgp_table
*table
;
11030 struct bgp_adj_in
*ain
;
11031 struct bgp_adj_out
*adj
;
11032 unsigned long output_count
;
11033 unsigned long filtered_count
;
11034 struct bgp_node
*rn
;
11040 struct update_subgroup
*subgrp
;
11041 json_object
*json_scode
= NULL
;
11042 json_object
*json_ocode
= NULL
;
11043 json_object
*json_ar
= NULL
;
11044 struct peer_af
*paf
;
11045 bool route_filtered
;
11048 json_scode
= json_object_new_object();
11049 json_ocode
= json_object_new_object();
11050 json_ar
= json_object_new_object();
11052 json_object_string_add(json_scode
, "suppressed", "s");
11053 json_object_string_add(json_scode
, "damped", "d");
11054 json_object_string_add(json_scode
, "history", "h");
11055 json_object_string_add(json_scode
, "valid", "*");
11056 json_object_string_add(json_scode
, "best", ">");
11057 json_object_string_add(json_scode
, "multipath", "=");
11058 json_object_string_add(json_scode
, "internal", "i");
11059 json_object_string_add(json_scode
, "ribFailure", "r");
11060 json_object_string_add(json_scode
, "stale", "S");
11061 json_object_string_add(json_scode
, "removed", "R");
11063 json_object_string_add(json_ocode
, "igp", "i");
11064 json_object_string_add(json_ocode
, "egp", "e");
11065 json_object_string_add(json_ocode
, "incomplete", "?");
11072 json_object_string_add(json
, "alert", "no BGP");
11073 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11074 json_object_free(json
);
11076 vty_out(vty
, "%% No bgp\n");
11080 /* labeled-unicast routes live in the unicast table */
11081 if (safi
== SAFI_LABELED_UNICAST
)
11082 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11084 table
= bgp
->rib
[afi
][safi
];
11086 output_count
= filtered_count
= 0;
11087 subgrp
= peer_subgroup(peer
, afi
, safi
);
11089 if (type
== bgp_show_adj_route_advertised
&& subgrp
11090 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11092 json_object_int_add(json
, "bgpTableVersion",
11094 json_object_string_add(json
, "bgpLocalRouterId",
11095 inet_ntoa(bgp
->router_id
));
11096 json_object_int_add(json
, "defaultLocPrf",
11097 bgp
->default_local_pref
);
11098 json_object_int_add(json
, "localAS", bgp
->as
);
11099 json_object_object_add(json
, "bgpStatusCodes",
11101 json_object_object_add(json
, "bgpOriginCodes",
11103 json_object_string_add(
11104 json
, "bgpOriginatingDefaultNetwork",
11105 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11107 vty_out(vty
, "BGP table version is %" PRIu64
11108 ", local router ID is %s, vrf id ",
11109 table
->version
, inet_ntoa(bgp
->router_id
));
11110 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11111 vty_out(vty
, "%s", VRFID_NONE_STR
);
11113 vty_out(vty
, "%u", bgp
->vrf_id
);
11114 vty_out(vty
, "\n");
11115 vty_out(vty
, "Default local pref %u, ",
11116 bgp
->default_local_pref
);
11117 vty_out(vty
, "local AS %u\n", bgp
->as
);
11118 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11119 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11120 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11122 vty_out(vty
, "Originating default network %s\n\n",
11123 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11128 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11129 if (type
== bgp_show_adj_route_received
11130 || type
== bgp_show_adj_route_filtered
) {
11131 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11132 if (ain
->peer
!= peer
|| !ain
->attr
)
11137 json_object_int_add(
11138 json
, "bgpTableVersion",
11140 json_object_string_add(
11142 "bgpLocalRouterId",
11145 json_object_int_add(json
,
11147 bgp
->default_local_pref
);
11148 json_object_int_add(json
,
11149 "localAS", bgp
->as
);
11150 json_object_object_add(
11151 json
, "bgpStatusCodes",
11153 json_object_object_add(
11154 json
, "bgpOriginCodes",
11158 "BGP table version is 0, local router ID is %s, vrf id ",
11161 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11167 vty_out(vty
, "\n");
11169 "Default local pref %u, ",
11170 bgp
->default_local_pref
);
11171 vty_out(vty
, "local AS %u\n",
11174 BGP_SHOW_SCODE_HEADER
);
11176 BGP_SHOW_NCODE_HEADER
);
11178 BGP_SHOW_OCODE_HEADER
);
11184 vty_out(vty
, BGP_SHOW_HEADER
);
11188 bgp_attr_dup(&attr
, ain
->attr
);
11189 route_filtered
= false;
11191 /* Filter prefix using distribute list,
11192 * filter list or prefix list
11194 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11195 safi
)) == FILTER_DENY
)
11196 route_filtered
= true;
11198 /* Filter prefix using route-map */
11199 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11200 afi
, safi
, rmap_name
);
11202 if (type
== bgp_show_adj_route_filtered
&&
11203 !route_filtered
&& ret
!= RMAP_DENY
) {
11204 bgp_attr_undup(&attr
, ain
->attr
);
11208 if (type
== bgp_show_adj_route_received
&&
11209 (route_filtered
|| ret
== RMAP_DENY
))
11212 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11213 use_json
, json_ar
);
11214 bgp_attr_undup(&attr
, ain
->attr
);
11217 } else if (type
== bgp_show_adj_route_advertised
) {
11218 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11219 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11220 if (paf
->peer
!= peer
|| !adj
->attr
)
11225 json_object_int_add(
11229 json_object_string_add(
11231 "bgpLocalRouterId",
11234 json_object_int_add(
11235 json
, "defaultLocPrf",
11236 bgp
->default_local_pref
11238 json_object_int_add(
11241 json_object_object_add(
11245 json_object_object_add(
11251 "BGP table version is %" PRIu64
11252 ", local router ID is %s, vrf id ",
11265 vty_out(vty
, "\n");
11267 "Default local pref %u, ",
11268 bgp
->default_local_pref
11274 BGP_SHOW_SCODE_HEADER
);
11276 BGP_SHOW_NCODE_HEADER
);
11278 BGP_SHOW_OCODE_HEADER
);
11289 bgp_attr_dup(&attr
, adj
->attr
);
11290 ret
= bgp_output_modifier(
11291 peer
, &rn
->p
, &attr
, afi
, safi
,
11294 if (ret
!= RMAP_DENY
) {
11295 route_vty_out_tmp(vty
, &rn
->p
,
11304 bgp_attr_undup(&attr
, adj
->attr
);
11310 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11311 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11312 json_object_int_add(json
, "filteredPrefixCounter",
11315 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11316 json
, JSON_C_TO_STRING_PRETTY
));
11317 json_object_free(json
);
11318 } else if (output_count
> 0) {
11319 if (filtered_count
> 0)
11321 "\nTotal number of prefixes %ld (%ld filtered)\n",
11322 output_count
, filtered_count
);
11324 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11329 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11330 safi_t safi
, enum bgp_show_adj_route_type type
,
11331 const char *rmap_name
, bool use_json
)
11333 json_object
*json
= NULL
;
11336 json
= json_object_new_object();
11338 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11340 json_object_string_add(
11342 "No such neighbor or address family");
11343 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11344 json_object_free(json
);
11346 vty_out(vty
, "%% No such neighbor or address family\n");
11348 return CMD_WARNING
;
11351 if ((type
== bgp_show_adj_route_received
11352 || type
== bgp_show_adj_route_filtered
)
11353 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11354 PEER_FLAG_SOFT_RECONFIG
)) {
11356 json_object_string_add(
11358 "Inbound soft reconfiguration not enabled");
11359 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11360 json_object_free(json
);
11363 "%% Inbound soft reconfiguration not enabled\n");
11365 return CMD_WARNING
;
11368 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11370 return CMD_SUCCESS
;
11373 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11374 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11375 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11376 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11380 BGP_INSTANCE_HELP_STR
11382 BGP_SAFI_WITH_LABEL_HELP_STR
11383 "Detailed information on TCP and BGP neighbor connections\n"
11384 "Neighbor to display information about\n"
11385 "Neighbor to display information about\n"
11386 "Neighbor on BGP configured interface\n"
11387 "Display the routes advertised to a BGP neighbor\n"
11388 "Display the received routes from neighbor\n"
11389 "Display the filtered routes received from neighbor\n"
11390 "Route-map to modify the attributes\n"
11391 "Name of the route map\n"
11394 afi_t afi
= AFI_IP6
;
11395 safi_t safi
= SAFI_UNICAST
;
11396 char *rmap_name
= NULL
;
11397 char *peerstr
= NULL
;
11398 struct bgp
*bgp
= NULL
;
11400 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11402 bool uj
= use_json(argc
, argv
);
11407 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11410 return CMD_WARNING
;
11412 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11413 argv_find(argv
, argc
, "neighbors", &idx
);
11414 peerstr
= argv
[++idx
]->arg
;
11416 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11418 return CMD_WARNING
;
11420 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11421 type
= bgp_show_adj_route_advertised
;
11422 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11423 type
= bgp_show_adj_route_received
;
11424 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11425 type
= bgp_show_adj_route_filtered
;
11427 if (argv_find(argv
, argc
, "route-map", &idx
))
11428 rmap_name
= argv
[++idx
]->arg
;
11430 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11433 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11434 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11435 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11441 "Address Family modifier\n"
11442 "Detailed information on TCP and BGP neighbor connections\n"
11443 "Neighbor to display information about\n"
11444 "Neighbor to display information about\n"
11445 "Neighbor on BGP configured interface\n"
11446 "Display information received from a BGP neighbor\n"
11447 "Display the prefixlist filter\n"
11450 afi_t afi
= AFI_IP6
;
11451 safi_t safi
= SAFI_UNICAST
;
11452 char *peerstr
= NULL
;
11455 union sockunion su
;
11461 /* show [ip] bgp */
11462 if (argv_find(argv
, argc
, "ip", &idx
))
11464 /* [<ipv4|ipv6> [unicast]] */
11465 if (argv_find(argv
, argc
, "ipv4", &idx
))
11467 if (argv_find(argv
, argc
, "ipv6", &idx
))
11469 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11470 argv_find(argv
, argc
, "neighbors", &idx
);
11471 peerstr
= argv
[++idx
]->arg
;
11473 bool uj
= use_json(argc
, argv
);
11475 ret
= str2sockunion(peerstr
, &su
);
11477 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11480 vty_out(vty
, "{}\n");
11483 "%% Malformed address or name: %s\n",
11485 return CMD_WARNING
;
11488 peer
= peer_lookup(NULL
, &su
);
11491 vty_out(vty
, "{}\n");
11493 vty_out(vty
, "No peer\n");
11494 return CMD_WARNING
;
11498 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11499 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11502 vty_out(vty
, "Address Family: %s\n",
11503 afi_safi_print(afi
, safi
));
11504 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11507 vty_out(vty
, "{}\n");
11509 vty_out(vty
, "No functional output\n");
11512 return CMD_SUCCESS
;
11515 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11516 afi_t afi
, safi_t safi
,
11517 enum bgp_show_type type
, bool use_json
)
11519 /* labeled-unicast routes live in the unicast table */
11520 if (safi
== SAFI_LABELED_UNICAST
)
11521 safi
= SAFI_UNICAST
;
11523 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11525 json_object
*json_no
= NULL
;
11526 json_no
= json_object_new_object();
11527 json_object_string_add(
11528 json_no
, "warning",
11529 "No such neighbor or address family");
11530 vty_out(vty
, "%s\n",
11531 json_object_to_json_string(json_no
));
11532 json_object_free(json_no
);
11534 vty_out(vty
, "%% No such neighbor or address family\n");
11535 return CMD_WARNING
;
11538 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11541 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11542 show_ip_bgp_flowspec_routes_detailed_cmd
,
11543 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11547 BGP_INSTANCE_HELP_STR
11550 "Detailed information on flowspec entries\n"
11553 afi_t afi
= AFI_IP
;
11554 safi_t safi
= SAFI_UNICAST
;
11555 struct bgp
*bgp
= NULL
;
11557 bool uj
= use_json(argc
, argv
);
11562 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11565 return CMD_WARNING
;
11567 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11570 DEFUN (show_ip_bgp_neighbor_routes
,
11571 show_ip_bgp_neighbor_routes_cmd
,
11572 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11573 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11577 BGP_INSTANCE_HELP_STR
11579 BGP_SAFI_WITH_LABEL_HELP_STR
11580 "Detailed information on TCP and BGP neighbor connections\n"
11581 "Neighbor to display information about\n"
11582 "Neighbor to display information about\n"
11583 "Neighbor on BGP configured interface\n"
11584 "Display flap statistics of the routes learned from neighbor\n"
11585 "Display the dampened routes received from neighbor\n"
11586 "Display routes learned from neighbor\n"
11589 char *peerstr
= NULL
;
11590 struct bgp
*bgp
= NULL
;
11591 afi_t afi
= AFI_IP6
;
11592 safi_t safi
= SAFI_UNICAST
;
11594 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11596 bool uj
= use_json(argc
, argv
);
11601 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11604 return CMD_WARNING
;
11606 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11607 argv_find(argv
, argc
, "neighbors", &idx
);
11608 peerstr
= argv
[++idx
]->arg
;
11610 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11612 return CMD_WARNING
;
11614 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11615 sh_type
= bgp_show_type_flap_neighbor
;
11616 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11617 sh_type
= bgp_show_type_damp_neighbor
;
11618 else if (argv_find(argv
, argc
, "routes", &idx
))
11619 sh_type
= bgp_show_type_neighbor
;
11621 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11624 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11626 struct bgp_distance
{
11627 /* Distance value for the IP source prefix. */
11630 /* Name of the access-list to be matched. */
11634 DEFUN (show_bgp_afi_vpn_rd_route
,
11635 show_bgp_afi_vpn_rd_route_cmd
,
11636 "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]",
11640 "Address Family modifier\n"
11641 "Display information for a route distinguisher\n"
11642 "Route Distinguisher\n"
11643 "Network in the BGP routing table to display\n"
11644 "Network in the BGP routing table to display\n"
11648 struct prefix_rd prd
;
11649 afi_t afi
= AFI_MAX
;
11652 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11653 vty_out(vty
, "%% Malformed Address Family\n");
11654 return CMD_WARNING
;
11657 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11659 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11660 return CMD_WARNING
;
11663 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11664 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11667 static struct bgp_distance
*bgp_distance_new(void)
11669 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11672 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11674 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11677 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11678 const char *ip_str
, const char *access_list_str
)
11685 struct bgp_node
*rn
;
11686 struct bgp_distance
*bdistance
;
11688 afi
= bgp_node_afi(vty
);
11689 safi
= bgp_node_safi(vty
);
11691 ret
= str2prefix(ip_str
, &p
);
11693 vty_out(vty
, "Malformed prefix\n");
11694 return CMD_WARNING_CONFIG_FAILED
;
11697 distance
= atoi(distance_str
);
11699 /* Get BGP distance node. */
11700 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11701 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11703 bgp_unlock_node(rn
);
11705 bdistance
= bgp_distance_new();
11706 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11709 /* Set distance value. */
11710 bdistance
->distance
= distance
;
11712 /* Reset access-list configuration. */
11713 if (bdistance
->access_list
) {
11714 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11715 bdistance
->access_list
= NULL
;
11717 if (access_list_str
)
11718 bdistance
->access_list
=
11719 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11721 return CMD_SUCCESS
;
11724 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11725 const char *ip_str
, const char *access_list_str
)
11732 struct bgp_node
*rn
;
11733 struct bgp_distance
*bdistance
;
11735 afi
= bgp_node_afi(vty
);
11736 safi
= bgp_node_safi(vty
);
11738 ret
= str2prefix(ip_str
, &p
);
11740 vty_out(vty
, "Malformed prefix\n");
11741 return CMD_WARNING_CONFIG_FAILED
;
11744 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11745 (struct prefix
*)&p
);
11747 vty_out(vty
, "Can't find specified prefix\n");
11748 return CMD_WARNING_CONFIG_FAILED
;
11751 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11752 distance
= atoi(distance_str
);
11754 if (bdistance
->distance
!= distance
) {
11755 vty_out(vty
, "Distance does not match configured\n");
11756 return CMD_WARNING_CONFIG_FAILED
;
11759 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11760 bgp_distance_free(bdistance
);
11762 bgp_node_set_bgp_path_info(rn
, NULL
);
11763 bgp_unlock_node(rn
);
11764 bgp_unlock_node(rn
);
11766 return CMD_SUCCESS
;
11769 /* Apply BGP information to distance method. */
11770 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11771 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11773 struct bgp_node
*rn
;
11776 struct bgp_distance
*bdistance
;
11777 struct access_list
*alist
;
11778 struct bgp_static
*bgp_static
;
11783 peer
= pinfo
->peer
;
11785 /* Check source address. */
11786 sockunion2hostprefix(&peer
->su
, &q
);
11787 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11789 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11790 bgp_unlock_node(rn
);
11792 if (bdistance
->access_list
) {
11793 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11795 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11796 return bdistance
->distance
;
11798 return bdistance
->distance
;
11801 /* Backdoor check. */
11802 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11804 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11805 bgp_unlock_node(rn
);
11807 if (bgp_static
->backdoor
) {
11808 if (bgp
->distance_local
[afi
][safi
])
11809 return bgp
->distance_local
[afi
][safi
];
11811 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11815 if (peer
->sort
== BGP_PEER_EBGP
) {
11816 if (bgp
->distance_ebgp
[afi
][safi
])
11817 return bgp
->distance_ebgp
[afi
][safi
];
11818 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11820 if (bgp
->distance_ibgp
[afi
][safi
])
11821 return bgp
->distance_ibgp
[afi
][safi
];
11822 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11826 DEFUN (bgp_distance
,
11828 "distance bgp (1-255) (1-255) (1-255)",
11829 "Define an administrative distance\n"
11831 "Distance for routes external to the AS\n"
11832 "Distance for routes internal to the AS\n"
11833 "Distance for local routes\n")
11835 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11836 int idx_number
= 2;
11837 int idx_number_2
= 3;
11838 int idx_number_3
= 4;
11842 afi
= bgp_node_afi(vty
);
11843 safi
= bgp_node_safi(vty
);
11845 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11846 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11847 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11848 return CMD_SUCCESS
;
11851 DEFUN (no_bgp_distance
,
11852 no_bgp_distance_cmd
,
11853 "no distance bgp [(1-255) (1-255) (1-255)]",
11855 "Define an administrative distance\n"
11857 "Distance for routes external to the AS\n"
11858 "Distance for routes internal to the AS\n"
11859 "Distance for local routes\n")
11861 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11865 afi
= bgp_node_afi(vty
);
11866 safi
= bgp_node_safi(vty
);
11868 bgp
->distance_ebgp
[afi
][safi
] = 0;
11869 bgp
->distance_ibgp
[afi
][safi
] = 0;
11870 bgp
->distance_local
[afi
][safi
] = 0;
11871 return CMD_SUCCESS
;
11875 DEFUN (bgp_distance_source
,
11876 bgp_distance_source_cmd
,
11877 "distance (1-255) A.B.C.D/M",
11878 "Define an administrative distance\n"
11879 "Administrative distance\n"
11880 "IP source prefix\n")
11882 int idx_number
= 1;
11883 int idx_ipv4_prefixlen
= 2;
11884 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11885 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11886 return CMD_SUCCESS
;
11889 DEFUN (no_bgp_distance_source
,
11890 no_bgp_distance_source_cmd
,
11891 "no distance (1-255) A.B.C.D/M",
11893 "Define an administrative distance\n"
11894 "Administrative distance\n"
11895 "IP source prefix\n")
11897 int idx_number
= 2;
11898 int idx_ipv4_prefixlen
= 3;
11899 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11900 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11901 return CMD_SUCCESS
;
11904 DEFUN (bgp_distance_source_access_list
,
11905 bgp_distance_source_access_list_cmd
,
11906 "distance (1-255) A.B.C.D/M WORD",
11907 "Define an administrative distance\n"
11908 "Administrative distance\n"
11909 "IP source prefix\n"
11910 "Access list name\n")
11912 int idx_number
= 1;
11913 int idx_ipv4_prefixlen
= 2;
11915 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11916 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11917 return CMD_SUCCESS
;
11920 DEFUN (no_bgp_distance_source_access_list
,
11921 no_bgp_distance_source_access_list_cmd
,
11922 "no distance (1-255) A.B.C.D/M WORD",
11924 "Define an administrative distance\n"
11925 "Administrative distance\n"
11926 "IP source prefix\n"
11927 "Access list name\n")
11929 int idx_number
= 2;
11930 int idx_ipv4_prefixlen
= 3;
11932 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11933 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11934 return CMD_SUCCESS
;
11937 DEFUN (ipv6_bgp_distance_source
,
11938 ipv6_bgp_distance_source_cmd
,
11939 "distance (1-255) X:X::X:X/M",
11940 "Define an administrative distance\n"
11941 "Administrative distance\n"
11942 "IP source prefix\n")
11944 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11945 return CMD_SUCCESS
;
11948 DEFUN (no_ipv6_bgp_distance_source
,
11949 no_ipv6_bgp_distance_source_cmd
,
11950 "no distance (1-255) X:X::X:X/M",
11952 "Define an administrative distance\n"
11953 "Administrative distance\n"
11954 "IP source prefix\n")
11956 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11957 return CMD_SUCCESS
;
11960 DEFUN (ipv6_bgp_distance_source_access_list
,
11961 ipv6_bgp_distance_source_access_list_cmd
,
11962 "distance (1-255) X:X::X:X/M WORD",
11963 "Define an administrative distance\n"
11964 "Administrative distance\n"
11965 "IP source prefix\n"
11966 "Access list name\n")
11968 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11969 return CMD_SUCCESS
;
11972 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11973 no_ipv6_bgp_distance_source_access_list_cmd
,
11974 "no distance (1-255) X:X::X:X/M WORD",
11976 "Define an administrative distance\n"
11977 "Administrative distance\n"
11978 "IP source prefix\n"
11979 "Access list name\n")
11981 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11982 return CMD_SUCCESS
;
11985 DEFUN (bgp_damp_set
,
11987 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11988 "BGP Specific commands\n"
11989 "Enable route-flap dampening\n"
11990 "Half-life time for the penalty\n"
11991 "Value to start reusing a route\n"
11992 "Value to start suppressing a route\n"
11993 "Maximum duration to suppress a stable route\n")
11995 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11996 int idx_half_life
= 2;
11998 int idx_suppress
= 4;
11999 int idx_max_suppress
= 5;
12000 int half
= DEFAULT_HALF_LIFE
* 60;
12001 int reuse
= DEFAULT_REUSE
;
12002 int suppress
= DEFAULT_SUPPRESS
;
12003 int max
= 4 * half
;
12006 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12007 reuse
= atoi(argv
[idx_reuse
]->arg
);
12008 suppress
= atoi(argv
[idx_suppress
]->arg
);
12009 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12010 } else if (argc
== 3) {
12011 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12015 if (suppress
< reuse
) {
12017 "Suppress value cannot be less than reuse value \n");
12021 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12022 reuse
, suppress
, max
);
12025 DEFUN (bgp_damp_unset
,
12026 bgp_damp_unset_cmd
,
12027 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12029 "BGP Specific commands\n"
12030 "Enable route-flap dampening\n"
12031 "Half-life time for the penalty\n"
12032 "Value to start reusing a route\n"
12033 "Value to start suppressing a route\n"
12034 "Maximum duration to suppress a stable route\n")
12036 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12037 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12040 /* Display specified route of BGP table. */
12041 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12042 const char *ip_str
, afi_t afi
, safi_t safi
,
12043 struct prefix_rd
*prd
, int prefix_check
)
12046 struct prefix match
;
12047 struct bgp_node
*rn
;
12048 struct bgp_node
*rm
;
12049 struct bgp_path_info
*pi
;
12050 struct bgp_path_info
*pi_temp
;
12052 struct bgp_table
*table
;
12054 /* BGP structure lookup. */
12056 bgp
= bgp_lookup_by_name(view_name
);
12058 vty_out(vty
, "%% Can't find BGP instance %s\n",
12060 return CMD_WARNING
;
12063 bgp
= bgp_get_default();
12065 vty_out(vty
, "%% No BGP process is configured\n");
12066 return CMD_WARNING
;
12070 /* Check IP address argument. */
12071 ret
= str2prefix(ip_str
, &match
);
12073 vty_out(vty
, "%% address is malformed\n");
12074 return CMD_WARNING
;
12077 match
.family
= afi2family(afi
);
12079 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12080 || (safi
== SAFI_EVPN
)) {
12081 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12082 rn
= bgp_route_next(rn
)) {
12083 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12085 table
= bgp_node_get_bgp_table_info(rn
);
12088 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12092 || rm
->p
.prefixlen
== match
.prefixlen
) {
12093 pi
= bgp_node_get_bgp_path_info(rm
);
12095 if (pi
->extra
&& pi
->extra
->damp_info
) {
12096 pi_temp
= pi
->next
;
12097 bgp_damp_info_free(
12098 pi
->extra
->damp_info
,
12106 bgp_unlock_node(rm
);
12109 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12112 || rn
->p
.prefixlen
== match
.prefixlen
) {
12113 pi
= bgp_node_get_bgp_path_info(rn
);
12115 if (pi
->extra
&& pi
->extra
->damp_info
) {
12116 pi_temp
= pi
->next
;
12117 bgp_damp_info_free(
12118 pi
->extra
->damp_info
,
12126 bgp_unlock_node(rn
);
12130 return CMD_SUCCESS
;
12133 DEFUN (clear_ip_bgp_dampening
,
12134 clear_ip_bgp_dampening_cmd
,
12135 "clear ip bgp dampening",
12139 "Clear route flap dampening information\n")
12141 bgp_damp_info_clean();
12142 return CMD_SUCCESS
;
12145 DEFUN (clear_ip_bgp_dampening_prefix
,
12146 clear_ip_bgp_dampening_prefix_cmd
,
12147 "clear ip bgp dampening A.B.C.D/M",
12151 "Clear route flap dampening information\n"
12154 int idx_ipv4_prefixlen
= 4;
12155 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12156 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12159 DEFUN (clear_ip_bgp_dampening_address
,
12160 clear_ip_bgp_dampening_address_cmd
,
12161 "clear ip bgp dampening A.B.C.D",
12165 "Clear route flap dampening information\n"
12166 "Network to clear damping information\n")
12169 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12170 SAFI_UNICAST
, NULL
, 0);
12173 DEFUN (clear_ip_bgp_dampening_address_mask
,
12174 clear_ip_bgp_dampening_address_mask_cmd
,
12175 "clear ip bgp dampening A.B.C.D A.B.C.D",
12179 "Clear route flap dampening information\n"
12180 "Network to clear damping information\n"
12184 int idx_ipv4_2
= 5;
12186 char prefix_str
[BUFSIZ
];
12188 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12191 vty_out(vty
, "%% Inconsistent address and mask\n");
12192 return CMD_WARNING
;
12195 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12199 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12201 struct vty
*vty
= arg
;
12202 struct peer
*peer
= bucket
->data
;
12203 char buf
[SU_ADDRSTRLEN
];
12205 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12206 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12209 DEFUN (show_bgp_peerhash
,
12210 show_bgp_peerhash_cmd
,
12211 "show bgp peerhash",
12214 "Display information about the BGP peerhash\n")
12216 struct list
*instances
= bm
->bgp
;
12217 struct listnode
*node
;
12220 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12221 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12222 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12226 return CMD_SUCCESS
;
12229 /* also used for encap safi */
12230 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12231 afi_t afi
, safi_t safi
)
12233 struct bgp_node
*prn
;
12234 struct bgp_node
*rn
;
12235 struct bgp_table
*table
;
12237 struct prefix_rd
*prd
;
12238 struct bgp_static
*bgp_static
;
12239 mpls_label_t label
;
12240 char buf
[SU_ADDRSTRLEN
];
12241 char rdbuf
[RD_ADDRSTRLEN
];
12243 /* Network configuration. */
12244 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12245 prn
= bgp_route_next(prn
)) {
12246 table
= bgp_node_get_bgp_table_info(prn
);
12250 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12251 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12252 if (bgp_static
== NULL
)
12256 prd
= (struct prefix_rd
*)&prn
->p
;
12258 /* "network" configuration display. */
12259 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12260 label
= decode_label(&bgp_static
->label
);
12262 vty_out(vty
, " network %s/%d rd %s",
12263 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12265 p
->prefixlen
, rdbuf
);
12266 if (safi
== SAFI_MPLS_VPN
)
12267 vty_out(vty
, " label %u", label
);
12269 if (bgp_static
->rmap
.name
)
12270 vty_out(vty
, " route-map %s",
12271 bgp_static
->rmap
.name
);
12273 if (bgp_static
->backdoor
)
12274 vty_out(vty
, " backdoor");
12276 vty_out(vty
, "\n");
12281 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12282 afi_t afi
, safi_t safi
)
12284 struct bgp_node
*prn
;
12285 struct bgp_node
*rn
;
12286 struct bgp_table
*table
;
12288 struct prefix_rd
*prd
;
12289 struct bgp_static
*bgp_static
;
12290 char buf
[PREFIX_STRLEN
* 2];
12291 char buf2
[SU_ADDRSTRLEN
];
12292 char rdbuf
[RD_ADDRSTRLEN
];
12294 /* Network configuration. */
12295 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12296 prn
= bgp_route_next(prn
)) {
12297 table
= bgp_node_get_bgp_table_info(prn
);
12301 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12302 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12303 if (bgp_static
== NULL
)
12306 char *macrouter
= NULL
;
12309 if (bgp_static
->router_mac
)
12310 macrouter
= prefix_mac2str(
12311 bgp_static
->router_mac
, NULL
, 0);
12312 if (bgp_static
->eth_s_id
)
12313 esi
= esi2str(bgp_static
->eth_s_id
);
12315 prd
= (struct prefix_rd
*)&prn
->p
;
12317 /* "network" configuration display. */
12318 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12319 if (p
->u
.prefix_evpn
.route_type
== 5) {
12320 char local_buf
[PREFIX_STRLEN
];
12321 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12322 struct prefix_evpn
*)p
)
12326 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12327 local_buf
, PREFIX_STRLEN
);
12328 sprintf(buf
, "%s/%u", local_buf
,
12329 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12331 prefix2str(p
, buf
, sizeof(buf
));
12334 if (bgp_static
->gatewayIp
.family
== AF_INET
12335 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12336 inet_ntop(bgp_static
->gatewayIp
.family
,
12337 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12340 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12342 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12343 decode_label(&bgp_static
->label
), esi
, buf2
,
12346 XFREE(MTYPE_TMP
, macrouter
);
12347 XFREE(MTYPE_TMP
, esi
);
12352 /* Configuration of static route announcement and aggregate
12354 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12357 struct bgp_node
*rn
;
12359 struct bgp_static
*bgp_static
;
12360 struct bgp_aggregate
*bgp_aggregate
;
12361 char buf
[SU_ADDRSTRLEN
];
12363 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12364 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12368 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12369 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12373 /* Network configuration. */
12374 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12375 rn
= bgp_route_next(rn
)) {
12376 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12377 if (bgp_static
== NULL
)
12382 vty_out(vty
, " network %s/%d",
12383 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12386 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12387 vty_out(vty
, " label-index %u",
12388 bgp_static
->label_index
);
12390 if (bgp_static
->rmap
.name
)
12391 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12393 if (bgp_static
->backdoor
)
12394 vty_out(vty
, " backdoor");
12396 vty_out(vty
, "\n");
12399 /* Aggregate-address configuration. */
12400 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12401 rn
= bgp_route_next(rn
)) {
12402 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12403 if (bgp_aggregate
== NULL
)
12408 vty_out(vty
, " aggregate-address %s/%d",
12409 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12412 if (bgp_aggregate
->as_set
)
12413 vty_out(vty
, " as-set");
12415 if (bgp_aggregate
->summary_only
)
12416 vty_out(vty
, " summary-only");
12418 vty_out(vty
, "\n");
12422 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12425 struct bgp_node
*rn
;
12426 struct bgp_distance
*bdistance
;
12428 /* Distance configuration. */
12429 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12430 && bgp
->distance_local
[afi
][safi
]
12431 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12432 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12433 || bgp
->distance_local
[afi
][safi
]
12434 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12435 vty_out(vty
, " distance bgp %d %d %d\n",
12436 bgp
->distance_ebgp
[afi
][safi
],
12437 bgp
->distance_ibgp
[afi
][safi
],
12438 bgp
->distance_local
[afi
][safi
]);
12441 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12442 rn
= bgp_route_next(rn
)) {
12443 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12444 if (bdistance
!= NULL
) {
12445 char buf
[PREFIX_STRLEN
];
12447 vty_out(vty
, " distance %d %s %s\n",
12448 bdistance
->distance
,
12449 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12450 bdistance
->access_list
? bdistance
->access_list
12456 /* Allocate routing table structure and install commands. */
12457 void bgp_route_init(void)
12462 /* Init BGP distance table. */
12463 FOREACH_AFI_SAFI (afi
, safi
)
12464 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12466 /* IPv4 BGP commands. */
12467 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12468 install_element(BGP_NODE
, &bgp_network_cmd
);
12469 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12471 install_element(BGP_NODE
, &aggregate_address_cmd
);
12472 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12473 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12474 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12476 /* IPv4 unicast configuration. */
12477 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12478 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12479 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12481 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12482 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12483 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12484 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12486 /* IPv4 multicast configuration. */
12487 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12488 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12489 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12490 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12491 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12492 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12493 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12495 /* IPv4 labeled-unicast configuration. */
12496 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12497 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12498 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12499 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12500 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12502 install_element(VIEW_NODE
,
12503 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12504 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12505 install_element(VIEW_NODE
,
12506 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12507 #ifdef KEEP_OLD_VPN_COMMANDS
12508 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12509 #endif /* KEEP_OLD_VPN_COMMANDS */
12510 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12511 install_element(VIEW_NODE
,
12512 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
12514 /* BGP dampening clear commands */
12515 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12516 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12518 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12519 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12522 install_element(ENABLE_NODE
,
12523 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12524 #ifdef KEEP_OLD_VPN_COMMANDS
12525 install_element(ENABLE_NODE
,
12526 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12527 #endif /* KEEP_OLD_VPN_COMMANDS */
12529 /* New config IPv6 BGP commands. */
12530 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12531 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12532 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12534 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12535 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12537 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12539 install_element(BGP_NODE
, &bgp_distance_cmd
);
12540 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12541 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12542 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12543 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12544 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12545 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12546 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12547 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12548 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12549 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12550 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12551 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12552 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12553 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12554 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12555 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12556 install_element(BGP_IPV4M_NODE
,
12557 &no_bgp_distance_source_access_list_cmd
);
12558 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12559 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12560 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12561 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12562 install_element(BGP_IPV6_NODE
,
12563 &ipv6_bgp_distance_source_access_list_cmd
);
12564 install_element(BGP_IPV6_NODE
,
12565 &no_ipv6_bgp_distance_source_access_list_cmd
);
12566 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12567 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12568 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12569 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12570 install_element(BGP_IPV6M_NODE
,
12571 &ipv6_bgp_distance_source_access_list_cmd
);
12572 install_element(BGP_IPV6M_NODE
,
12573 &no_ipv6_bgp_distance_source_access_list_cmd
);
12575 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12576 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12577 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12578 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12580 /* IPv4 Multicast Mode */
12581 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12582 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12584 /* Large Communities */
12585 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12586 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12588 /* show bgp ipv4 flowspec detailed */
12589 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12591 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12594 void bgp_route_finish(void)
12599 FOREACH_AFI_SAFI (afi
, safi
) {
12600 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12601 bgp_distance_table
[afi
][safi
] = NULL
;