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 DEFINE_HOOK(bgp_process
,
111 (struct bgp
*bgp
, afi_t afi
, safi_t safi
,
112 struct bgp_node
*bn
, struct peer
*peer
, bool withdraw
),
113 (bgp
, afi
, safi
, bn
, peer
, withdraw
))
116 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
117 safi_t safi
, struct prefix
*p
,
118 struct prefix_rd
*prd
)
121 struct bgp_node
*prn
= NULL
;
127 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
128 || (safi
== SAFI_EVPN
)) {
129 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
131 if (!bgp_node_has_bgp_path_info_data(prn
))
132 bgp_node_set_bgp_table_info(
133 prn
, bgp_table_init(table
->bgp
, afi
, safi
));
135 bgp_unlock_node(prn
);
136 table
= bgp_node_get_bgp_table_info(prn
);
139 rn
= bgp_node_get(table
, p
);
141 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
142 || (safi
== SAFI_EVPN
))
148 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
149 safi_t safi
, struct prefix
*p
,
150 struct prefix_rd
*prd
)
153 struct bgp_node
*prn
= NULL
;
158 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
159 || (safi
== SAFI_EVPN
)) {
160 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
164 if (!bgp_node_has_bgp_path_info_data(prn
)) {
165 bgp_unlock_node(prn
);
169 table
= bgp_node_get_bgp_table_info(prn
);
172 rn
= bgp_node_lookup(table
, p
);
177 /* Allocate bgp_path_info_extra */
178 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
180 struct bgp_path_info_extra
*new;
181 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
182 sizeof(struct bgp_path_info_extra
));
183 new->label
[0] = MPLS_INVALID_LABEL
;
185 new->bgp_fs_pbr
= NULL
;
186 new->bgp_fs_iprule
= NULL
;
190 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
192 struct bgp_path_info_extra
*e
;
194 if (!extra
|| !*extra
)
199 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
204 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
207 /* FIXME: since multiple e may have the same e->parent
208 * and e->parent->net is holding a refcount for each
209 * of them, we need to do some fudging here.
211 * WARNING: if bpi->net->lock drops to 0, bpi may be
212 * freed as well (because bpi->net was holding the
213 * last reference to bpi) => write after free!
217 bpi
= bgp_path_info_lock(bpi
);
218 refcount
= bpi
->net
->lock
- 1;
219 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
222 bgp_path_info_unlock(bpi
);
224 bgp_path_info_unlock(e
->parent
);
229 bgp_unlock(e
->bgp_orig
);
231 if ((*extra
)->bgp_fs_iprule
)
232 list_delete(&((*extra
)->bgp_fs_iprule
));
233 if ((*extra
)->bgp_fs_pbr
)
234 list_delete(&((*extra
)->bgp_fs_pbr
));
235 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
240 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
241 * allocated if required.
243 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
246 pi
->extra
= bgp_path_info_extra_new();
250 /* Free bgp route information. */
251 static void bgp_path_info_free(struct bgp_path_info
*path
)
253 bgp_attr_unintern(&path
->attr
);
255 bgp_unlink_nexthop(path
);
256 bgp_path_info_extra_free(&path
->extra
);
257 bgp_path_info_mpath_free(&path
->mpath
);
259 bgp_addpath_free_info_data(&path
->tx_addpath
,
260 &path
->net
->tx_addpath
);
262 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
264 XFREE(MTYPE_BGP_ROUTE
, path
);
267 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
273 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
275 assert(path
&& path
->lock
> 0);
278 if (path
->lock
== 0) {
280 zlog_debug ("%s: unlocked and freeing", __func__
);
281 zlog_backtrace (LOG_DEBUG
);
283 bgp_path_info_free(path
);
290 zlog_debug ("%s: unlocked to 1", __func__
);
291 zlog_backtrace (LOG_DEBUG
);
298 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
300 struct bgp_path_info
*top
;
302 top
= bgp_node_get_bgp_path_info(rn
);
308 bgp_node_set_bgp_path_info(rn
, pi
);
310 bgp_path_info_lock(pi
);
312 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
315 /* Do the actual removal of info from RIB, for use by bgp_process
316 completion callback *only* */
317 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
320 pi
->next
->prev
= pi
->prev
;
322 pi
->prev
->next
= pi
->next
;
324 bgp_node_set_bgp_path_info(rn
, pi
->next
);
326 bgp_path_info_mpath_dequeue(pi
);
327 bgp_path_info_unlock(pi
);
331 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
333 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
334 /* set of previous already took care of pcount */
335 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
338 /* undo the effects of a previous call to bgp_path_info_delete; typically
339 called when a route is deleted and then quickly re-added before the
340 deletion has been processed */
341 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
343 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
344 /* unset of previous already took care of pcount */
345 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
348 /* Adjust pcount as required */
349 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
351 struct bgp_table
*table
;
353 assert(rn
&& bgp_node_table(rn
));
354 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
356 table
= bgp_node_table(rn
);
358 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
361 if (!BGP_PATH_COUNTABLE(pi
)
362 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
364 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
366 /* slight hack, but more robust against errors. */
367 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
368 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
370 flog_err(EC_LIB_DEVELOPMENT
,
371 "Asked to decrement 0 prefix count for peer");
372 } else if (BGP_PATH_COUNTABLE(pi
)
373 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
374 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
375 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
379 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
380 struct bgp_path_info
*pi2
)
382 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
385 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
386 * This is here primarily to keep prefix-count in check.
388 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
391 SET_FLAG(pi
->flags
, flag
);
393 /* early bath if we know it's not a flag that changes countability state
395 if (!CHECK_FLAG(flag
,
396 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
399 bgp_pcount_adjust(rn
, pi
);
402 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
405 UNSET_FLAG(pi
->flags
, flag
);
407 /* early bath if we know it's not a flag that changes countability state
409 if (!CHECK_FLAG(flag
,
410 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
413 bgp_pcount_adjust(rn
, pi
);
416 /* Get MED value. If MED value is missing and "bgp bestpath
417 missing-as-worst" is specified, treat it as the worst value. */
418 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
420 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
423 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
430 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
432 if (pi
->addpath_rx_id
)
433 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
436 sprintf(buf
, "path %s", pi
->peer
->host
);
439 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
441 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
442 struct bgp_path_info
*exist
, int *paths_eq
,
443 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
444 char *pfx_buf
, afi_t afi
, safi_t safi
,
445 enum bgp_path_selection_reason
*reason
)
447 struct attr
*newattr
, *existattr
;
448 bgp_peer_sort_t new_sort
;
449 bgp_peer_sort_t exist_sort
;
455 uint32_t exist_weight
;
456 uint32_t newm
, existm
;
457 struct in_addr new_id
;
458 struct in_addr exist_id
;
461 int internal_as_route
;
464 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
465 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
467 uint32_t exist_mm_seq
;
474 *reason
= bgp_path_selection_none
;
476 zlog_debug("%s: new is NULL", pfx_buf
);
481 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
484 *reason
= bgp_path_selection_first
;
486 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
492 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
493 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
494 pfx_buf
, new_buf
, new->flags
, exist_buf
,
499 existattr
= exist
->attr
;
501 /* For EVPN routes, we cannot just go by local vs remote, we have to
502 * look at the MAC mobility sequence number, if present.
504 if (safi
== SAFI_EVPN
) {
505 /* This is an error condition described in RFC 7432 Section
507 * states that in this scenario "the PE MUST alert the operator"
509 * does not state what other action to take. In order to provide
511 * consistency in this scenario we are going to prefer the path
515 if (newattr
->sticky
!= existattr
->sticky
) {
517 prefix2str(&new->net
->p
, pfx_buf
,
519 * PREFIX2STR_BUFFER
);
520 bgp_path_info_path_with_addpath_rx_str(new,
522 bgp_path_info_path_with_addpath_rx_str(
526 if (newattr
->sticky
&& !existattr
->sticky
) {
527 *reason
= bgp_path_selection_evpn_sticky_mac
;
530 "%s: %s wins over %s due to sticky MAC flag",
531 pfx_buf
, new_buf
, exist_buf
);
535 if (!newattr
->sticky
&& existattr
->sticky
) {
536 *reason
= bgp_path_selection_evpn_sticky_mac
;
539 "%s: %s loses to %s due to sticky MAC flag",
540 pfx_buf
, new_buf
, exist_buf
);
545 new_mm_seq
= mac_mobility_seqnum(newattr
);
546 exist_mm_seq
= mac_mobility_seqnum(existattr
);
548 if (new_mm_seq
> exist_mm_seq
) {
549 *reason
= bgp_path_selection_evpn_seq
;
552 "%s: %s wins over %s due to MM seq %u > %u",
553 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
558 if (new_mm_seq
< exist_mm_seq
) {
559 *reason
= bgp_path_selection_evpn_seq
;
562 "%s: %s loses to %s due to MM seq %u < %u",
563 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
569 * if sequence numbers are the same path with the lowest IP
572 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
574 *reason
= bgp_path_selection_evpn_lower_ip
;
577 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
578 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
579 inet_ntoa(new->attr
->nexthop
));
583 *reason
= bgp_path_selection_evpn_lower_ip
;
586 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
587 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
588 inet_ntoa(new->attr
->nexthop
));
593 /* 1. Weight check. */
594 new_weight
= newattr
->weight
;
595 exist_weight
= existattr
->weight
;
597 if (new_weight
> exist_weight
) {
598 *reason
= bgp_path_selection_weight
;
600 zlog_debug("%s: %s wins over %s due to weight %d > %d",
601 pfx_buf
, new_buf
, exist_buf
, new_weight
,
606 if (new_weight
< exist_weight
) {
607 *reason
= bgp_path_selection_weight
;
609 zlog_debug("%s: %s loses to %s due to weight %d < %d",
610 pfx_buf
, new_buf
, exist_buf
, new_weight
,
615 /* 2. Local preference check. */
616 new_pref
= exist_pref
= bgp
->default_local_pref
;
618 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
619 new_pref
= newattr
->local_pref
;
620 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
621 exist_pref
= existattr
->local_pref
;
623 if (new_pref
> exist_pref
) {
624 *reason
= bgp_path_selection_local_pref
;
627 "%s: %s wins over %s due to localpref %d > %d",
628 pfx_buf
, new_buf
, exist_buf
, new_pref
,
633 if (new_pref
< exist_pref
) {
634 *reason
= bgp_path_selection_local_pref
;
637 "%s: %s loses to %s due to localpref %d < %d",
638 pfx_buf
, new_buf
, exist_buf
, new_pref
,
643 /* 3. Local route check. We prefer:
645 * - BGP_ROUTE_AGGREGATE
646 * - BGP_ROUTE_REDISTRIBUTE
648 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
649 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
650 *reason
= bgp_path_selection_local_route
;
653 "%s: %s wins over %s due to preferred BGP_ROUTE type",
654 pfx_buf
, new_buf
, exist_buf
);
658 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
659 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
660 *reason
= bgp_path_selection_local_route
;
663 "%s: %s loses to %s due to preferred BGP_ROUTE type",
664 pfx_buf
, new_buf
, exist_buf
);
668 /* 4. AS path length check. */
669 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
670 int exist_hops
= aspath_count_hops(existattr
->aspath
);
671 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
673 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
676 aspath_hops
= aspath_count_hops(newattr
->aspath
);
677 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
679 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
680 *reason
= bgp_path_selection_confed_as_path
;
683 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
684 pfx_buf
, new_buf
, exist_buf
,
686 (exist_hops
+ exist_confeds
));
690 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
691 *reason
= bgp_path_selection_confed_as_path
;
694 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
695 pfx_buf
, new_buf
, exist_buf
,
697 (exist_hops
+ exist_confeds
));
701 int newhops
= aspath_count_hops(newattr
->aspath
);
703 if (newhops
< exist_hops
) {
704 *reason
= bgp_path_selection_as_path
;
707 "%s: %s wins over %s due to aspath hopcount %d < %d",
708 pfx_buf
, new_buf
, exist_buf
,
709 newhops
, exist_hops
);
713 if (newhops
> exist_hops
) {
714 *reason
= bgp_path_selection_as_path
;
717 "%s: %s loses to %s due to aspath hopcount %d > %d",
718 pfx_buf
, new_buf
, exist_buf
,
719 newhops
, exist_hops
);
725 /* 5. Origin check. */
726 if (newattr
->origin
< existattr
->origin
) {
727 *reason
= bgp_path_selection_origin
;
729 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
730 pfx_buf
, new_buf
, exist_buf
,
731 bgp_origin_long_str
[newattr
->origin
],
732 bgp_origin_long_str
[existattr
->origin
]);
736 if (newattr
->origin
> existattr
->origin
) {
737 *reason
= bgp_path_selection_origin
;
739 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
740 pfx_buf
, new_buf
, exist_buf
,
741 bgp_origin_long_str
[newattr
->origin
],
742 bgp_origin_long_str
[existattr
->origin
]);
747 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
748 && aspath_count_hops(existattr
->aspath
) == 0);
749 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
750 && aspath_count_confeds(existattr
->aspath
) > 0
751 && aspath_count_hops(newattr
->aspath
) == 0
752 && aspath_count_hops(existattr
->aspath
) == 0);
754 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
755 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
756 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
757 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
758 || internal_as_route
) {
759 new_med
= bgp_med_value(new->attr
, bgp
);
760 exist_med
= bgp_med_value(exist
->attr
, bgp
);
762 if (new_med
< exist_med
) {
763 *reason
= bgp_path_selection_med
;
766 "%s: %s wins over %s due to MED %d < %d",
767 pfx_buf
, new_buf
, exist_buf
, new_med
,
772 if (new_med
> exist_med
) {
773 *reason
= bgp_path_selection_med
;
776 "%s: %s loses to %s due to MED %d > %d",
777 pfx_buf
, new_buf
, exist_buf
, new_med
,
783 /* 7. Peer type check. */
784 new_sort
= new->peer
->sort
;
785 exist_sort
= exist
->peer
->sort
;
787 if (new_sort
== BGP_PEER_EBGP
788 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
789 *reason
= bgp_path_selection_peer
;
792 "%s: %s wins over %s due to eBGP peer > iBGP peer",
793 pfx_buf
, new_buf
, exist_buf
);
797 if (exist_sort
== BGP_PEER_EBGP
798 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
799 *reason
= bgp_path_selection_peer
;
802 "%s: %s loses to %s due to iBGP peer < eBGP peer",
803 pfx_buf
, new_buf
, exist_buf
);
807 /* 8. IGP metric check. */
811 newm
= new->extra
->igpmetric
;
813 existm
= exist
->extra
->igpmetric
;
818 "%s: %s wins over %s due to IGP metric %d < %d",
819 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
826 "%s: %s loses to %s due to IGP metric %d > %d",
827 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
831 /* 9. Same IGP metric. Compare the cluster list length as
832 representative of IGP hops metric. Rewrite the metric value
833 pair (newm, existm) with the cluster list length. Prefer the
834 path with smaller cluster list length. */
835 if (newm
== existm
) {
836 if (peer_sort(new->peer
) == BGP_PEER_IBGP
837 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
838 && (mpath_cfg
== NULL
840 mpath_cfg
->ibgp_flags
,
841 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
842 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
843 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
848 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
849 pfx_buf
, new_buf
, exist_buf
,
857 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
858 pfx_buf
, new_buf
, exist_buf
,
865 /* 10. confed-external vs. confed-internal */
866 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
867 if (new_sort
== BGP_PEER_CONFED
868 && exist_sort
== BGP_PEER_IBGP
) {
869 *reason
= bgp_path_selection_confed
;
872 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
873 pfx_buf
, new_buf
, exist_buf
);
877 if (exist_sort
== BGP_PEER_CONFED
878 && new_sort
== BGP_PEER_IBGP
) {
879 *reason
= bgp_path_selection_confed
;
882 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
883 pfx_buf
, new_buf
, exist_buf
);
888 /* 11. Maximum path check. */
889 if (newm
== existm
) {
890 /* If one path has a label but the other does not, do not treat
891 * them as equals for multipath
893 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
895 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
898 "%s: %s and %s cannot be multipath, one has a label while the other does not",
899 pfx_buf
, new_buf
, exist_buf
);
900 } else if (bgp_flag_check(bgp
,
901 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
904 * For the two paths, all comparison steps till IGP
906 * have succeeded - including AS_PATH hop count. Since
908 * bestpath as-path multipath-relax' knob is on, we
910 * an exact match of AS_PATH. Thus, mark the paths are
912 * That will trigger both these paths to get into the
920 "%s: %s and %s are equal via multipath-relax",
921 pfx_buf
, new_buf
, exist_buf
);
922 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
923 if (aspath_cmp(new->attr
->aspath
,
924 exist
->attr
->aspath
)) {
929 "%s: %s and %s are equal via matching aspaths",
930 pfx_buf
, new_buf
, exist_buf
);
932 } else if (new->peer
->as
== exist
->peer
->as
) {
937 "%s: %s and %s are equal via same remote-as",
938 pfx_buf
, new_buf
, exist_buf
);
942 * TODO: If unequal cost ibgp multipath is enabled we can
943 * mark the paths as equal here instead of returning
948 "%s: %s wins over %s after IGP metric comparison",
949 pfx_buf
, new_buf
, exist_buf
);
952 "%s: %s loses to %s after IGP metric comparison",
953 pfx_buf
, new_buf
, exist_buf
);
955 *reason
= bgp_path_selection_igp_metric
;
959 /* 12. If both paths are external, prefer the path that was received
960 first (the oldest one). This step minimizes route-flap, since a
961 newer path won't displace an older one, even if it was the
962 preferred route based on the additional decision criteria below. */
963 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
964 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
965 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
966 *reason
= bgp_path_selection_older
;
969 "%s: %s wins over %s due to oldest external",
970 pfx_buf
, new_buf
, exist_buf
);
974 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
975 *reason
= bgp_path_selection_older
;
978 "%s: %s loses to %s due to oldest external",
979 pfx_buf
, new_buf
, exist_buf
);
984 /* 13. Router-ID comparision. */
985 /* If one of the paths is "stale", the corresponding peer router-id will
986 * be 0 and would always win over the other path. If originator id is
987 * used for the comparision, it will decide which path is better.
989 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
990 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
992 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
993 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
994 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
996 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
998 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
999 *reason
= bgp_path_selection_router_id
;
1002 "%s: %s wins over %s due to Router-ID comparison",
1003 pfx_buf
, new_buf
, exist_buf
);
1007 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1008 *reason
= bgp_path_selection_router_id
;
1011 "%s: %s loses to %s due to Router-ID comparison",
1012 pfx_buf
, new_buf
, exist_buf
);
1016 /* 14. Cluster length comparision. */
1017 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1018 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1020 if (new_cluster
< exist_cluster
) {
1021 *reason
= bgp_path_selection_cluster_length
;
1024 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1025 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1030 if (new_cluster
> exist_cluster
) {
1031 *reason
= bgp_path_selection_cluster_length
;
1034 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1035 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1040 /* 15. Neighbor address comparision. */
1041 /* Do this only if neither path is "stale" as stale paths do not have
1042 * valid peer information (as the connection may or may not be up).
1044 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1045 *reason
= bgp_path_selection_stale
;
1048 "%s: %s wins over %s due to latter path being STALE",
1049 pfx_buf
, new_buf
, exist_buf
);
1053 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1054 *reason
= bgp_path_selection_stale
;
1057 "%s: %s loses to %s due to former path being STALE",
1058 pfx_buf
, new_buf
, exist_buf
);
1062 /* locally configured routes to advertise do not have su_remote */
1063 if (new->peer
->su_remote
== NULL
) {
1064 *reason
= bgp_path_selection_local_configured
;
1067 if (exist
->peer
->su_remote
== NULL
) {
1068 *reason
= bgp_path_selection_local_configured
;
1072 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1075 *reason
= bgp_path_selection_neighbor_ip
;
1078 "%s: %s loses to %s due to Neighor IP comparison",
1079 pfx_buf
, new_buf
, exist_buf
);
1084 *reason
= bgp_path_selection_neighbor_ip
;
1087 "%s: %s wins over %s due to Neighor IP comparison",
1088 pfx_buf
, new_buf
, exist_buf
);
1092 *reason
= bgp_path_selection_default
;
1094 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1095 pfx_buf
, new_buf
, exist_buf
);
1100 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1101 * is preferred, or 0 if they are the same (usually will only occur if
1102 * multipath is enabled
1103 * This version is compatible with */
1104 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1105 struct bgp_path_info
*exist
, char *pfx_buf
,
1106 afi_t afi
, safi_t safi
,
1107 enum bgp_path_selection_reason
*reason
)
1111 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1125 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1126 struct attr
*attr
, afi_t afi
,
1129 struct bgp_filter
*filter
;
1131 filter
= &peer
->filter
[afi
][safi
];
1133 #define FILTER_EXIST_WARN(F, f, filter) \
1134 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1135 zlog_debug("%s: Could not find configured input %s-list %s!", \
1136 peer->host, #f, F##_IN_NAME(filter));
1138 if (DISTRIBUTE_IN_NAME(filter
)) {
1139 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1141 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1145 if (PREFIX_LIST_IN_NAME(filter
)) {
1146 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1148 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1152 if (FILTER_LIST_IN_NAME(filter
)) {
1153 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1155 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1160 return FILTER_PERMIT
;
1161 #undef FILTER_EXIST_WARN
1164 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1165 struct attr
*attr
, afi_t afi
,
1168 struct bgp_filter
*filter
;
1170 filter
= &peer
->filter
[afi
][safi
];
1172 #define FILTER_EXIST_WARN(F, f, filter) \
1173 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1174 zlog_debug("%s: Could not find configured output %s-list %s!", \
1175 peer->host, #f, F##_OUT_NAME(filter));
1177 if (DISTRIBUTE_OUT_NAME(filter
)) {
1178 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1180 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1184 if (PREFIX_LIST_OUT_NAME(filter
)) {
1185 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1187 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1192 if (FILTER_LIST_OUT_NAME(filter
)) {
1193 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1195 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1200 return FILTER_PERMIT
;
1201 #undef FILTER_EXIST_WARN
1204 /* If community attribute includes no_export then return 1. */
1205 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1207 if (attr
->community
) {
1208 /* NO_ADVERTISE check. */
1209 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1212 /* NO_EXPORT check. */
1213 if (peer
->sort
== BGP_PEER_EBGP
1214 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1217 /* NO_EXPORT_SUBCONFED check. */
1218 if (peer
->sort
== BGP_PEER_EBGP
1219 || peer
->sort
== BGP_PEER_CONFED
)
1220 if (community_include(attr
->community
,
1221 COMMUNITY_NO_EXPORT_SUBCONFED
))
1227 /* Route reflection loop check. */
1228 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1230 struct in_addr cluster_id
;
1232 if (attr
->cluster
) {
1233 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1234 cluster_id
= peer
->bgp
->cluster_id
;
1236 cluster_id
= peer
->bgp
->router_id
;
1238 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1244 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1245 struct attr
*attr
, afi_t afi
, safi_t safi
,
1246 const char *rmap_name
, mpls_label_t
*label
,
1247 uint32_t num_labels
, struct bgp_node
*rn
)
1249 struct bgp_filter
*filter
;
1250 struct bgp_path_info rmap_path
= { 0 };
1251 struct bgp_path_info_extra extra
= { 0 };
1252 route_map_result_t ret
;
1253 struct route_map
*rmap
= NULL
;
1255 filter
= &peer
->filter
[afi
][safi
];
1257 /* Apply default weight value. */
1258 if (peer
->weight
[afi
][safi
])
1259 attr
->weight
= peer
->weight
[afi
][safi
];
1262 rmap
= route_map_lookup_by_name(rmap_name
);
1267 if (ROUTE_MAP_IN_NAME(filter
)) {
1268 rmap
= ROUTE_MAP_IN(filter
);
1275 /* Route map apply. */
1277 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1278 /* Duplicate current value to new strucutre for modification. */
1279 rmap_path
.peer
= peer
;
1280 rmap_path
.attr
= attr
;
1281 rmap_path
.extra
= &extra
;
1284 extra
.num_labels
= num_labels
;
1285 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1286 memcpy(extra
.label
, label
,
1287 num_labels
* sizeof(mpls_label_t
));
1289 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1291 /* Apply BGP route map to the attribute. */
1292 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1294 peer
->rmap_type
= 0;
1296 if (ret
== RMAP_DENYMATCH
)
1302 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1303 struct attr
*attr
, afi_t afi
, safi_t safi
,
1304 const char *rmap_name
)
1306 struct bgp_path_info rmap_path
;
1307 route_map_result_t ret
;
1308 struct route_map
*rmap
= NULL
;
1312 * So if we get to this point and have no rmap_name
1313 * we want to just show the output as it currently
1319 /* Apply default weight value. */
1320 if (peer
->weight
[afi
][safi
])
1321 attr
->weight
= peer
->weight
[afi
][safi
];
1323 rmap
= route_map_lookup_by_name(rmap_name
);
1326 * If we have a route map name and we do not find
1327 * the routemap that means we have an implicit
1333 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1334 /* Route map apply. */
1335 /* Duplicate current value to new strucutre for modification. */
1336 rmap_path
.peer
= peer
;
1337 rmap_path
.attr
= attr
;
1339 rmap_type
= peer
->rmap_type
;
1340 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1342 /* Apply BGP route map to the attribute. */
1343 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1345 peer
->rmap_type
= rmap_type
;
1347 if (ret
== RMAP_DENYMATCH
)
1349 * caller has multiple error paths with bgp_attr_flush()
1356 /* If this is an EBGP peer with remove-private-AS */
1357 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1358 struct peer
*peer
, struct attr
*attr
)
1360 if (peer
->sort
== BGP_PEER_EBGP
1361 && (peer_af_flag_check(peer
, afi
, safi
,
1362 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1363 || peer_af_flag_check(peer
, afi
, safi
,
1364 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1365 || peer_af_flag_check(peer
, afi
, safi
,
1366 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1367 || peer_af_flag_check(peer
, afi
, safi
,
1368 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1369 // Take action on the entire aspath
1370 if (peer_af_flag_check(peer
, afi
, safi
,
1371 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1372 || peer_af_flag_check(peer
, afi
, safi
,
1373 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1374 if (peer_af_flag_check(
1376 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1377 attr
->aspath
= aspath_replace_private_asns(
1378 attr
->aspath
, bgp
->as
, peer
->as
);
1380 // The entire aspath consists of private ASNs so create
1382 else if (aspath_private_as_check(attr
->aspath
))
1383 attr
->aspath
= aspath_empty_get();
1385 // There are some public and some private ASNs, remove
1388 attr
->aspath
= aspath_remove_private_asns(
1389 attr
->aspath
, peer
->as
);
1392 // 'all' was not specified so the entire aspath must be private
1394 // for us to do anything
1395 else if (aspath_private_as_check(attr
->aspath
)) {
1396 if (peer_af_flag_check(
1398 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1399 attr
->aspath
= aspath_replace_private_asns(
1400 attr
->aspath
, bgp
->as
, peer
->as
);
1402 attr
->aspath
= aspath_empty_get();
1407 /* If this is an EBGP peer with as-override */
1408 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1409 struct peer
*peer
, struct attr
*attr
)
1411 if (peer
->sort
== BGP_PEER_EBGP
1412 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1413 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1414 attr
->aspath
= aspath_replace_specific_asn(
1415 attr
->aspath
, peer
->as
, bgp
->as
);
1419 void bgp_attr_add_gshut_community(struct attr
*attr
)
1421 struct community
*old
;
1422 struct community
*new;
1423 struct community
*merge
;
1424 struct community
*gshut
;
1426 old
= attr
->community
;
1427 gshut
= community_str2com("graceful-shutdown");
1432 merge
= community_merge(community_dup(old
), gshut
);
1434 if (old
->refcnt
== 0)
1435 community_free(&old
);
1437 new = community_uniq_sort(merge
);
1438 community_free(&merge
);
1440 new = community_dup(gshut
);
1443 community_free(&gshut
);
1444 attr
->community
= new;
1445 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1447 /* When we add the graceful-shutdown community we must also
1448 * lower the local-preference */
1449 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1450 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1454 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1456 if (family
== AF_INET
) {
1457 attr
->nexthop
.s_addr
= 0;
1458 attr
->mp_nexthop_global_in
.s_addr
= 0;
1460 if (family
== AF_INET6
)
1461 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1462 if (family
== AF_EVPN
)
1463 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1466 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1467 struct update_subgroup
*subgrp
, struct prefix
*p
,
1470 struct bgp_filter
*filter
;
1473 struct peer
*onlypeer
;
1475 struct attr
*piattr
;
1476 char buf
[PREFIX_STRLEN
];
1477 route_map_result_t ret
;
1482 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1484 if (DISABLE_BGP_ANNOUNCE
)
1487 afi
= SUBGRP_AFI(subgrp
);
1488 safi
= SUBGRP_SAFI(subgrp
);
1489 peer
= SUBGRP_PEER(subgrp
);
1491 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1492 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1495 filter
= &peer
->filter
[afi
][safi
];
1496 bgp
= SUBGRP_INST(subgrp
);
1497 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1501 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1502 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1503 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1506 * direct and direct_ext type routes originate internally even
1507 * though they can have peer pointers that reference other
1510 prefix2str(p
, buf
, PREFIX_STRLEN
);
1511 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1517 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1518 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1519 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1520 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1522 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1527 /* With addpath we may be asked to TX all kinds of paths so make sure
1529 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1530 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1531 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1535 /* If this is not the bestpath then check to see if there is an enabled
1537 * feature that requires us to advertise it */
1538 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1539 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1544 /* Aggregate-address suppress check. */
1545 if (pi
->extra
&& pi
->extra
->suppress
)
1546 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1551 * If we are doing VRF 2 VRF leaking via the import
1552 * statement, we want to prevent the route going
1553 * off box as that the RT and RD created are localy
1554 * significant and globaly useless.
1556 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1557 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1560 /* If it's labeled safi, make sure the route has a valid label. */
1561 if (safi
== SAFI_LABELED_UNICAST
) {
1562 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1563 if (!bgp_is_valid_label(&label
)) {
1564 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1565 zlog_debug("u%" PRIu64
":s%" PRIu64
1566 " %s/%d is filtered - no label (%p)",
1567 subgrp
->update_group
->id
, subgrp
->id
,
1568 inet_ntop(p
->family
, &p
->u
.prefix
,
1569 buf
, SU_ADDRSTRLEN
),
1570 p
->prefixlen
, &label
);
1575 /* Do not send back route to sender. */
1576 if (onlypeer
&& from
== onlypeer
) {
1580 /* Do not send the default route in the BGP table if the neighbor is
1581 * configured for default-originate */
1582 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1583 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1584 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1586 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1590 /* Transparency check. */
1591 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1592 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1597 /* If community is not disabled check the no-export and local. */
1598 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1599 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1601 "subgrpannouncecheck: community filter check fail");
1605 /* If the attribute has originator-id and it is same as remote
1607 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1608 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1609 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1611 "%s [Update:SEND] %s originator-id is same as "
1614 prefix2str(p
, buf
, sizeof(buf
)));
1618 /* ORF prefix-list filter check */
1619 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1620 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1621 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1622 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1623 if (peer
->orf_plist
[afi
][safi
]) {
1624 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1626 if (bgp_debug_update(NULL
, p
,
1627 subgrp
->update_group
, 0))
1629 "%s [Update:SEND] %s is filtered via ORF",
1637 /* Output filter check. */
1638 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1639 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1640 zlog_debug("%s [Update:SEND] %s is filtered",
1641 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1645 /* AS path loop check. */
1646 if (onlypeer
&& onlypeer
->as_path_loop_detection
1647 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1648 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1650 "%s [Update:SEND] suppress announcement to peer AS %u "
1651 "that is part of AS path.",
1652 onlypeer
->host
, onlypeer
->as
);
1656 /* If we're a CONFED we need to loop check the CONFED ID too */
1657 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1658 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1659 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1661 "%s [Update:SEND] suppress announcement to peer AS %u"
1663 peer
->host
, bgp
->confed_id
);
1668 /* Route-Reflect check. */
1669 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1674 /* IBGP reflection check. */
1675 if (reflect
&& !samepeer_safe
) {
1676 /* A route from a Client peer. */
1677 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1678 PEER_FLAG_REFLECTOR_CLIENT
)) {
1679 /* Reflect to all the Non-Client peers and also to the
1680 Client peers other than the originator. Originator
1682 is already done. So there is noting to do. */
1683 /* no bgp client-to-client reflection check. */
1684 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1685 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1686 PEER_FLAG_REFLECTOR_CLIENT
))
1689 /* A route from a Non-client peer. Reflect to all other
1691 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1692 PEER_FLAG_REFLECTOR_CLIENT
))
1697 /* For modify attribute, copy it to temporary structure. */
1700 /* If local-preference is not set. */
1701 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1702 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1703 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1704 attr
->local_pref
= bgp
->default_local_pref
;
1707 /* If originator-id is not set and the route is to be reflected,
1708 set the originator id */
1710 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1711 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1712 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1715 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1717 if (peer
->sort
== BGP_PEER_EBGP
1718 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1719 if (from
!= bgp
->peer_self
&& !transparent
1720 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1721 PEER_FLAG_MED_UNCHANGED
))
1723 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1726 /* Since the nexthop attribute can vary per peer, it is not explicitly
1728 * in announce check, only certain flags and length (or number of
1730 * -- for IPv6/MP_REACH) are set here in order to guide the update
1732 * code in setting the nexthop(s) on a per peer basis in
1734 * Typically, the source nexthop in the attribute is preserved but in
1736 * scenarios where we know it will always be overwritten, we reset the
1737 * nexthop to "0" in an attempt to achieve better Update packing. An
1738 * example of this is when a prefix from each of 2 IBGP peers needs to
1740 * announced to an EBGP peer (and they have the same attributes barring
1744 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1746 #define NEXTHOP_IS_V6 \
1747 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1748 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1749 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1750 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1752 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1754 * the peer (group) is configured to receive link-local nexthop
1756 * and it is available in the prefix OR we're not reflecting the route,
1757 * link-local nexthop address is valid and
1758 * the peer (group) to whom we're going to announce is on a shared
1760 * and this is either a self-originated route or the peer is EBGP.
1761 * By checking if nexthop LL address is valid we are sure that
1762 * we do not announce LL address as `::`.
1764 if (NEXTHOP_IS_V6
) {
1765 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1766 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1767 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1768 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1770 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
1771 && peer
->shared_network
1772 && (from
== bgp
->peer_self
1773 || peer
->sort
== BGP_PEER_EBGP
))) {
1774 attr
->mp_nexthop_len
=
1775 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1778 /* Clear off link-local nexthop in source, whenever it is not
1780 * ensure more prefixes share the same attribute for
1783 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1784 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1785 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1788 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1789 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1791 /* Route map & unsuppress-map apply. */
1792 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1793 struct bgp_path_info rmap_path
= {0};
1794 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
1795 struct attr dummy_attr
= {0};
1797 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1798 rmap_path
.peer
= peer
;
1799 rmap_path
.attr
= attr
;
1803 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1804 sizeof(struct bgp_path_info_extra
));
1805 rmap_path
.extra
= &dummy_rmap_path_extra
;
1808 /* don't confuse inbound and outbound setting */
1809 RESET_FLAG(attr
->rmap_change_flags
);
1812 * The route reflector is not allowed to modify the attributes
1813 * of the reflected IBGP routes unless explicitly allowed.
1815 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1816 && !bgp_flag_check(bgp
,
1817 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1819 rmap_path
.attr
= &dummy_attr
;
1822 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1824 if (pi
->extra
&& pi
->extra
->suppress
)
1825 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1826 RMAP_BGP
, &rmap_path
);
1828 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1829 RMAP_BGP
, &rmap_path
);
1831 peer
->rmap_type
= 0;
1833 if (ret
== RMAP_DENYMATCH
) {
1834 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1835 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1836 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1838 bgp_attr_flush(attr
);
1843 /* RFC 8212 to prevent route leaks.
1844 * This specification intends to improve this situation by requiring the
1845 * explicit configuration of both BGP Import and Export Policies for any
1846 * External BGP (EBGP) session such as customers, peers, or
1847 * confederation boundaries for all enabled address families. Through
1848 * codification of the aforementioned requirement, operators will
1849 * benefit from consistent behavior across different BGP
1852 if (peer
->bgp
->ebgp_requires_policy
1853 == DEFAULT_EBGP_POLICY_ENABLED
)
1854 if (!bgp_outbound_policy_exists(peer
, filter
))
1857 /* draft-ietf-idr-deprecate-as-set-confed-set
1858 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1859 * Eventually, This document (if approved) updates RFC 4271
1860 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1861 * and obsoletes RFC 6472.
1863 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
1864 if (aspath_check_as_sets(attr
->aspath
))
1867 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1868 if (peer
->sort
== BGP_PEER_IBGP
1869 || peer
->sort
== BGP_PEER_CONFED
) {
1870 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1871 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1873 bgp_attr_add_gshut_community(attr
);
1877 /* After route-map has been applied, we check to see if the nexthop to
1878 * be carried in the attribute (that is used for the announcement) can
1879 * be cleared off or not. We do this in all cases where we would be
1880 * setting the nexthop to "ourselves". For IPv6, we only need to
1882 * the global nexthop here; the link-local nexthop would have been
1884 * already, and if not, it is required by the update formation code.
1885 * Also see earlier comments in this function.
1888 * If route-map has performed some operation on the nexthop or the peer
1889 * configuration says to pass it unchanged, we cannot reset the nexthop
1890 * here, so only attempt to do it if these aren't true. Note that the
1891 * route-map handler itself might have cleared the nexthop, if for
1893 * it is configured as 'peer-address'.
1895 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1896 piattr
->rmap_change_flags
)
1898 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1899 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1900 /* We can reset the nexthop, if setting (or forcing) it to
1902 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1903 PEER_FLAG_NEXTHOP_SELF
)
1904 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1905 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1907 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1908 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1909 subgroup_announce_reset_nhop(
1910 (peer_cap_enhe(peer
, afi
, safi
)
1914 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1915 /* Can also reset the nexthop if announcing to EBGP, but
1917 * no peer in the subgroup is on a shared subnet.
1918 * Note: 3rd party nexthop currently implemented for
1921 if ((p
->family
== AF_INET
) &&
1922 (!bgp_subgrp_multiaccess_check_v4(
1925 subgroup_announce_reset_nhop(
1926 (peer_cap_enhe(peer
, afi
, safi
)
1931 if ((p
->family
== AF_INET6
) &&
1932 (!bgp_subgrp_multiaccess_check_v6(
1933 piattr
->mp_nexthop_global
,
1935 subgroup_announce_reset_nhop(
1936 (peer_cap_enhe(peer
, afi
, safi
)
1943 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1945 * This flag is used for leaked vpn-vrf routes
1947 int family
= p
->family
;
1949 if (peer_cap_enhe(peer
, afi
, safi
))
1952 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1954 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1955 __func__
, family2str(family
));
1956 subgroup_announce_reset_nhop(family
, attr
);
1960 /* If IPv6/MP and nexthop does not have any override and happens
1962 * be a link-local address, reset it so that we don't pass along
1964 * source's link-local IPv6 address to recipients who may not be
1966 * the same interface.
1968 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1969 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1970 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1976 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1977 struct bgp_maxpaths_cfg
*mpath_cfg
,
1978 struct bgp_path_info_pair
*result
, afi_t afi
,
1981 struct bgp_path_info
*new_select
;
1982 struct bgp_path_info
*old_select
;
1983 struct bgp_path_info
*pi
;
1984 struct bgp_path_info
*pi1
;
1985 struct bgp_path_info
*pi2
;
1986 struct bgp_path_info
*nextpi
= NULL
;
1987 int paths_eq
, do_mpath
, debug
;
1988 struct list mp_list
;
1989 char pfx_buf
[PREFIX2STR_BUFFER
];
1990 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1992 bgp_mp_list_init(&mp_list
);
1994 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1996 debug
= bgp_debug_bestpath(&rn
->p
);
1999 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2001 /* bgp deterministic-med */
2003 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
2005 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2006 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2008 bgp_path_info_unset_flag(rn
, pi1
,
2009 BGP_PATH_DMED_SELECTED
);
2011 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2013 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2015 if (BGP_PATH_HOLDDOWN(pi1
))
2017 if (pi1
->peer
!= bgp
->peer_self
)
2018 if (pi1
->peer
->status
!= Established
)
2023 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2024 if (CHECK_FLAG(pi2
->flags
,
2025 BGP_PATH_DMED_CHECK
))
2027 if (BGP_PATH_HOLDDOWN(pi2
))
2029 if (pi2
->peer
!= bgp
->peer_self
2032 PEER_STATUS_NSF_WAIT
))
2033 if (pi2
->peer
->status
2037 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2039 && !aspath_cmp_left_confed(
2044 if (bgp_path_info_cmp(
2045 bgp
, pi2
, new_select
,
2046 &paths_eq
, mpath_cfg
, debug
,
2049 bgp_path_info_unset_flag(
2051 BGP_PATH_DMED_SELECTED
);
2055 bgp_path_info_set_flag(
2056 rn
, pi2
, BGP_PATH_DMED_CHECK
);
2059 bgp_path_info_set_flag(rn
, new_select
,
2060 BGP_PATH_DMED_CHECK
);
2061 bgp_path_info_set_flag(rn
, new_select
,
2062 BGP_PATH_DMED_SELECTED
);
2065 bgp_path_info_path_with_addpath_rx_str(
2066 new_select
, path_buf
);
2067 zlog_debug("%s: %s is the bestpath from AS %u",
2069 aspath_get_first_as(
2070 new_select
->attr
->aspath
));
2075 /* Check old selected route and new selected route. */
2078 for (pi
= bgp_node_get_bgp_path_info(rn
);
2079 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2080 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2083 if (BGP_PATH_HOLDDOWN(pi
)) {
2084 /* reap REMOVED routes, if needs be
2085 * selected route must stay for a while longer though
2087 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2088 && (pi
!= old_select
))
2089 bgp_path_info_reap(rn
, pi
);
2092 zlog_debug("%s: pi %p in holddown", __func__
,
2098 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2099 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2100 if (pi
->peer
->status
!= Established
) {
2104 "%s: pi %p non self peer %s not estab state",
2105 __func__
, pi
, pi
->peer
->host
);
2110 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2111 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2112 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2114 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2118 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2120 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2121 debug
, pfx_buf
, afi
, safi
, &rn
->reason
)) {
2126 /* Now that we know which path is the bestpath see if any of the other
2128 * qualify as multipaths
2132 bgp_path_info_path_with_addpath_rx_str(new_select
,
2135 sprintf(path_buf
, "NONE");
2137 "%s: After path selection, newbest is %s oldbest was %s",
2139 old_select
? old_select
->peer
->host
: "NONE");
2142 if (do_mpath
&& new_select
) {
2143 for (pi
= bgp_node_get_bgp_path_info(rn
);
2144 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2147 bgp_path_info_path_with_addpath_rx_str(
2150 if (pi
== new_select
) {
2153 "%s: %s is the bestpath, add to the multipath list",
2155 bgp_mp_list_add(&mp_list
, pi
);
2159 if (BGP_PATH_HOLDDOWN(pi
))
2162 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2163 && !CHECK_FLAG(pi
->peer
->sflags
,
2164 PEER_STATUS_NSF_WAIT
))
2165 if (pi
->peer
->status
!= Established
)
2168 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2171 "%s: %s has the same nexthop as the bestpath, skip it",
2176 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2177 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2183 "%s: %s is equivalent to the bestpath, add to the multipath list",
2185 bgp_mp_list_add(&mp_list
, pi
);
2190 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2192 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2193 bgp_mp_list_clear(&mp_list
);
2195 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2197 result
->old
= old_select
;
2198 result
->new = new_select
;
2204 * A new route/change in bestpath of an existing route. Evaluate the path
2205 * for advertisement to the subgroup.
2207 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2208 struct bgp_path_info
*selected
,
2209 struct bgp_node
*rn
,
2210 uint32_t addpath_tx_id
)
2213 struct peer
*onlypeer
;
2219 afi
= SUBGRP_AFI(subgrp
);
2220 safi
= SUBGRP_SAFI(subgrp
);
2221 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2224 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2225 char buf_prefix
[PREFIX_STRLEN
];
2226 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2227 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2231 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2232 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2233 PEER_STATUS_ORF_WAIT_REFRESH
))
2236 memset(&attr
, 0, sizeof(struct attr
));
2237 /* It's initialized in bgp_announce_check() */
2239 /* Announcement to the subgroup. If the route is filtered withdraw it.
2242 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2243 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2245 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2249 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2251 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2258 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2259 * This is called at the end of route processing.
2261 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2263 struct bgp_path_info
*pi
;
2265 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2266 if (BGP_PATH_HOLDDOWN(pi
))
2268 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2269 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2274 * Has the route changed from the RIB's perspective? This is invoked only
2275 * if the route selection returns the same best route as earlier - to
2276 * determine if we need to update zebra or not.
2278 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2279 struct bgp_path_info
*selected
)
2281 struct bgp_path_info
*mpinfo
;
2283 /* If this is multipath, check all selected paths for any nexthop
2284 * change or attribute change. Some attribute changes (e.g., community)
2285 * aren't of relevance to the RIB, but we'll update zebra to ensure
2286 * we handle the case of BGP nexthop change. This is the behavior
2287 * when the best path has an attribute change anyway.
2289 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2290 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2294 * If this is multipath, check all selected paths for any nexthop change
2296 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2297 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2298 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2299 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2303 /* Nothing has changed from the RIB's perspective. */
2307 struct bgp_process_queue
{
2309 STAILQ_HEAD(, bgp_node
) pqueue
;
2310 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2312 unsigned int queued
;
2316 * old_select = The old best path
2317 * new_select = the new best path
2319 * if (!old_select && new_select)
2320 * We are sending new information on.
2322 * if (old_select && new_select) {
2323 * if (new_select != old_select)
2324 * We have a new best path send a change
2326 * We've received a update with new attributes that needs
2330 * if (old_select && !new_select)
2331 * We have no eligible route that we can announce or the rn
2334 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2335 afi_t afi
, safi_t safi
)
2337 struct bgp_path_info
*new_select
;
2338 struct bgp_path_info
*old_select
;
2339 struct bgp_path_info_pair old_and_new
;
2340 char pfx_buf
[PREFIX2STR_BUFFER
];
2343 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2345 debug
= bgp_debug_bestpath(&rn
->p
);
2347 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2349 "%s: bgp delete in progress, ignoring event, p=%s",
2354 /* Is it end of initial update? (after startup) */
2356 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2357 sizeof(bgp
->update_delay_zebra_resume_time
));
2359 bgp
->main_zebra_update_hold
= 0;
2360 FOREACH_AFI_SAFI (afi
, safi
) {
2361 if (bgp_fibupd_safi(safi
))
2362 bgp_zebra_announce_table(bgp
, afi
, safi
);
2364 bgp
->main_peers_update_hold
= 0;
2366 bgp_start_routeadv(bgp
);
2370 struct prefix
*p
= &rn
->p
;
2372 debug
= bgp_debug_bestpath(&rn
->p
);
2374 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2375 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2376 afi2str(afi
), safi2str(safi
));
2379 /* Best path selection. */
2380 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2382 old_select
= old_and_new
.old
;
2383 new_select
= old_and_new
.new;
2385 /* Do we need to allocate or free labels?
2386 * Right now, since we only deal with per-prefix labels, it is not
2387 * necessary to do this upon changes to best path. Exceptions:
2388 * - label index has changed -> recalculate resulting label
2389 * - path_info sub_type changed -> switch to/from implicit-null
2390 * - no valid label (due to removed static label binding) -> get new one
2392 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2395 || bgp_label_index_differs(new_select
, old_select
)
2396 || new_select
->sub_type
!= old_select
->sub_type
2397 || !bgp_is_valid_label(&rn
->local_label
)) {
2398 /* Enforced penultimate hop popping:
2399 * implicit-null for local routes, aggregate
2400 * and redistributed routes
2402 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2403 || new_select
->sub_type
2404 == BGP_ROUTE_AGGREGATE
2405 || new_select
->sub_type
2406 == BGP_ROUTE_REDISTRIBUTE
) {
2409 BGP_NODE_REGISTERED_FOR_LABEL
))
2410 bgp_unregister_for_label(rn
);
2411 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2413 bgp_set_valid_label(&rn
->local_label
);
2415 bgp_register_for_label(rn
, new_select
);
2417 } else if (CHECK_FLAG(rn
->flags
,
2418 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2419 bgp_unregister_for_label(rn
);
2421 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2422 bgp_unregister_for_label(rn
);
2426 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2428 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2429 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2430 old_select
, new_select
);
2433 /* If best route remains the same and this is not due to user-initiated
2434 * clear, see exactly what needs to be done.
2436 if (old_select
&& old_select
== new_select
2437 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2438 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2439 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2440 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2442 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2443 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2445 if (bgp_fibupd_safi(safi
)
2446 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2448 if (new_select
->type
== ZEBRA_ROUTE_BGP
2449 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2450 || new_select
->sub_type
2451 == BGP_ROUTE_IMPORTED
))
2453 bgp_zebra_announce(rn
, p
, old_select
,
2457 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2458 bgp_zebra_clear_route_change_flags(rn
);
2460 /* If there is a change of interest to peers, reannounce the
2462 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2463 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2464 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2466 /* unicast routes must also be annouced to
2467 * labeled-unicast update-groups */
2468 if (safi
== SAFI_UNICAST
)
2469 group_announce_route(bgp
, afi
,
2470 SAFI_LABELED_UNICAST
, rn
,
2473 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2474 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2477 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2481 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2483 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2485 /* bestpath has changed; bump version */
2486 if (old_select
|| new_select
) {
2487 bgp_bump_version(rn
);
2489 if (!bgp
->t_rmap_def_originate_eval
) {
2493 update_group_refresh_default_originate_route_map
,
2494 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2495 &bgp
->t_rmap_def_originate_eval
);
2500 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2503 zlog_debug("%s: setting SELECTED flag", __func__
);
2504 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2505 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2506 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2510 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2511 if (old_select
!= new_select
) {
2513 vnc_import_bgp_exterior_del_route(bgp
, p
,
2515 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2518 vnc_import_bgp_exterior_add_route(bgp
, p
,
2520 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2526 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2528 /* unicast routes must also be annouced to labeled-unicast update-groups
2530 if (safi
== SAFI_UNICAST
)
2531 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2535 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2536 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2537 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2538 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2539 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2540 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2542 /* if this is an evpn imported type-5 prefix,
2543 * we need to withdraw the route first to clear
2544 * the nh neigh and the RMAC entry.
2547 is_route_parent_evpn(old_select
))
2548 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2550 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2552 /* Withdraw the route from the kernel. */
2553 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2554 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2555 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2556 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2558 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2562 /* advertise/withdraw type-5 routes */
2563 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2564 if (advertise_type5_routes(bgp
, afi
) &&
2566 is_route_injectable_into_evpn(new_select
)) {
2568 /* apply the route-map */
2569 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2570 route_map_result_t ret
;
2572 ret
= route_map_apply(
2573 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2574 &rn
->p
, RMAP_BGP
, new_select
);
2575 if (ret
== RMAP_PERMITMATCH
)
2576 bgp_evpn_advertise_type5_route(
2577 bgp
, &rn
->p
, new_select
->attr
,
2580 bgp_evpn_withdraw_type5_route(
2581 bgp
, &rn
->p
, afi
, safi
);
2583 bgp_evpn_advertise_type5_route(bgp
,
2589 } else if (advertise_type5_routes(bgp
, afi
) &&
2591 is_route_injectable_into_evpn(old_select
))
2592 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2595 /* Clear any route change flags. */
2596 bgp_zebra_clear_route_change_flags(rn
);
2598 /* Reap old select bgp_path_info, if it has been removed */
2599 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2600 bgp_path_info_reap(rn
, old_select
);
2602 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2606 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2608 struct bgp_process_queue
*pqnode
= data
;
2609 struct bgp
*bgp
= pqnode
->bgp
;
2610 struct bgp_table
*table
;
2611 struct bgp_node
*rn
;
2614 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2615 bgp_process_main_one(bgp
, NULL
, 0, 0);
2616 /* should always have dedicated wq call */
2617 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2621 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2622 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2623 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2624 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2625 table
= bgp_node_table(rn
);
2626 /* note, new RNs may be added as part of processing */
2627 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2629 bgp_unlock_node(rn
);
2630 bgp_table_unlock(table
);
2636 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2638 struct bgp_process_queue
*pqnode
= data
;
2640 bgp_unlock(pqnode
->bgp
);
2642 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2645 void bgp_process_queue_init(void)
2647 if (!bm
->process_main_queue
)
2648 bm
->process_main_queue
=
2649 work_queue_new(bm
->master
, "process_main_queue");
2651 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2652 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2653 bm
->process_main_queue
->spec
.max_retries
= 0;
2654 bm
->process_main_queue
->spec
.hold
= 50;
2655 /* Use a higher yield value of 50ms for main queue processing */
2656 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2659 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2661 struct bgp_process_queue
*pqnode
;
2663 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2664 sizeof(struct bgp_process_queue
));
2666 /* unlocked in bgp_processq_del */
2667 pqnode
->bgp
= bgp_lock(bgp
);
2668 STAILQ_INIT(&pqnode
->pqueue
);
2673 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2675 #define ARBITRARY_PROCESS_QLEN 10000
2676 struct work_queue
*wq
= bm
->process_main_queue
;
2677 struct bgp_process_queue
*pqnode
;
2678 int pqnode_reuse
= 0;
2680 /* already scheduled for processing? */
2681 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2687 /* Add route nodes to an existing work queue item until reaching the
2688 limit only if is from the same BGP view and it's not an EOIU marker
2690 if (work_queue_item_count(wq
)) {
2691 struct work_queue_item
*item
= work_queue_last_item(wq
);
2692 pqnode
= item
->data
;
2694 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2695 || pqnode
->bgp
!= bgp
2696 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2697 pqnode
= bgp_processq_alloc(bgp
);
2701 pqnode
= bgp_processq_alloc(bgp
);
2702 /* all unlocked in bgp_process_wq */
2703 bgp_table_lock(bgp_node_table(rn
));
2705 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2708 /* can't be enqueued twice */
2709 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2710 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2714 work_queue_add(wq
, pqnode
);
2719 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2721 struct bgp_process_queue
*pqnode
;
2723 if (bm
->process_main_queue
== NULL
)
2726 pqnode
= bgp_processq_alloc(bgp
);
2728 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2729 work_queue_add(bm
->process_main_queue
, pqnode
);
2732 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2736 peer
= THREAD_ARG(thread
);
2737 peer
->t_pmax_restart
= NULL
;
2739 if (bgp_debug_neighbor_events(peer
))
2741 "%s Maximum-prefix restart timer expired, restore peering",
2744 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2745 zlog_debug("%s: %s peer_clear failed",
2746 __PRETTY_FUNCTION__
, peer
->host
);
2751 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2755 iana_safi_t pkt_safi
;
2757 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2760 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2761 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2762 PEER_STATUS_PREFIX_LIMIT
)
2767 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2768 " exceed, limit %" PRIu32
,
2769 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2770 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2771 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2773 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2774 PEER_FLAG_MAX_PREFIX_WARNING
))
2777 /* Convert AFI, SAFI to values for packet. */
2778 pkt_afi
= afi_int2iana(afi
);
2779 pkt_safi
= safi_int2iana(safi
);
2783 ndata
[0] = (pkt_afi
>> 8);
2785 ndata
[2] = pkt_safi
;
2786 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2787 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2788 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2789 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2791 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2792 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2793 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2797 /* Dynamic peers will just close their connection. */
2798 if (peer_dynamic_neighbor(peer
))
2801 /* restart timer start */
2802 if (peer
->pmax_restart
[afi
][safi
]) {
2803 peer
->v_pmax_restart
=
2804 peer
->pmax_restart
[afi
][safi
] * 60;
2806 if (bgp_debug_neighbor_events(peer
))
2808 "%s Maximum-prefix restart timer started for %d secs",
2809 peer
->host
, peer
->v_pmax_restart
);
2811 BGP_TIMER_ON(peer
->t_pmax_restart
,
2812 bgp_maximum_prefix_restart_timer
,
2813 peer
->v_pmax_restart
);
2818 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2819 PEER_STATUS_PREFIX_LIMIT
);
2821 if (peer
->pcount
[afi
][safi
]
2822 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2823 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2824 PEER_STATUS_PREFIX_THRESHOLD
)
2829 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
2831 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2832 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2833 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2834 PEER_STATUS_PREFIX_THRESHOLD
);
2836 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2837 PEER_STATUS_PREFIX_THRESHOLD
);
2841 /* Unconditionally remove the route from the RIB, without taking
2842 * damping into consideration (eg, because the session went down)
2844 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2845 struct peer
*peer
, afi_t afi
, safi_t safi
)
2847 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2849 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2850 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2852 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, rn
, peer
, true);
2854 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2857 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2858 struct peer
*peer
, afi_t afi
, safi_t safi
,
2859 struct prefix_rd
*prd
)
2861 /* apply dampening, if result is suppressed, we'll be retaining
2862 * the bgp_path_info in the RIB for historical reference.
2864 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2865 && peer
->sort
== BGP_PEER_EBGP
)
2866 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2867 == BGP_DAMP_SUPPRESSED
) {
2868 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2874 if (safi
== SAFI_MPLS_VPN
) {
2875 struct bgp_node
*prn
= NULL
;
2876 struct bgp_table
*table
= NULL
;
2878 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2879 (struct prefix
*)prd
);
2880 if (bgp_node_has_bgp_path_info_data(prn
)) {
2881 table
= bgp_node_get_bgp_table_info(prn
);
2883 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2884 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2886 bgp_unlock_node(prn
);
2888 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2889 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2891 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2892 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2898 /* If this is an EVPN route, process for un-import. */
2899 if (safi
== SAFI_EVPN
)
2900 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2902 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2905 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2906 struct peer
*peer
, struct attr
*attr
,
2907 struct bgp_node
*rn
)
2909 struct bgp_path_info
*new;
2911 /* Make new BGP info. */
2912 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2914 new->instance
= instance
;
2915 new->sub_type
= sub_type
;
2918 new->uptime
= bgp_clock();
2923 static void overlay_index_update(struct attr
*attr
,
2924 struct eth_segment_id
*eth_s_id
,
2925 union gw_addr
*gw_ip
)
2930 if (eth_s_id
== NULL
) {
2931 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2932 sizeof(struct eth_segment_id
));
2934 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2935 sizeof(struct eth_segment_id
));
2937 if (gw_ip
== NULL
) {
2938 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2940 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2941 sizeof(union gw_addr
));
2945 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2946 struct eth_segment_id
*eth_s_id
,
2947 union gw_addr
*gw_ip
)
2949 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2950 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2952 struct eth_segment_id esi
;
2956 if (afi
!= AFI_L2VPN
)
2959 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2960 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2962 if (gw_ip
== NULL
) {
2963 memset(&temp
, 0, sizeof(temp
));
2964 path_gw_ip_remote
= &temp
.ip
;
2966 path_gw_ip_remote
= gw_ip
;
2968 if (eth_s_id
== NULL
) {
2969 memset(&temp
, 0, sizeof(temp
));
2970 path_eth_s_id_remote
= &temp
.esi
;
2972 path_eth_s_id_remote
= eth_s_id
;
2974 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2977 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2978 sizeof(struct eth_segment_id
));
2981 /* Check if received nexthop is valid or not. */
2982 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2983 uint8_t type
, uint8_t stype
,
2984 struct attr
*attr
, struct bgp_node
*rn
)
2988 /* Only validated for unicast and multicast currently. */
2989 /* Also valid for EVPN where the nexthop is an IP address. */
2990 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2993 /* If NEXT_HOP is present, validate it. */
2994 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2995 if (attr
->nexthop
.s_addr
== 0
2996 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2997 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3002 /* If MP_NEXTHOP is present, validate it. */
3003 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3004 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3005 * it is not an IPv6 link-local address.
3007 if (attr
->mp_nexthop_len
) {
3008 switch (attr
->mp_nexthop_len
) {
3009 case BGP_ATTR_NHLEN_IPV4
:
3010 case BGP_ATTR_NHLEN_VPNV4
:
3011 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
3012 || IPV4_CLASS_DE(ntohl(
3013 attr
->mp_nexthop_global_in
.s_addr
))
3014 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3018 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3019 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3020 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3021 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
3022 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3023 || IN6_IS_ADDR_MULTICAST(
3024 &attr
->mp_nexthop_global
)
3025 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3038 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3039 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3040 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3041 uint32_t num_labels
, int soft_reconfig
,
3042 struct bgp_route_evpn
*evpn
)
3045 int aspath_loop_count
= 0;
3046 struct bgp_node
*rn
;
3048 struct attr new_attr
;
3049 struct attr
*attr_new
;
3050 struct bgp_path_info
*pi
;
3051 struct bgp_path_info
*new;
3052 struct bgp_path_info_extra
*extra
;
3054 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3056 int do_loop_check
= 1;
3057 int has_valid_label
= 0;
3059 uint8_t pi_type
= 0;
3060 uint8_t pi_sub_type
= 0;
3063 int vnc_implicit_withdraw
= 0;
3067 memset(&new_attr
, 0, sizeof(struct attr
));
3068 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3069 new_attr
.label
= MPLS_INVALID_LABEL
;
3072 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3073 /* TODO: Check to see if we can get rid of "is_valid_label" */
3074 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3075 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3077 has_valid_label
= bgp_is_valid_label(label
);
3079 /* When peer's soft reconfiguration enabled. Record input packet in
3082 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3083 && peer
!= bgp
->peer_self
)
3084 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3086 /* Check previously received route. */
3087 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3088 if (pi
->peer
== peer
&& pi
->type
== type
3089 && pi
->sub_type
== sub_type
3090 && pi
->addpath_rx_id
== addpath_id
)
3093 /* AS path local-as loop check. */
3094 if (peer
->change_local_as
) {
3095 if (peer
->allowas_in
[afi
][safi
])
3096 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3097 else if (!CHECK_FLAG(peer
->flags
,
3098 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3099 aspath_loop_count
= 1;
3101 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3102 > aspath_loop_count
) {
3103 peer
->stat_pfx_aspath_loop
++;
3104 reason
= "as-path contains our own AS;";
3109 /* If the peer is configured for "allowas-in origin" and the last ASN in
3111 * as-path is our ASN then we do not need to call aspath_loop_check
3113 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3114 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3117 /* AS path loop check. */
3118 if (do_loop_check
) {
3119 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3120 > peer
->allowas_in
[afi
][safi
]
3121 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3122 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3123 > peer
->allowas_in
[afi
][safi
])) {
3124 peer
->stat_pfx_aspath_loop
++;
3125 reason
= "as-path contains our own AS;";
3130 /* Route reflector originator ID check. */
3131 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3132 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3133 peer
->stat_pfx_originator_loop
++;
3134 reason
= "originator is us;";
3138 /* Route reflector cluster ID check. */
3139 if (bgp_cluster_filter(peer
, attr
)) {
3140 peer
->stat_pfx_cluster_loop
++;
3141 reason
= "reflected from the same cluster;";
3145 /* Apply incoming filter. */
3146 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3147 peer
->stat_pfx_filter
++;
3152 /* RFC 8212 to prevent route leaks.
3153 * This specification intends to improve this situation by requiring the
3154 * explicit configuration of both BGP Import and Export Policies for any
3155 * External BGP (EBGP) session such as customers, peers, or
3156 * confederation boundaries for all enabled address families. Through
3157 * codification of the aforementioned requirement, operators will
3158 * benefit from consistent behavior across different BGP
3161 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3162 if (!bgp_inbound_policy_exists(peer
,
3163 &peer
->filter
[afi
][safi
])) {
3164 reason
= "inbound policy missing";
3168 /* draft-ietf-idr-deprecate-as-set-confed-set
3169 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3170 * Eventually, This document (if approved) updates RFC 4271
3171 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3172 * and obsoletes RFC 6472.
3174 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
3175 if (aspath_check_as_sets(attr
->aspath
)) {
3177 "as-path contains AS_SET or AS_CONFED_SET type;";
3183 /* Apply incoming route-map.
3184 * NB: new_attr may now contain newly allocated values from route-map
3186 * commands, so we need bgp_attr_flush in the error paths, until we
3188 * the attr (which takes over the memory references) */
3189 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
,
3190 label
, num_labels
, rn
) == RMAP_DENY
) {
3191 peer
->stat_pfx_filter
++;
3192 reason
= "route-map;";
3193 bgp_attr_flush(&new_attr
);
3197 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3198 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3199 /* remove from RIB previous entry */
3200 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3203 if (peer
->sort
== BGP_PEER_EBGP
) {
3205 /* If we receive the graceful-shutdown community from an eBGP
3206 * peer we must lower local-preference */
3207 if (new_attr
.community
3208 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3209 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3210 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3212 /* If graceful-shutdown is configured then add the GSHUT
3213 * community to all paths received from eBGP peers */
3214 } else if (bgp_flag_check(peer
->bgp
,
3215 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3216 bgp_attr_add_gshut_community(&new_attr
);
3222 pi_sub_type
= pi
->sub_type
;
3225 /* next hop check. */
3226 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3227 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
,
3228 pi_sub_type
, &new_attr
, rn
)) {
3229 peer
->stat_pfx_nh_invalid
++;
3230 reason
= "martian or self next-hop;";
3231 bgp_attr_flush(&new_attr
);
3235 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3236 peer
->stat_pfx_nh_invalid
++;
3237 reason
= "self mac;";
3241 attr_new
= bgp_attr_intern(&new_attr
);
3243 /* If the update is implicit withdraw. */
3245 pi
->uptime
= bgp_clock();
3246 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3248 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3250 /* Same attribute comes in. */
3251 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3252 && attrhash_cmp(pi
->attr
, attr_new
)
3253 && (!has_valid_label
3254 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3255 num_labels
* sizeof(mpls_label_t
))
3257 && (overlay_index_equal(
3258 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3259 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3260 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3261 BGP_CONFIG_DAMPENING
)
3262 && peer
->sort
== BGP_PEER_EBGP
3263 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3264 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3265 bgp_debug_rdpfxpath2str(
3266 afi
, safi
, prd
, p
, label
,
3267 num_labels
, addpath_id
? 1 : 0,
3268 addpath_id
, pfx_buf
,
3270 zlog_debug("%s rcvd %s", peer
->host
,
3274 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3275 != BGP_DAMP_SUPPRESSED
) {
3276 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3278 bgp_process(bgp
, rn
, afi
, safi
);
3280 } else /* Duplicate - odd */
3282 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3283 if (!peer
->rcvd_attr_printed
) {
3285 "%s rcvd UPDATE w/ attr: %s",
3287 peer
->rcvd_attr_str
);
3288 peer
->rcvd_attr_printed
= 1;
3291 bgp_debug_rdpfxpath2str(
3292 afi
, safi
, prd
, p
, label
,
3293 num_labels
, addpath_id
? 1 : 0,
3294 addpath_id
, pfx_buf
,
3297 "%s rcvd %s...duplicate ignored",
3298 peer
->host
, pfx_buf
);
3301 /* graceful restart STALE flag unset. */
3302 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3303 bgp_path_info_unset_flag(
3304 rn
, pi
, BGP_PATH_STALE
);
3305 bgp_process(bgp
, rn
, afi
, safi
);
3309 bgp_unlock_node(rn
);
3310 bgp_attr_unintern(&attr_new
);
3315 /* Withdraw/Announce before we fully processed the withdraw */
3316 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3317 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3318 bgp_debug_rdpfxpath2str(
3319 afi
, safi
, prd
, p
, label
, num_labels
,
3320 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3323 "%s rcvd %s, flapped quicker than processing",
3324 peer
->host
, pfx_buf
);
3327 bgp_path_info_restore(rn
, pi
);
3330 /* Received Logging. */
3331 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3332 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3333 num_labels
, addpath_id
? 1 : 0,
3334 addpath_id
, pfx_buf
,
3336 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3339 /* graceful restart STALE flag unset. */
3340 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3341 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3343 /* The attribute is changed. */
3344 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3346 /* implicit withdraw, decrement aggregate and pcount here.
3347 * only if update is accepted, they'll increment below.
3349 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3351 /* Update bgp route dampening information. */
3352 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3353 && peer
->sort
== BGP_PEER_EBGP
) {
3354 /* This is implicit withdraw so we should update
3357 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3358 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3361 if (safi
== SAFI_MPLS_VPN
) {
3362 struct bgp_node
*prn
= NULL
;
3363 struct bgp_table
*table
= NULL
;
3365 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3366 (struct prefix
*)prd
);
3367 if (bgp_node_has_bgp_path_info_data(prn
)) {
3368 table
= bgp_node_get_bgp_table_info(prn
);
3370 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3371 bgp
, prd
, table
, p
, pi
);
3373 bgp_unlock_node(prn
);
3375 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3376 && (safi
== SAFI_UNICAST
)) {
3377 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3379 * Implicit withdraw case.
3381 ++vnc_implicit_withdraw
;
3382 vnc_import_bgp_del_route(bgp
, p
, pi
);
3383 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3388 /* Special handling for EVPN update of an existing route. If the
3389 * extended community attribute has changed, we need to
3391 * the route using its existing extended community. It will be
3392 * subsequently processed for import with the new extended
3395 if (safi
== SAFI_EVPN
&& !same_attr
) {
3397 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3399 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3402 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3403 attr_new
->ecommunity
);
3405 if (bgp_debug_update(peer
, p
, NULL
, 1))
3407 "Change in EXT-COMM, existing %s new %s",
3409 pi
->attr
->ecommunity
),
3411 attr_new
->ecommunity
));
3412 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3418 /* Update to new attribute. */
3419 bgp_attr_unintern(&pi
->attr
);
3420 pi
->attr
= attr_new
;
3422 /* Update MPLS label */
3423 if (has_valid_label
) {
3424 extra
= bgp_path_info_extra_get(pi
);
3425 if (extra
->label
!= label
) {
3426 memcpy(&extra
->label
, label
,
3427 num_labels
* sizeof(mpls_label_t
));
3428 extra
->num_labels
= num_labels
;
3430 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3431 bgp_set_valid_label(&extra
->label
[0]);
3435 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3436 && (safi
== SAFI_UNICAST
)) {
3437 if (vnc_implicit_withdraw
) {
3439 * Add back the route with its new attributes
3441 * The route is still selected, until the route
3443 * queued by bgp_process actually runs. We have
3445 * update to the VNC side immediately to avoid
3447 * configuration changes (e.g., route-map
3449 * trigger re-importation of the entire RIB.
3451 vnc_import_bgp_add_route(bgp
, p
, pi
);
3452 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3456 /* Update Overlay Index */
3457 if (afi
== AFI_L2VPN
) {
3458 overlay_index_update(
3459 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3460 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3463 /* Update bgp route dampening information. */
3464 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3465 && peer
->sort
== BGP_PEER_EBGP
) {
3466 /* Now we do normal update dampening. */
3467 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3468 if (ret
== BGP_DAMP_SUPPRESSED
) {
3469 bgp_unlock_node(rn
);
3474 /* Nexthop reachability check - for unicast and
3475 * labeled-unicast.. */
3476 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3477 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3478 || (safi
== SAFI_EVPN
&&
3479 bgp_evpn_is_prefix_nht_supported(p
))) {
3480 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3481 && peer
->ttl
== BGP_DEFAULT_TTL
3482 && !CHECK_FLAG(peer
->flags
,
3483 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3485 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3490 struct bgp
*bgp_nexthop
= bgp
;
3492 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3493 bgp_nexthop
= pi
->extra
->bgp_orig
;
3495 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3497 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3498 pi
, NULL
, connected
)
3499 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3500 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3502 if (BGP_DEBUG(nht
, NHT
)) {
3503 char buf1
[INET6_ADDRSTRLEN
];
3505 (const void *)&attr_new
3507 buf1
, INET6_ADDRSTRLEN
);
3508 zlog_debug("%s(%s): NH unresolved",
3509 __FUNCTION__
, buf1
);
3511 bgp_path_info_unset_flag(rn
, pi
,
3515 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3518 if (safi
== SAFI_MPLS_VPN
) {
3519 struct bgp_node
*prn
= NULL
;
3520 struct bgp_table
*table
= NULL
;
3522 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3523 (struct prefix
*)prd
);
3524 if (bgp_node_has_bgp_path_info_data(prn
)) {
3525 table
= bgp_node_get_bgp_table_info(prn
);
3527 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3528 bgp
, prd
, table
, p
, pi
);
3530 bgp_unlock_node(prn
);
3534 /* If this is an EVPN route and some attribute has changed,
3536 * route for import. If the extended community has changed, we
3538 * have done the un-import earlier and the import would result
3540 * route getting injected into appropriate L2 VNIs. If it is
3542 * some other attribute change, the import will result in
3544 * the attributes for the route in the VNI(s).
3546 if (safi
== SAFI_EVPN
&& !same_attr
&&
3547 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3548 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3550 /* Process change. */
3551 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3553 bgp_process(bgp
, rn
, afi
, safi
);
3554 bgp_unlock_node(rn
);
3556 if (SAFI_UNICAST
== safi
3557 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3558 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3560 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3562 if ((SAFI_MPLS_VPN
== safi
)
3563 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3565 vpn_leak_to_vrf_update(bgp
, pi
);
3569 if (SAFI_MPLS_VPN
== safi
) {
3570 mpls_label_t label_decoded
= decode_label(label
);
3572 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3573 type
, sub_type
, &label_decoded
);
3575 if (SAFI_ENCAP
== safi
) {
3576 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3577 type
, sub_type
, NULL
);
3582 } // End of implicit withdraw
3584 /* Received Logging. */
3585 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3586 if (!peer
->rcvd_attr_printed
) {
3587 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3588 peer
->rcvd_attr_str
);
3589 peer
->rcvd_attr_printed
= 1;
3592 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3593 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3595 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3598 /* Make new BGP info. */
3599 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3601 /* Update MPLS label */
3602 if (has_valid_label
) {
3603 extra
= bgp_path_info_extra_get(new);
3604 if (extra
->label
!= label
) {
3605 memcpy(&extra
->label
, label
,
3606 num_labels
* sizeof(mpls_label_t
));
3607 extra
->num_labels
= num_labels
;
3609 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3610 bgp_set_valid_label(&extra
->label
[0]);
3613 /* Update Overlay Index */
3614 if (afi
== AFI_L2VPN
) {
3615 overlay_index_update(new->attr
,
3616 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3617 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3619 /* Nexthop reachability check. */
3620 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3621 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3622 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
3623 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3624 && peer
->ttl
== BGP_DEFAULT_TTL
3625 && !CHECK_FLAG(peer
->flags
,
3626 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3627 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3632 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
3634 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
3636 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3637 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3639 if (BGP_DEBUG(nht
, NHT
)) {
3640 char buf1
[INET6_ADDRSTRLEN
];
3642 (const void *)&attr_new
->nexthop
,
3643 buf1
, INET6_ADDRSTRLEN
);
3644 zlog_debug("%s(%s): NH unresolved",
3645 __FUNCTION__
, buf1
);
3647 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3650 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3653 new->addpath_rx_id
= addpath_id
;
3655 /* Increment prefix */
3656 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3658 /* Register new BGP information. */
3659 bgp_path_info_add(rn
, new);
3661 /* route_node_get lock */
3662 bgp_unlock_node(rn
);
3665 if (safi
== SAFI_MPLS_VPN
) {
3666 struct bgp_node
*prn
= NULL
;
3667 struct bgp_table
*table
= NULL
;
3669 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3670 if (bgp_node_has_bgp_path_info_data(prn
)) {
3671 table
= bgp_node_get_bgp_table_info(prn
);
3673 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3674 bgp
, prd
, table
, p
, new);
3676 bgp_unlock_node(prn
);
3680 /* If maximum prefix count is configured and current prefix
3682 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3685 /* If this is an EVPN route, process for import. */
3686 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
3687 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3689 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3691 /* Process change. */
3692 bgp_process(bgp
, rn
, afi
, safi
);
3694 if (SAFI_UNICAST
== safi
3695 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3696 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3697 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3699 if ((SAFI_MPLS_VPN
== safi
)
3700 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3702 vpn_leak_to_vrf_update(bgp
, new);
3705 if (SAFI_MPLS_VPN
== safi
) {
3706 mpls_label_t label_decoded
= decode_label(label
);
3708 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3709 sub_type
, &label_decoded
);
3711 if (SAFI_ENCAP
== safi
) {
3712 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3719 /* This BGP update is filtered. Log the reason then update BGP
3722 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3724 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3725 if (!peer
->rcvd_attr_printed
) {
3726 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3727 peer
->rcvd_attr_str
);
3728 peer
->rcvd_attr_printed
= 1;
3731 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3732 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3734 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3735 peer
->host
, pfx_buf
, reason
);
3739 /* If this is an EVPN route, un-import it as it is now filtered.
3741 if (safi
== SAFI_EVPN
)
3742 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3744 if (SAFI_UNICAST
== safi
3745 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3746 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3748 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3750 if ((SAFI_MPLS_VPN
== safi
)
3751 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3753 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3756 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3759 bgp_unlock_node(rn
);
3763 * Filtered update is treated as an implicit withdrawal (see
3765 * a few lines above)
3767 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3768 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3776 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3777 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3778 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3779 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3782 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3783 struct bgp_node
*rn
;
3784 struct bgp_path_info
*pi
;
3787 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3788 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3796 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3798 /* If peer is soft reconfiguration enabled. Record input packet for
3799 * further calculation.
3801 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3802 * routes that are filtered. This tanks out Quagga RS pretty badly due
3804 * the iteration over all RS clients.
3805 * Since we need to remove the entry from adj_in anyway, do that first
3807 * if there was no entry, we don't need to do anything more.
3809 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3810 && peer
!= bgp
->peer_self
)
3811 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3812 peer
->stat_pfx_dup_withdraw
++;
3814 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3815 bgp_debug_rdpfxpath2str(
3816 afi
, safi
, prd
, p
, label
, num_labels
,
3817 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3820 "%s withdrawing route %s not in adj-in",
3821 peer
->host
, pfx_buf
);
3823 bgp_unlock_node(rn
);
3827 /* Lookup withdrawn route. */
3828 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3829 if (pi
->peer
== peer
&& pi
->type
== type
3830 && pi
->sub_type
== sub_type
3831 && pi
->addpath_rx_id
== addpath_id
)
3835 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3836 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3837 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3839 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3843 /* Withdraw specified route from routing table. */
3844 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3845 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3846 if (SAFI_UNICAST
== safi
3847 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3848 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3849 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3851 if ((SAFI_MPLS_VPN
== safi
)
3852 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3854 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3856 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3857 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3858 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3860 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3863 /* Unlock bgp_node_get() lock. */
3864 bgp_unlock_node(rn
);
3869 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3872 struct update_subgroup
*subgrp
;
3873 subgrp
= peer_subgroup(peer
, afi
, safi
);
3874 subgroup_default_originate(subgrp
, withdraw
);
3879 * bgp_stop_announce_route_timer
3881 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3883 if (!paf
->t_announce_route
)
3886 THREAD_TIMER_OFF(paf
->t_announce_route
);
3890 * bgp_announce_route_timer_expired
3892 * Callback that is invoked when the route announcement timer for a
3895 static int bgp_announce_route_timer_expired(struct thread
*t
)
3897 struct peer_af
*paf
;
3900 paf
= THREAD_ARG(t
);
3903 if (peer
->status
!= Established
)
3906 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3909 peer_af_announce_route(paf
, 1);
3914 * bgp_announce_route
3916 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3918 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3920 struct peer_af
*paf
;
3921 struct update_subgroup
*subgrp
;
3923 paf
= peer_af_find(peer
, afi
, safi
);
3926 subgrp
= PAF_SUBGRP(paf
);
3929 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3930 * or a refresh has already been triggered.
3932 if (!subgrp
|| paf
->t_announce_route
)
3936 * Start a timer to stagger/delay the announce. This serves
3937 * two purposes - announcement can potentially be combined for
3938 * multiple peers and the announcement doesn't happen in the
3941 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3942 (subgrp
->peer_count
== 1)
3943 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3944 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3945 &paf
->t_announce_route
);
3949 * Announce routes from all AF tables to a peer.
3951 * This should ONLY be called when there is a need to refresh the
3952 * routes to the peer based on a policy change for this peer alone
3953 * or a route refresh request received from the peer.
3954 * The operation will result in splitting the peer from its existing
3955 * subgroups and putting it in new subgroups.
3957 void bgp_announce_route_all(struct peer
*peer
)
3962 FOREACH_AFI_SAFI (afi
, safi
)
3963 bgp_announce_route(peer
, afi
, safi
);
3966 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3967 struct bgp_table
*table
,
3968 struct prefix_rd
*prd
)
3971 struct bgp_node
*rn
;
3972 struct bgp_adj_in
*ain
;
3975 table
= peer
->bgp
->rib
[afi
][safi
];
3977 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3978 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3979 if (ain
->peer
!= peer
)
3982 struct bgp_path_info
*pi
;
3983 uint32_t num_labels
= 0;
3984 mpls_label_t
*label_pnt
= NULL
;
3985 struct bgp_route_evpn evpn
;
3987 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
3989 if (pi
->peer
== peer
)
3992 if (pi
&& pi
->extra
)
3993 num_labels
= pi
->extra
->num_labels
;
3995 label_pnt
= &pi
->extra
->label
[0];
3997 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
4000 memset(&evpn
, 0, sizeof(evpn
));
4002 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
4003 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
4004 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4005 num_labels
, 1, &evpn
);
4008 bgp_unlock_node(rn
);
4014 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4016 struct bgp_node
*rn
;
4017 struct bgp_table
*table
;
4019 if (peer
->status
!= Established
)
4022 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4023 && (safi
!= SAFI_EVPN
))
4024 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4026 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4027 rn
= bgp_route_next(rn
)) {
4028 table
= bgp_node_get_bgp_table_info(rn
);
4029 if (table
!= NULL
) {
4030 struct prefix_rd prd
;
4032 prd
.family
= AF_UNSPEC
;
4034 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
4036 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
4043 struct bgp_clear_node_queue
{
4044 struct bgp_node
*rn
;
4047 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4049 struct bgp_clear_node_queue
*cnq
= data
;
4050 struct bgp_node
*rn
= cnq
->rn
;
4051 struct peer
*peer
= wq
->spec
.data
;
4052 struct bgp_path_info
*pi
;
4054 afi_t afi
= bgp_node_table(rn
)->afi
;
4055 safi_t safi
= bgp_node_table(rn
)->safi
;
4060 /* It is possible that we have multiple paths for a prefix from a peer
4061 * if that peer is using AddPath.
4063 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4064 if (pi
->peer
!= peer
)
4067 /* graceful restart STALE flag set. */
4068 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4069 && peer
->nsf
[afi
][safi
]
4070 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4071 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4072 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4074 /* If this is an EVPN route, process for
4076 if (safi
== SAFI_EVPN
)
4077 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
4079 /* Handle withdraw for VRF route-leaking and L3VPN */
4080 if (SAFI_UNICAST
== safi
4081 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4082 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4083 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4086 if (SAFI_MPLS_VPN
== safi
&&
4087 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4088 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4091 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4097 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4099 struct bgp_clear_node_queue
*cnq
= data
;
4100 struct bgp_node
*rn
= cnq
->rn
;
4101 struct bgp_table
*table
= bgp_node_table(rn
);
4103 bgp_unlock_node(rn
);
4104 bgp_table_unlock(table
);
4105 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4108 static void bgp_clear_node_complete(struct work_queue
*wq
)
4110 struct peer
*peer
= wq
->spec
.data
;
4112 /* Tickle FSM to start moving again */
4113 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4115 peer_unlock(peer
); /* bgp_clear_route */
4118 static void bgp_clear_node_queue_init(struct peer
*peer
)
4120 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4122 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4123 #undef CLEAR_QUEUE_NAME_LEN
4125 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4126 peer
->clear_node_queue
->spec
.hold
= 10;
4127 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4128 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4129 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4130 peer
->clear_node_queue
->spec
.max_retries
= 0;
4132 /* we only 'lock' this peer reference when the queue is actually active
4134 peer
->clear_node_queue
->spec
.data
= peer
;
4137 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4138 struct bgp_table
*table
)
4140 struct bgp_node
*rn
;
4141 int force
= bm
->process_main_queue
? 0 : 1;
4144 table
= peer
->bgp
->rib
[afi
][safi
];
4146 /* If still no table => afi/safi isn't configured at all or smth. */
4150 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4151 struct bgp_path_info
*pi
, *next
;
4152 struct bgp_adj_in
*ain
;
4153 struct bgp_adj_in
*ain_next
;
4155 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4156 * queued for every clearing peer, regardless of whether it is
4157 * relevant to the peer at hand.
4159 * Overview: There are 3 different indices which need to be
4160 * scrubbed, potentially, when a peer is removed:
4162 * 1 peer's routes visible via the RIB (ie accepted routes)
4163 * 2 peer's routes visible by the (optional) peer's adj-in index
4164 * 3 other routes visible by the peer's adj-out index
4166 * 3 there is no hurry in scrubbing, once the struct peer is
4167 * removed from bgp->peer, we could just GC such deleted peer's
4168 * adj-outs at our leisure.
4170 * 1 and 2 must be 'scrubbed' in some way, at least made
4171 * invisible via RIB index before peer session is allowed to be
4172 * brought back up. So one needs to know when such a 'search' is
4177 * - there'd be a single global queue or a single RIB walker
4178 * - rather than tracking which route_nodes still need to be
4179 * examined on a peer basis, we'd track which peers still
4182 * Given that our per-peer prefix-counts now should be reliable,
4183 * this may actually be achievable. It doesn't seem to be a huge
4184 * problem at this time,
4186 * It is possible that we have multiple paths for a prefix from
4188 * if that peer is using AddPath.
4192 ain_next
= ain
->next
;
4194 if (ain
->peer
== peer
) {
4195 bgp_adj_in_remove(rn
, ain
);
4196 bgp_unlock_node(rn
);
4202 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4204 if (pi
->peer
!= peer
)
4208 bgp_path_info_reap(rn
, pi
);
4210 struct bgp_clear_node_queue
*cnq
;
4212 /* both unlocked in bgp_clear_node_queue_del */
4213 bgp_table_lock(bgp_node_table(rn
));
4216 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4217 sizeof(struct bgp_clear_node_queue
));
4219 work_queue_add(peer
->clear_node_queue
, cnq
);
4227 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4229 struct bgp_node
*rn
;
4230 struct bgp_table
*table
;
4232 if (peer
->clear_node_queue
== NULL
)
4233 bgp_clear_node_queue_init(peer
);
4235 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4236 * Idle until it receives a Clearing_Completed event. This protects
4237 * against peers which flap faster than we can we clear, which could
4240 * a) race with routes from the new session being installed before
4241 * clear_route_node visits the node (to delete the route of that
4243 * b) resource exhaustion, clear_route_node likely leads to an entry
4244 * on the process_main queue. Fast-flapping could cause that queue
4248 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4249 * the unlock will happen upon work-queue completion; other wise, the
4250 * unlock happens at the end of this function.
4252 if (!peer
->clear_node_queue
->thread
)
4255 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4256 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4258 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4259 rn
= bgp_route_next(rn
)) {
4260 table
= bgp_node_get_bgp_table_info(rn
);
4264 bgp_clear_route_table(peer
, afi
, safi
, table
);
4267 /* unlock if no nodes got added to the clear-node-queue. */
4268 if (!peer
->clear_node_queue
->thread
)
4272 void bgp_clear_route_all(struct peer
*peer
)
4277 FOREACH_AFI_SAFI (afi
, safi
)
4278 bgp_clear_route(peer
, afi
, safi
);
4281 rfapiProcessPeerDown(peer
);
4285 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4287 struct bgp_table
*table
;
4288 struct bgp_node
*rn
;
4289 struct bgp_adj_in
*ain
;
4290 struct bgp_adj_in
*ain_next
;
4292 table
= peer
->bgp
->rib
[afi
][safi
];
4294 /* It is possible that we have multiple paths for a prefix from a peer
4295 * if that peer is using AddPath.
4297 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4301 ain_next
= ain
->next
;
4303 if (ain
->peer
== peer
) {
4304 bgp_adj_in_remove(rn
, ain
);
4305 bgp_unlock_node(rn
);
4313 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4315 struct bgp_node
*rn
;
4316 struct bgp_path_info
*pi
;
4317 struct bgp_table
*table
;
4319 if (safi
== SAFI_MPLS_VPN
) {
4320 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4321 rn
= bgp_route_next(rn
)) {
4322 struct bgp_node
*rm
;
4324 /* look for neighbor in tables */
4325 table
= bgp_node_get_bgp_table_info(rn
);
4329 for (rm
= bgp_table_top(table
); rm
;
4330 rm
= bgp_route_next(rm
))
4331 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4333 if (pi
->peer
!= peer
)
4335 if (!CHECK_FLAG(pi
->flags
,
4339 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4344 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4345 rn
= bgp_route_next(rn
))
4346 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4348 if (pi
->peer
!= peer
)
4350 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4352 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4358 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4360 if (peer
->sort
== BGP_PEER_EBGP
4361 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4362 || FILTER_LIST_OUT_NAME(filter
)
4363 || DISTRIBUTE_OUT_NAME(filter
)))
4368 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4370 if (peer
->sort
== BGP_PEER_EBGP
4371 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4372 || FILTER_LIST_IN_NAME(filter
)
4373 || DISTRIBUTE_IN_NAME(filter
)))
4378 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4381 struct bgp_node
*rn
;
4382 struct bgp_path_info
*pi
;
4383 struct bgp_path_info
*next
;
4385 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4386 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4389 /* Unimport EVPN routes from VRFs */
4390 if (safi
== SAFI_EVPN
)
4391 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4395 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4396 && pi
->type
== ZEBRA_ROUTE_BGP
4397 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4398 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4399 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4401 if (bgp_fibupd_safi(safi
))
4402 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4404 bgp_path_info_reap(rn
, pi
);
4409 /* Delete all kernel routes. */
4410 void bgp_cleanup_routes(struct bgp
*bgp
)
4413 struct bgp_node
*rn
;
4414 struct bgp_table
*table
;
4416 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4417 if (afi
== AFI_L2VPN
)
4419 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4422 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4424 if (afi
!= AFI_L2VPN
) {
4426 safi
= SAFI_MPLS_VPN
;
4427 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4428 rn
= bgp_route_next(rn
)) {
4429 table
= bgp_node_get_bgp_table_info(rn
);
4430 if (table
!= NULL
) {
4431 bgp_cleanup_table(bgp
, table
, safi
);
4432 bgp_table_finish(&table
);
4433 bgp_node_set_bgp_table_info(rn
, NULL
);
4434 bgp_unlock_node(rn
);
4438 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4439 rn
= bgp_route_next(rn
)) {
4440 table
= bgp_node_get_bgp_table_info(rn
);
4441 if (table
!= NULL
) {
4442 bgp_cleanup_table(bgp
, table
, safi
);
4443 bgp_table_finish(&table
);
4444 bgp_node_set_bgp_table_info(rn
, NULL
);
4445 bgp_unlock_node(rn
);
4450 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4451 rn
= bgp_route_next(rn
)) {
4452 table
= bgp_node_get_bgp_table_info(rn
);
4453 if (table
!= NULL
) {
4454 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4455 bgp_table_finish(&table
);
4456 bgp_node_set_bgp_table_info(rn
, NULL
);
4457 bgp_unlock_node(rn
);
4462 void bgp_reset(void)
4465 bgp_zclient_reset();
4466 access_list_reset();
4467 prefix_list_reset();
4470 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4472 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4473 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4474 PEER_CAP_ADDPATH_AF_TX_RCV
));
4477 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4479 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4480 struct bgp_nlri
*packet
)
4489 int addpath_encoded
;
4490 uint32_t addpath_id
;
4493 lim
= pnt
+ packet
->length
;
4495 safi
= packet
->safi
;
4497 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4499 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4500 syntactic validity. If the field is syntactically incorrect,
4501 then the Error Subcode is set to Invalid Network Field. */
4502 for (; pnt
< lim
; pnt
+= psize
) {
4503 /* Clear prefix structure. */
4504 memset(&p
, 0, sizeof(struct prefix
));
4506 if (addpath_encoded
) {
4508 /* When packet overflow occurs return immediately. */
4509 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4510 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4512 addpath_id
= ntohl(*((uint32_t *)pnt
));
4513 pnt
+= BGP_ADDPATH_ID_LEN
;
4516 /* Fetch prefix length. */
4517 p
.prefixlen
= *pnt
++;
4518 /* afi/safi validity already verified by caller,
4519 * bgp_update_receive */
4520 p
.family
= afi2family(afi
);
4522 /* Prefix length check. */
4523 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4526 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4527 peer
->host
, p
.prefixlen
, packet
->afi
);
4528 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4531 /* Packet size overflow check. */
4532 psize
= PSIZE(p
.prefixlen
);
4534 /* When packet overflow occur return immediately. */
4535 if (pnt
+ psize
> lim
) {
4538 "%s [Error] Update packet error (prefix length %d overflows packet)",
4539 peer
->host
, p
.prefixlen
);
4540 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4543 /* Defensive coding, double-check the psize fits in a struct
4545 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4548 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4549 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4550 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4553 /* Fetch prefix from NLRI packet. */
4554 memcpy(p
.u
.val
, pnt
, psize
);
4556 /* Check address. */
4557 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4558 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4559 /* From RFC4271 Section 6.3:
4561 * If a prefix in the NLRI field is semantically
4563 * (e.g., an unexpected multicast IP address),
4565 * be logged locally, and the prefix SHOULD be
4570 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4571 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4576 /* Check address. */
4577 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4578 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4583 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4585 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4590 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4595 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4597 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4604 /* Normal process. */
4606 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4607 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4608 NULL
, NULL
, 0, 0, NULL
);
4610 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4611 safi
, ZEBRA_ROUTE_BGP
,
4612 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4615 /* Do not send BGP notification twice when maximum-prefix count
4617 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4618 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4620 /* Address family configuration mismatch. */
4622 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4625 /* Packet length consistency check. */
4629 "%s [Error] Update packet error (prefix length mismatch with total length)",
4631 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4634 return BGP_NLRI_PARSE_OK
;
4637 static struct bgp_static
*bgp_static_new(void)
4639 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4642 static void bgp_static_free(struct bgp_static
*bgp_static
)
4644 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4645 route_map_counter_decrement(bgp_static
->rmap
.map
);
4647 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4648 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4651 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4652 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4654 struct bgp_node
*rn
;
4655 struct bgp_path_info
*pi
;
4656 struct bgp_path_info
*new;
4657 struct bgp_path_info rmap_path
;
4659 struct attr
*attr_new
;
4660 route_map_result_t ret
;
4662 int vnc_implicit_withdraw
= 0;
4669 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4671 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4673 attr
.nexthop
= bgp_static
->igpnexthop
;
4674 attr
.med
= bgp_static
->igpmetric
;
4675 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4677 if (bgp_static
->atomic
)
4678 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4680 /* Store label index, if required. */
4681 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4682 attr
.label_index
= bgp_static
->label_index
;
4683 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4686 /* Apply route-map. */
4687 if (bgp_static
->rmap
.name
) {
4688 struct attr attr_tmp
= attr
;
4690 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4691 rmap_path
.peer
= bgp
->peer_self
;
4692 rmap_path
.attr
= &attr_tmp
;
4694 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4696 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4699 bgp
->peer_self
->rmap_type
= 0;
4701 if (ret
== RMAP_DENYMATCH
) {
4702 /* Free uninterned attribute. */
4703 bgp_attr_flush(&attr_tmp
);
4705 /* Unintern original. */
4706 aspath_unintern(&attr
.aspath
);
4707 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4711 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4712 bgp_attr_add_gshut_community(&attr_tmp
);
4714 attr_new
= bgp_attr_intern(&attr_tmp
);
4717 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4718 bgp_attr_add_gshut_community(&attr
);
4720 attr_new
= bgp_attr_intern(&attr
);
4723 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4724 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4725 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4729 if (attrhash_cmp(pi
->attr
, attr_new
)
4730 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4731 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4732 bgp_unlock_node(rn
);
4733 bgp_attr_unintern(&attr_new
);
4734 aspath_unintern(&attr
.aspath
);
4737 /* The attribute is changed. */
4738 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4740 /* Rewrite BGP route information. */
4741 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4742 bgp_path_info_restore(rn
, pi
);
4744 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4746 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4747 && (safi
== SAFI_UNICAST
)) {
4748 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4750 * Implicit withdraw case.
4751 * We have to do this before pi is
4754 ++vnc_implicit_withdraw
;
4755 vnc_import_bgp_del_route(bgp
, p
, pi
);
4756 vnc_import_bgp_exterior_del_route(
4761 bgp_attr_unintern(&pi
->attr
);
4762 pi
->attr
= attr_new
;
4763 pi
->uptime
= bgp_clock();
4765 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4766 && (safi
== SAFI_UNICAST
)) {
4767 if (vnc_implicit_withdraw
) {
4768 vnc_import_bgp_add_route(bgp
, p
, pi
);
4769 vnc_import_bgp_exterior_add_route(
4775 /* Nexthop reachability check. */
4776 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4777 && (safi
== SAFI_UNICAST
4778 || safi
== SAFI_LABELED_UNICAST
)) {
4780 struct bgp
*bgp_nexthop
= bgp
;
4782 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4783 bgp_nexthop
= pi
->extra
->bgp_orig
;
4785 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4787 bgp_path_info_set_flag(rn
, pi
,
4790 if (BGP_DEBUG(nht
, NHT
)) {
4791 char buf1
[INET6_ADDRSTRLEN
];
4792 inet_ntop(p
->family
,
4796 "%s(%s): Route not in table, not advertising",
4797 __FUNCTION__
, buf1
);
4799 bgp_path_info_unset_flag(
4800 rn
, pi
, BGP_PATH_VALID
);
4803 /* Delete the NHT structure if any, if we're
4805 * enabling/disabling import check. We
4806 * deregister the route
4807 * from NHT to avoid overloading NHT and the
4808 * process interaction
4810 bgp_unlink_nexthop(pi
);
4811 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4813 /* Process change. */
4814 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4815 bgp_process(bgp
, rn
, afi
, safi
);
4817 if (SAFI_UNICAST
== safi
4818 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4820 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4821 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4825 bgp_unlock_node(rn
);
4826 aspath_unintern(&attr
.aspath
);
4831 /* Make new BGP info. */
4832 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4834 /* Nexthop reachability check. */
4835 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4836 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4837 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4838 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4840 if (BGP_DEBUG(nht
, NHT
)) {
4841 char buf1
[INET6_ADDRSTRLEN
];
4842 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4845 "%s(%s): Route not in table, not advertising",
4846 __FUNCTION__
, buf1
);
4848 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4851 /* Delete the NHT structure if any, if we're toggling between
4852 * enabling/disabling import check. We deregister the route
4853 * from NHT to avoid overloading NHT and the process interaction
4855 bgp_unlink_nexthop(new);
4857 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4860 /* Aggregate address increment. */
4861 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4863 /* Register new BGP information. */
4864 bgp_path_info_add(rn
, new);
4866 /* route_node_get lock */
4867 bgp_unlock_node(rn
);
4869 /* Process change. */
4870 bgp_process(bgp
, rn
, afi
, safi
);
4872 if (SAFI_UNICAST
== safi
4873 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4874 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4875 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4878 /* Unintern original. */
4879 aspath_unintern(&attr
.aspath
);
4882 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4885 struct bgp_node
*rn
;
4886 struct bgp_path_info
*pi
;
4888 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4890 /* Check selected route and self inserted route. */
4891 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4892 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4893 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4896 /* Withdraw static BGP route from routing table. */
4898 if (SAFI_UNICAST
== safi
4899 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4900 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4901 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4903 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4904 bgp_unlink_nexthop(pi
);
4905 bgp_path_info_delete(rn
, pi
);
4906 bgp_process(bgp
, rn
, afi
, safi
);
4909 /* Unlock bgp_node_lookup. */
4910 bgp_unlock_node(rn
);
4914 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4916 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4917 afi_t afi
, safi_t safi
,
4918 struct prefix_rd
*prd
)
4920 struct bgp_node
*rn
;
4921 struct bgp_path_info
*pi
;
4923 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4925 /* Check selected route and self inserted route. */
4926 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4927 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4928 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4931 /* Withdraw static BGP route from routing table. */
4934 rfapiProcessWithdraw(
4935 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4936 1); /* Kill, since it is an administrative change */
4938 if (SAFI_MPLS_VPN
== safi
4939 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4940 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4942 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4943 bgp_path_info_delete(rn
, pi
);
4944 bgp_process(bgp
, rn
, afi
, safi
);
4947 /* Unlock bgp_node_lookup. */
4948 bgp_unlock_node(rn
);
4951 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4952 struct bgp_static
*bgp_static
, afi_t afi
,
4955 struct bgp_node
*rn
;
4956 struct bgp_path_info
*new;
4957 struct attr
*attr_new
;
4958 struct attr attr
= {0};
4959 struct bgp_path_info
*pi
;
4961 mpls_label_t label
= 0;
4963 uint32_t num_labels
= 0;
4968 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4970 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4973 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4975 attr
.nexthop
= bgp_static
->igpnexthop
;
4976 attr
.med
= bgp_static
->igpmetric
;
4977 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4979 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4980 || (safi
== SAFI_ENCAP
)) {
4981 if (afi
== AFI_IP
) {
4982 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4983 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4986 if (afi
== AFI_L2VPN
) {
4987 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4989 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4990 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4991 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4992 sizeof(struct in6_addr
));
4993 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4994 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4995 struct bgp_encap_type_vxlan bet
;
4996 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4997 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4998 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5000 if (bgp_static
->router_mac
) {
5001 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5004 /* Apply route-map. */
5005 if (bgp_static
->rmap
.name
) {
5006 struct attr attr_tmp
= attr
;
5007 struct bgp_path_info rmap_path
;
5008 route_map_result_t ret
;
5010 rmap_path
.peer
= bgp
->peer_self
;
5011 rmap_path
.attr
= &attr_tmp
;
5013 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5015 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5018 bgp
->peer_self
->rmap_type
= 0;
5020 if (ret
== RMAP_DENYMATCH
) {
5021 /* Free uninterned attribute. */
5022 bgp_attr_flush(&attr_tmp
);
5024 /* Unintern original. */
5025 aspath_unintern(&attr
.aspath
);
5026 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5031 attr_new
= bgp_attr_intern(&attr_tmp
);
5033 attr_new
= bgp_attr_intern(&attr
);
5036 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5037 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5038 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5042 memset(&add
, 0, sizeof(union gw_addr
));
5043 if (attrhash_cmp(pi
->attr
, attr_new
)
5044 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
5045 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5046 bgp_unlock_node(rn
);
5047 bgp_attr_unintern(&attr_new
);
5048 aspath_unintern(&attr
.aspath
);
5051 /* The attribute is changed. */
5052 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5054 /* Rewrite BGP route information. */
5055 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5056 bgp_path_info_restore(rn
, pi
);
5058 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5059 bgp_attr_unintern(&pi
->attr
);
5060 pi
->attr
= attr_new
;
5061 pi
->uptime
= bgp_clock();
5064 label
= decode_label(&pi
->extra
->label
[0]);
5067 /* Process change. */
5068 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5069 bgp_process(bgp
, rn
, afi
, safi
);
5071 if (SAFI_MPLS_VPN
== safi
5072 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5073 vpn_leak_to_vrf_update(bgp
, pi
);
5076 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5077 pi
->attr
, afi
, safi
, pi
->type
,
5078 pi
->sub_type
, &label
);
5080 bgp_unlock_node(rn
);
5081 aspath_unintern(&attr
.aspath
);
5087 /* Make new BGP info. */
5088 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5090 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5091 new->extra
= bgp_path_info_extra_new();
5093 new->extra
->label
[0] = bgp_static
->label
;
5094 new->extra
->num_labels
= num_labels
;
5097 label
= decode_label(&bgp_static
->label
);
5100 /* Aggregate address increment. */
5101 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5103 /* Register new BGP information. */
5104 bgp_path_info_add(rn
, new);
5105 /* route_node_get lock */
5106 bgp_unlock_node(rn
);
5108 /* Process change. */
5109 bgp_process(bgp
, rn
, afi
, safi
);
5111 if (SAFI_MPLS_VPN
== safi
5112 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5113 vpn_leak_to_vrf_update(bgp
, new);
5116 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5117 safi
, new->type
, new->sub_type
, &label
);
5120 /* Unintern original. */
5121 aspath_unintern(&attr
.aspath
);
5124 /* Configure static BGP network. When user don't run zebra, static
5125 route should be installed as valid. */
5126 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5127 const char *ip_str
, afi_t afi
, safi_t safi
,
5128 const char *rmap
, int backdoor
, uint32_t label_index
)
5130 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5133 struct bgp_static
*bgp_static
;
5134 struct bgp_node
*rn
;
5135 uint8_t need_update
= 0;
5137 /* Convert IP prefix string to struct prefix. */
5138 ret
= str2prefix(ip_str
, &p
);
5140 vty_out(vty
, "%% Malformed prefix\n");
5141 return CMD_WARNING_CONFIG_FAILED
;
5143 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5144 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5145 return CMD_WARNING_CONFIG_FAILED
;
5152 /* Set BGP static route configuration. */
5153 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5156 vty_out(vty
, "%% Can't find static route specified\n");
5157 return CMD_WARNING_CONFIG_FAILED
;
5160 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5162 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5163 && (label_index
!= bgp_static
->label_index
)) {
5165 "%% label-index doesn't match static route\n");
5166 return CMD_WARNING_CONFIG_FAILED
;
5169 if ((rmap
&& bgp_static
->rmap
.name
)
5170 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5172 "%% route-map name doesn't match static route\n");
5173 return CMD_WARNING_CONFIG_FAILED
;
5176 /* Update BGP RIB. */
5177 if (!bgp_static
->backdoor
)
5178 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5180 /* Clear configuration. */
5181 bgp_static_free(bgp_static
);
5182 bgp_node_set_bgp_static_info(rn
, NULL
);
5183 bgp_unlock_node(rn
);
5184 bgp_unlock_node(rn
);
5187 /* Set BGP static route configuration. */
5188 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5190 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5192 /* Configuration change. */
5193 /* Label index cannot be changed. */
5194 if (bgp_static
->label_index
!= label_index
) {
5195 vty_out(vty
, "%% cannot change label-index\n");
5196 return CMD_WARNING_CONFIG_FAILED
;
5199 /* Check previous routes are installed into BGP. */
5200 if (bgp_static
->valid
5201 && bgp_static
->backdoor
!= backdoor
)
5204 bgp_static
->backdoor
= backdoor
;
5207 XFREE(MTYPE_ROUTE_MAP_NAME
,
5208 bgp_static
->rmap
.name
);
5209 route_map_counter_decrement(
5210 bgp_static
->rmap
.map
);
5211 bgp_static
->rmap
.name
=
5212 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5213 bgp_static
->rmap
.map
=
5214 route_map_lookup_by_name(rmap
);
5215 route_map_counter_increment(
5216 bgp_static
->rmap
.map
);
5218 XFREE(MTYPE_ROUTE_MAP_NAME
,
5219 bgp_static
->rmap
.name
);
5220 route_map_counter_decrement(
5221 bgp_static
->rmap
.map
);
5222 bgp_static
->rmap
.name
= NULL
;
5223 bgp_static
->rmap
.map
= NULL
;
5224 bgp_static
->valid
= 0;
5226 bgp_unlock_node(rn
);
5228 /* New configuration. */
5229 bgp_static
= bgp_static_new();
5230 bgp_static
->backdoor
= backdoor
;
5231 bgp_static
->valid
= 0;
5232 bgp_static
->igpmetric
= 0;
5233 bgp_static
->igpnexthop
.s_addr
= 0;
5234 bgp_static
->label_index
= label_index
;
5237 XFREE(MTYPE_ROUTE_MAP_NAME
,
5238 bgp_static
->rmap
.name
);
5239 route_map_counter_decrement(
5240 bgp_static
->rmap
.map
);
5241 bgp_static
->rmap
.name
=
5242 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5243 bgp_static
->rmap
.map
=
5244 route_map_lookup_by_name(rmap
);
5245 route_map_counter_increment(
5246 bgp_static
->rmap
.map
);
5248 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5251 bgp_static
->valid
= 1;
5253 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5255 if (!bgp_static
->backdoor
)
5256 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5262 void bgp_static_add(struct bgp
*bgp
)
5266 struct bgp_node
*rn
;
5267 struct bgp_node
*rm
;
5268 struct bgp_table
*table
;
5269 struct bgp_static
*bgp_static
;
5271 FOREACH_AFI_SAFI (afi
, safi
)
5272 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5273 rn
= bgp_route_next(rn
)) {
5274 if (!bgp_node_has_bgp_path_info_data(rn
))
5277 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5278 || (safi
== SAFI_EVPN
)) {
5279 table
= bgp_node_get_bgp_table_info(rn
);
5281 for (rm
= bgp_table_top(table
); rm
;
5282 rm
= bgp_route_next(rm
)) {
5284 bgp_node_get_bgp_static_info(
5286 bgp_static_update_safi(bgp
, &rm
->p
,
5293 bgp_node_get_bgp_static_info(rn
), afi
,
5299 /* Called from bgp_delete(). Delete all static routes from the BGP
5301 void bgp_static_delete(struct bgp
*bgp
)
5305 struct bgp_node
*rn
;
5306 struct bgp_node
*rm
;
5307 struct bgp_table
*table
;
5308 struct bgp_static
*bgp_static
;
5310 FOREACH_AFI_SAFI (afi
, safi
)
5311 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5312 rn
= bgp_route_next(rn
)) {
5313 if (!bgp_node_has_bgp_path_info_data(rn
))
5316 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5317 || (safi
== SAFI_EVPN
)) {
5318 table
= bgp_node_get_bgp_table_info(rn
);
5320 for (rm
= bgp_table_top(table
); rm
;
5321 rm
= bgp_route_next(rm
)) {
5323 bgp_node_get_bgp_static_info(
5328 bgp_static_withdraw_safi(
5329 bgp
, &rm
->p
, AFI_IP
, safi
,
5330 (struct prefix_rd
*)&rn
->p
);
5331 bgp_static_free(bgp_static
);
5332 bgp_node_set_bgp_static_info(rn
, NULL
);
5333 bgp_unlock_node(rn
);
5336 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5337 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5338 bgp_static_free(bgp_static
);
5339 bgp_node_set_bgp_static_info(rn
, NULL
);
5340 bgp_unlock_node(rn
);
5345 void bgp_static_redo_import_check(struct bgp
*bgp
)
5349 struct bgp_node
*rn
;
5350 struct bgp_node
*rm
;
5351 struct bgp_table
*table
;
5352 struct bgp_static
*bgp_static
;
5354 /* Use this flag to force reprocessing of the route */
5355 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5356 FOREACH_AFI_SAFI (afi
, safi
) {
5357 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5358 rn
= bgp_route_next(rn
)) {
5359 if (!bgp_node_has_bgp_path_info_data(rn
))
5362 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5363 || (safi
== SAFI_EVPN
)) {
5364 table
= bgp_node_get_bgp_table_info(rn
);
5366 for (rm
= bgp_table_top(table
); rm
;
5367 rm
= bgp_route_next(rm
)) {
5369 bgp_node_get_bgp_static_info(
5371 bgp_static_update_safi(bgp
, &rm
->p
,
5376 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5377 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5382 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5385 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5388 struct bgp_table
*table
;
5389 struct bgp_node
*rn
;
5390 struct bgp_path_info
*pi
;
5392 /* Do not install the aggregate route if BGP is in the
5393 * process of termination.
5395 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5396 (bgp
->peer_self
== NULL
))
5399 table
= bgp
->rib
[afi
][safi
];
5400 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5401 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5402 if (pi
->peer
== bgp
->peer_self
5403 && ((pi
->type
== ZEBRA_ROUTE_BGP
5404 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5405 || (pi
->type
!= ZEBRA_ROUTE_BGP
5407 == BGP_ROUTE_REDISTRIBUTE
))) {
5408 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5410 bgp_unlink_nexthop(pi
);
5411 bgp_path_info_delete(rn
, pi
);
5412 bgp_process(bgp
, rn
, afi
, safi
);
5419 * Purge all networks and redistributed routes from routing table.
5420 * Invoked upon the instance going down.
5422 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5427 FOREACH_AFI_SAFI (afi
, safi
)
5428 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5433 * Currently this is used to set static routes for VPN and ENCAP.
5434 * I think it can probably be factored with bgp_static_set.
5436 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5437 const char *ip_str
, const char *rd_str
,
5438 const char *label_str
, const char *rmap_str
,
5439 int evpn_type
, const char *esi
, const char *gwip
,
5440 const char *ethtag
, const char *routermac
)
5442 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5445 struct prefix_rd prd
;
5446 struct bgp_node
*prn
;
5447 struct bgp_node
*rn
;
5448 struct bgp_table
*table
;
5449 struct bgp_static
*bgp_static
;
5450 mpls_label_t label
= MPLS_INVALID_LABEL
;
5451 struct prefix gw_ip
;
5453 /* validate ip prefix */
5454 ret
= str2prefix(ip_str
, &p
);
5456 vty_out(vty
, "%% Malformed prefix\n");
5457 return CMD_WARNING_CONFIG_FAILED
;
5460 if ((afi
== AFI_L2VPN
)
5461 && (bgp_build_evpn_prefix(evpn_type
,
5462 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5463 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5464 return CMD_WARNING_CONFIG_FAILED
;
5467 ret
= str2prefix_rd(rd_str
, &prd
);
5469 vty_out(vty
, "%% Malformed rd\n");
5470 return CMD_WARNING_CONFIG_FAILED
;
5474 unsigned long label_val
;
5475 label_val
= strtoul(label_str
, NULL
, 10);
5476 encode_label(label_val
, &label
);
5479 if (safi
== SAFI_EVPN
) {
5480 if (esi
&& str2esi(esi
, NULL
) == 0) {
5481 vty_out(vty
, "%% Malformed ESI\n");
5482 return CMD_WARNING_CONFIG_FAILED
;
5484 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5485 vty_out(vty
, "%% Malformed Router MAC\n");
5486 return CMD_WARNING_CONFIG_FAILED
;
5489 memset(&gw_ip
, 0, sizeof(struct prefix
));
5490 ret
= str2prefix(gwip
, &gw_ip
);
5492 vty_out(vty
, "%% Malformed GatewayIp\n");
5493 return CMD_WARNING_CONFIG_FAILED
;
5495 if ((gw_ip
.family
== AF_INET
5496 && is_evpn_prefix_ipaddr_v6(
5497 (struct prefix_evpn
*)&p
))
5498 || (gw_ip
.family
== AF_INET6
5499 && is_evpn_prefix_ipaddr_v4(
5500 (struct prefix_evpn
*)&p
))) {
5502 "%% GatewayIp family differs with IP prefix\n");
5503 return CMD_WARNING_CONFIG_FAILED
;
5507 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5508 if (!bgp_node_has_bgp_path_info_data(prn
))
5509 bgp_node_set_bgp_table_info(prn
,
5510 bgp_table_init(bgp
, afi
, safi
));
5511 table
= bgp_node_get_bgp_table_info(prn
);
5513 rn
= bgp_node_get(table
, &p
);
5515 if (bgp_node_has_bgp_path_info_data(rn
)) {
5516 vty_out(vty
, "%% Same network configuration exists\n");
5517 bgp_unlock_node(rn
);
5519 /* New configuration. */
5520 bgp_static
= bgp_static_new();
5521 bgp_static
->backdoor
= 0;
5522 bgp_static
->valid
= 0;
5523 bgp_static
->igpmetric
= 0;
5524 bgp_static
->igpnexthop
.s_addr
= 0;
5525 bgp_static
->label
= label
;
5526 bgp_static
->prd
= prd
;
5529 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5530 route_map_counter_decrement(bgp_static
->rmap
.map
);
5531 bgp_static
->rmap
.name
=
5532 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5533 bgp_static
->rmap
.map
=
5534 route_map_lookup_by_name(rmap_str
);
5535 route_map_counter_increment(bgp_static
->rmap
.map
);
5538 if (safi
== SAFI_EVPN
) {
5540 bgp_static
->eth_s_id
=
5542 sizeof(struct eth_segment_id
));
5543 str2esi(esi
, bgp_static
->eth_s_id
);
5546 bgp_static
->router_mac
=
5547 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5548 (void)prefix_str2mac(routermac
,
5549 bgp_static
->router_mac
);
5552 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5554 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5556 bgp_static
->valid
= 1;
5557 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5563 /* Configure static BGP network. */
5564 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5565 const char *ip_str
, const char *rd_str
,
5566 const char *label_str
, int evpn_type
, const char *esi
,
5567 const char *gwip
, const char *ethtag
)
5569 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5572 struct prefix_rd prd
;
5573 struct bgp_node
*prn
;
5574 struct bgp_node
*rn
;
5575 struct bgp_table
*table
;
5576 struct bgp_static
*bgp_static
;
5577 mpls_label_t label
= MPLS_INVALID_LABEL
;
5579 /* Convert IP prefix string to struct prefix. */
5580 ret
= str2prefix(ip_str
, &p
);
5582 vty_out(vty
, "%% Malformed prefix\n");
5583 return CMD_WARNING_CONFIG_FAILED
;
5586 if ((afi
== AFI_L2VPN
)
5587 && (bgp_build_evpn_prefix(evpn_type
,
5588 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5589 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5590 return CMD_WARNING_CONFIG_FAILED
;
5592 ret
= str2prefix_rd(rd_str
, &prd
);
5594 vty_out(vty
, "%% Malformed rd\n");
5595 return CMD_WARNING_CONFIG_FAILED
;
5599 unsigned long label_val
;
5600 label_val
= strtoul(label_str
, NULL
, 10);
5601 encode_label(label_val
, &label
);
5604 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5605 if (!bgp_node_has_bgp_path_info_data(prn
))
5606 bgp_node_set_bgp_table_info(prn
,
5607 bgp_table_init(bgp
, afi
, safi
));
5609 bgp_unlock_node(prn
);
5610 table
= bgp_node_get_bgp_table_info(prn
);
5612 rn
= bgp_node_lookup(table
, &p
);
5615 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5617 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5618 bgp_static_free(bgp_static
);
5619 bgp_node_set_bgp_static_info(rn
, NULL
);
5620 bgp_unlock_node(rn
);
5621 bgp_unlock_node(rn
);
5623 vty_out(vty
, "%% Can't find the route\n");
5628 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5629 const char *rmap_name
)
5631 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5632 struct bgp_rmap
*rmap
;
5634 rmap
= &bgp
->table_map
[afi
][safi
];
5636 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5637 route_map_counter_decrement(rmap
->map
);
5638 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5639 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5640 route_map_counter_increment(rmap
->map
);
5642 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5643 route_map_counter_decrement(rmap
->map
);
5648 if (bgp_fibupd_safi(safi
))
5649 bgp_zebra_announce_table(bgp
, afi
, safi
);
5654 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5655 const char *rmap_name
)
5657 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5658 struct bgp_rmap
*rmap
;
5660 rmap
= &bgp
->table_map
[afi
][safi
];
5661 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5662 route_map_counter_decrement(rmap
->map
);
5666 if (bgp_fibupd_safi(safi
))
5667 bgp_zebra_announce_table(bgp
, afi
, safi
);
5672 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5675 if (bgp
->table_map
[afi
][safi
].name
) {
5676 vty_out(vty
, " table-map %s\n",
5677 bgp
->table_map
[afi
][safi
].name
);
5681 DEFUN (bgp_table_map
,
5684 "BGP table to RIB route download filter\n"
5685 "Name of the route map\n")
5688 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5689 argv
[idx_word
]->arg
);
5691 DEFUN (no_bgp_table_map
,
5692 no_bgp_table_map_cmd
,
5693 "no table-map WORD",
5695 "BGP table to RIB route download filter\n"
5696 "Name of the route map\n")
5699 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5700 argv
[idx_word
]->arg
);
5706 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5707 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5708 backdoor$backdoor}]",
5710 "Specify a network to announce via BGP\n"
5715 "Route-map to modify the attributes\n"
5716 "Name of the route map\n"
5717 "Label index to associate with the prefix\n"
5718 "Label index value\n"
5719 "Specify a BGP backdoor route\n")
5721 char addr_prefix_str
[BUFSIZ
];
5726 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5729 vty_out(vty
, "%% Inconsistent address and mask\n");
5730 return CMD_WARNING_CONFIG_FAILED
;
5734 return bgp_static_set(
5735 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5736 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5737 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5740 DEFPY(ipv6_bgp_network
,
5741 ipv6_bgp_network_cmd
,
5742 "[no] network X:X::X:X/M$prefix \
5743 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5745 "Specify a network to announce via BGP\n"
5747 "Route-map to modify the attributes\n"
5748 "Name of the route map\n"
5749 "Label index to associate with the prefix\n"
5750 "Label index value\n")
5752 return bgp_static_set(
5753 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5754 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5757 static struct bgp_aggregate
*bgp_aggregate_new(void)
5759 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5762 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5764 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
5765 route_map_counter_decrement(aggregate
->rmap
.map
);
5766 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5769 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5770 struct aspath
*aspath
,
5771 struct community
*comm
,
5772 struct ecommunity
*ecomm
,
5773 struct lcommunity
*lcomm
)
5775 static struct aspath
*ae
= NULL
;
5778 ae
= aspath_empty();
5783 if (origin
!= pi
->attr
->origin
)
5786 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5789 if (!community_cmp(pi
->attr
->community
, comm
))
5792 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5795 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5798 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5804 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5805 struct prefix
*p
, uint8_t origin
,
5806 struct aspath
*aspath
,
5807 struct community
*community
,
5808 struct ecommunity
*ecommunity
,
5809 struct lcommunity
*lcommunity
,
5810 uint8_t atomic_aggregate
,
5811 struct bgp_aggregate
*aggregate
)
5813 struct bgp_node
*rn
;
5814 struct bgp_table
*table
;
5815 struct bgp_path_info
*pi
, *orig
, *new;
5818 table
= bgp
->rib
[afi
][safi
];
5820 rn
= bgp_node_get(table
, p
);
5822 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5823 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5824 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5827 if (aggregate
->count
> 0) {
5829 * If the aggregate information has not changed
5830 * no need to re-install it again.
5832 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5833 ecommunity
, lcommunity
)) {
5834 bgp_unlock_node(rn
);
5837 aspath_free(aspath
);
5839 community_free(&community
);
5841 ecommunity_free(&ecommunity
);
5843 lcommunity_free(&lcommunity
);
5849 * Mark the old as unusable
5852 bgp_path_info_delete(rn
, pi
);
5854 attr
= bgp_attr_aggregate_intern(
5855 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
5856 aggregate
, atomic_aggregate
, p
);
5859 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
5863 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5864 bgp
->peer_self
, attr
, rn
);
5866 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5868 bgp_path_info_add(rn
, new);
5869 bgp_process(bgp
, rn
, afi
, safi
);
5871 for (pi
= orig
; pi
; pi
= pi
->next
)
5872 if (pi
->peer
== bgp
->peer_self
5873 && pi
->type
== ZEBRA_ROUTE_BGP
5874 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5877 /* Withdraw static BGP route from routing table. */
5879 bgp_path_info_delete(rn
, pi
);
5880 bgp_process(bgp
, rn
, afi
, safi
);
5884 bgp_unlock_node(rn
);
5887 /* Update an aggregate as routes are added/removed from the BGP table */
5888 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5889 afi_t afi
, safi_t safi
,
5890 struct bgp_aggregate
*aggregate
)
5892 struct bgp_table
*table
;
5893 struct bgp_node
*top
;
5894 struct bgp_node
*rn
;
5896 struct aspath
*aspath
= NULL
;
5897 struct community
*community
= NULL
;
5898 struct ecommunity
*ecommunity
= NULL
;
5899 struct lcommunity
*lcommunity
= NULL
;
5900 struct bgp_path_info
*pi
;
5901 unsigned long match
= 0;
5902 uint8_t atomic_aggregate
= 0;
5904 /* If the bgp instance is being deleted or self peer is deleted
5905 * then do not create aggregate route
5907 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5908 (bgp
->peer_self
== NULL
))
5911 /* ORIGIN attribute: If at least one route among routes that are
5912 aggregated has ORIGIN with the value INCOMPLETE, then the
5913 aggregated route must have the ORIGIN attribute with the value
5914 INCOMPLETE. Otherwise, if at least one route among routes that
5915 are aggregated has ORIGIN with the value EGP, then the aggregated
5916 route must have the origin attribute with the value EGP. In all
5917 other case the value of the ORIGIN attribute of the aggregated
5918 route is INTERNAL. */
5919 origin
= BGP_ORIGIN_IGP
;
5921 table
= bgp
->rib
[afi
][safi
];
5923 top
= bgp_node_get(table
, p
);
5924 for (rn
= bgp_node_get(table
, p
); rn
;
5925 rn
= bgp_route_next_until(rn
, top
)) {
5926 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5931 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5932 if (BGP_PATH_HOLDDOWN(pi
))
5936 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5937 atomic_aggregate
= 1;
5939 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5943 * summary-only aggregate route suppress
5944 * aggregated route announcements.
5946 if (aggregate
->summary_only
) {
5947 (bgp_path_info_extra_get(pi
))->suppress
++;
5948 bgp_path_info_set_flag(rn
, pi
,
5949 BGP_PATH_ATTR_CHANGED
);
5956 * If at least one route among routes that are
5957 * aggregated has ORIGIN with the value INCOMPLETE,
5958 * then the aggregated route MUST have the ORIGIN
5959 * attribute with the value INCOMPLETE. Otherwise, if
5960 * at least one route among routes that are aggregated
5961 * has ORIGIN with the value EGP, then the aggregated
5962 * route MUST have the ORIGIN attribute with the value
5965 switch (pi
->attr
->origin
) {
5966 case BGP_ORIGIN_INCOMPLETE
:
5967 aggregate
->incomplete_origin_count
++;
5969 case BGP_ORIGIN_EGP
:
5970 aggregate
->egp_origin_count
++;
5978 if (!aggregate
->as_set
)
5982 * as-set aggregate route generate origin, as path,
5983 * and community aggregation.
5985 /* Compute aggregate route's as-path.
5987 bgp_compute_aggregate_aspath_hash(aggregate
,
5990 /* Compute aggregate route's community.
5992 if (pi
->attr
->community
)
5993 bgp_compute_aggregate_community_hash(
5995 pi
->attr
->community
);
5997 /* Compute aggregate route's extended community.
5999 if (pi
->attr
->ecommunity
)
6000 bgp_compute_aggregate_ecommunity_hash(
6002 pi
->attr
->ecommunity
);
6004 /* Compute aggregate route's large community.
6006 if (pi
->attr
->lcommunity
)
6007 bgp_compute_aggregate_lcommunity_hash(
6009 pi
->attr
->lcommunity
);
6012 bgp_process(bgp
, rn
, afi
, safi
);
6014 if (aggregate
->as_set
) {
6015 bgp_compute_aggregate_aspath_val(aggregate
);
6016 bgp_compute_aggregate_community_val(aggregate
);
6017 bgp_compute_aggregate_ecommunity_val(aggregate
);
6018 bgp_compute_aggregate_lcommunity_val(aggregate
);
6022 bgp_unlock_node(top
);
6025 if (aggregate
->incomplete_origin_count
> 0)
6026 origin
= BGP_ORIGIN_INCOMPLETE
;
6027 else if (aggregate
->egp_origin_count
> 0)
6028 origin
= BGP_ORIGIN_EGP
;
6030 if (aggregate
->as_set
) {
6031 if (aggregate
->aspath
)
6032 /* Retrieve aggregate route's as-path.
6034 aspath
= aspath_dup(aggregate
->aspath
);
6036 if (aggregate
->community
)
6037 /* Retrieve aggregate route's community.
6039 community
= community_dup(aggregate
->community
);
6041 if (aggregate
->ecommunity
)
6042 /* Retrieve aggregate route's ecommunity.
6044 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6046 if (aggregate
->lcommunity
)
6047 /* Retrieve aggregate route's lcommunity.
6049 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6052 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6053 ecommunity
, lcommunity
, atomic_aggregate
,
6057 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6058 safi_t safi
, struct bgp_aggregate
*aggregate
)
6060 struct bgp_table
*table
;
6061 struct bgp_node
*top
;
6062 struct bgp_node
*rn
;
6063 struct bgp_path_info
*pi
;
6064 unsigned long match
;
6066 table
= bgp
->rib
[afi
][safi
];
6068 /* If routes exists below this node, generate aggregate routes. */
6069 top
= bgp_node_get(table
, p
);
6070 for (rn
= bgp_node_get(table
, p
); rn
;
6071 rn
= bgp_route_next_until(rn
, top
)) {
6072 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6076 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6077 if (BGP_PATH_HOLDDOWN(pi
))
6080 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6083 if (aggregate
->summary_only
&& pi
->extra
) {
6084 pi
->extra
->suppress
--;
6086 if (pi
->extra
->suppress
== 0) {
6087 bgp_path_info_set_flag(
6088 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6094 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6095 aggregate
->incomplete_origin_count
--;
6096 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6097 aggregate
->egp_origin_count
--;
6099 if (aggregate
->as_set
) {
6100 /* Remove as-path from aggregate.
6102 bgp_remove_aspath_from_aggregate_hash(
6106 if (pi
->attr
->community
)
6107 /* Remove community from aggregate.
6109 bgp_remove_comm_from_aggregate_hash(
6111 pi
->attr
->community
);
6113 if (pi
->attr
->ecommunity
)
6114 /* Remove ecommunity from aggregate.
6116 bgp_remove_ecomm_from_aggregate_hash(
6118 pi
->attr
->ecommunity
);
6120 if (pi
->attr
->lcommunity
)
6121 /* Remove lcommunity from aggregate.
6123 bgp_remove_lcomm_from_aggregate_hash(
6125 pi
->attr
->lcommunity
);
6130 /* If this node was suppressed, process the change. */
6132 bgp_process(bgp
, rn
, afi
, safi
);
6134 if (aggregate
->as_set
) {
6135 aspath_free(aggregate
->aspath
);
6136 aggregate
->aspath
= NULL
;
6137 if (aggregate
->community
)
6138 community_free(&aggregate
->community
);
6139 if (aggregate
->ecommunity
)
6140 ecommunity_free(&aggregate
->ecommunity
);
6141 if (aggregate
->lcommunity
)
6142 lcommunity_free(&aggregate
->lcommunity
);
6145 bgp_unlock_node(top
);
6148 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6149 struct bgp_path_info
*pinew
, afi_t afi
,
6151 struct bgp_aggregate
*aggregate
)
6154 struct aspath
*aspath
= NULL
;
6155 uint8_t atomic_aggregate
= 0;
6156 struct community
*community
= NULL
;
6157 struct ecommunity
*ecommunity
= NULL
;
6158 struct lcommunity
*lcommunity
= NULL
;
6160 /* ORIGIN attribute: If at least one route among routes that are
6161 * aggregated has ORIGIN with the value INCOMPLETE, then the
6162 * aggregated route must have the ORIGIN attribute with the value
6163 * INCOMPLETE. Otherwise, if at least one route among routes that
6164 * are aggregated has ORIGIN with the value EGP, then the aggregated
6165 * route must have the origin attribute with the value EGP. In all
6166 * other case the value of the ORIGIN attribute of the aggregated
6167 * route is INTERNAL.
6169 origin
= BGP_ORIGIN_IGP
;
6173 if (aggregate
->summary_only
)
6174 (bgp_path_info_extra_get(pinew
))->suppress
++;
6176 switch (pinew
->attr
->origin
) {
6177 case BGP_ORIGIN_INCOMPLETE
:
6178 aggregate
->incomplete_origin_count
++;
6180 case BGP_ORIGIN_EGP
:
6181 aggregate
->egp_origin_count
++;
6189 if (aggregate
->incomplete_origin_count
> 0)
6190 origin
= BGP_ORIGIN_INCOMPLETE
;
6191 else if (aggregate
->egp_origin_count
> 0)
6192 origin
= BGP_ORIGIN_EGP
;
6194 if (aggregate
->as_set
) {
6195 /* Compute aggregate route's as-path.
6197 bgp_compute_aggregate_aspath(aggregate
,
6198 pinew
->attr
->aspath
);
6200 /* Compute aggregate route's community.
6202 if (pinew
->attr
->community
)
6203 bgp_compute_aggregate_community(
6205 pinew
->attr
->community
);
6207 /* Compute aggregate route's extended community.
6209 if (pinew
->attr
->ecommunity
)
6210 bgp_compute_aggregate_ecommunity(
6212 pinew
->attr
->ecommunity
);
6214 /* Compute aggregate route's large community.
6216 if (pinew
->attr
->lcommunity
)
6217 bgp_compute_aggregate_lcommunity(
6219 pinew
->attr
->lcommunity
);
6221 /* Retrieve aggregate route's as-path.
6223 if (aggregate
->aspath
)
6224 aspath
= aspath_dup(aggregate
->aspath
);
6226 /* Retrieve aggregate route's community.
6228 if (aggregate
->community
)
6229 community
= community_dup(aggregate
->community
);
6231 /* Retrieve aggregate route's ecommunity.
6233 if (aggregate
->ecommunity
)
6234 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6236 /* Retrieve aggregate route's lcommunity.
6238 if (aggregate
->lcommunity
)
6239 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6242 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6243 aspath
, community
, ecommunity
,
6244 lcommunity
, atomic_aggregate
, aggregate
);
6247 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6249 struct bgp_path_info
*pi
,
6250 struct bgp_aggregate
*aggregate
,
6251 struct prefix
*aggr_p
)
6254 struct aspath
*aspath
= NULL
;
6255 uint8_t atomic_aggregate
= 0;
6256 struct community
*community
= NULL
;
6257 struct ecommunity
*ecommunity
= NULL
;
6258 struct lcommunity
*lcommunity
= NULL
;
6259 unsigned long match
= 0;
6261 if (BGP_PATH_HOLDDOWN(pi
))
6264 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6267 if (aggregate
->summary_only
6269 && pi
->extra
->suppress
> 0) {
6270 pi
->extra
->suppress
--;
6272 if (pi
->extra
->suppress
== 0) {
6273 bgp_path_info_set_flag(pi
->net
, pi
,
6274 BGP_PATH_ATTR_CHANGED
);
6279 if (aggregate
->count
> 0)
6282 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6283 aggregate
->incomplete_origin_count
--;
6284 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6285 aggregate
->egp_origin_count
--;
6287 if (aggregate
->as_set
) {
6288 /* Remove as-path from aggregate.
6290 bgp_remove_aspath_from_aggregate(aggregate
,
6293 if (pi
->attr
->community
)
6294 /* Remove community from aggregate.
6296 bgp_remove_community_from_aggregate(
6298 pi
->attr
->community
);
6300 if (pi
->attr
->ecommunity
)
6301 /* Remove ecommunity from aggregate.
6303 bgp_remove_ecommunity_from_aggregate(
6305 pi
->attr
->ecommunity
);
6307 if (pi
->attr
->lcommunity
)
6308 /* Remove lcommunity from aggregate.
6310 bgp_remove_lcommunity_from_aggregate(
6312 pi
->attr
->lcommunity
);
6315 /* If this node was suppressed, process the change. */
6317 bgp_process(bgp
, pi
->net
, afi
, safi
);
6319 origin
= BGP_ORIGIN_IGP
;
6320 if (aggregate
->incomplete_origin_count
> 0)
6321 origin
= BGP_ORIGIN_INCOMPLETE
;
6322 else if (aggregate
->egp_origin_count
> 0)
6323 origin
= BGP_ORIGIN_EGP
;
6325 if (aggregate
->as_set
) {
6326 /* Retrieve aggregate route's as-path.
6328 if (aggregate
->aspath
)
6329 aspath
= aspath_dup(aggregate
->aspath
);
6331 /* Retrieve aggregate route's community.
6333 if (aggregate
->community
)
6334 community
= community_dup(aggregate
->community
);
6336 /* Retrieve aggregate route's ecommunity.
6338 if (aggregate
->ecommunity
)
6339 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6341 /* Retrieve aggregate route's lcommunity.
6343 if (aggregate
->lcommunity
)
6344 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6347 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6348 aspath
, community
, ecommunity
,
6349 lcommunity
, atomic_aggregate
, aggregate
);
6352 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6353 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6355 struct bgp_node
*child
;
6356 struct bgp_node
*rn
;
6357 struct bgp_aggregate
*aggregate
;
6358 struct bgp_table
*table
;
6360 table
= bgp
->aggregate
[afi
][safi
];
6362 /* No aggregates configured. */
6363 if (bgp_table_top_nolock(table
) == NULL
)
6366 if (p
->prefixlen
== 0)
6369 if (BGP_PATH_HOLDDOWN(pi
))
6372 child
= bgp_node_get(table
, p
);
6374 /* Aggregate address configuration check. */
6375 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6376 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6377 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6378 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6382 bgp_unlock_node(child
);
6385 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6386 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6388 struct bgp_node
*child
;
6389 struct bgp_node
*rn
;
6390 struct bgp_aggregate
*aggregate
;
6391 struct bgp_table
*table
;
6393 table
= bgp
->aggregate
[afi
][safi
];
6395 /* No aggregates configured. */
6396 if (bgp_table_top_nolock(table
) == NULL
)
6399 if (p
->prefixlen
== 0)
6402 child
= bgp_node_get(table
, p
);
6404 /* Aggregate address configuration check. */
6405 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6406 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6407 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6408 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6409 del
, aggregate
, &rn
->p
);
6412 bgp_unlock_node(child
);
6415 /* Aggregate route attribute. */
6416 #define AGGREGATE_SUMMARY_ONLY 1
6417 #define AGGREGATE_AS_SET 1
6418 #define AGGREGATE_AS_UNSET 0
6420 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6421 afi_t afi
, safi_t safi
)
6423 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6426 struct bgp_node
*rn
;
6427 struct bgp_aggregate
*aggregate
;
6429 /* Convert string to prefix structure. */
6430 ret
= str2prefix(prefix_str
, &p
);
6432 vty_out(vty
, "Malformed prefix\n");
6433 return CMD_WARNING_CONFIG_FAILED
;
6437 /* Old configuration check. */
6438 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6441 "%% There is no aggregate-address configuration.\n");
6442 return CMD_WARNING_CONFIG_FAILED
;
6445 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6446 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6447 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6448 NULL
, NULL
, 0, aggregate
);
6450 /* Unlock aggregate address configuration. */
6451 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6453 if (aggregate
->community
)
6454 community_free(&aggregate
->community
);
6456 if (aggregate
->community_hash
) {
6457 /* Delete all communities in the hash.
6459 hash_clean(aggregate
->community_hash
,
6460 bgp_aggr_community_remove
);
6461 /* Free up the community_hash.
6463 hash_free(aggregate
->community_hash
);
6466 if (aggregate
->ecommunity
)
6467 ecommunity_free(&aggregate
->ecommunity
);
6469 if (aggregate
->ecommunity_hash
) {
6470 /* Delete all ecommunities in the hash.
6472 hash_clean(aggregate
->ecommunity_hash
,
6473 bgp_aggr_ecommunity_remove
);
6474 /* Free up the ecommunity_hash.
6476 hash_free(aggregate
->ecommunity_hash
);
6479 if (aggregate
->lcommunity
)
6480 lcommunity_free(&aggregate
->lcommunity
);
6482 if (aggregate
->lcommunity_hash
) {
6483 /* Delete all lcommunities in the hash.
6485 hash_clean(aggregate
->lcommunity_hash
,
6486 bgp_aggr_lcommunity_remove
);
6487 /* Free up the lcommunity_hash.
6489 hash_free(aggregate
->lcommunity_hash
);
6492 if (aggregate
->aspath
)
6493 aspath_free(aggregate
->aspath
);
6495 if (aggregate
->aspath_hash
) {
6496 /* Delete all as-paths in the hash.
6498 hash_clean(aggregate
->aspath_hash
,
6499 bgp_aggr_aspath_remove
);
6500 /* Free up the aspath_hash.
6502 hash_free(aggregate
->aspath_hash
);
6505 bgp_aggregate_free(aggregate
);
6506 bgp_unlock_node(rn
);
6507 bgp_unlock_node(rn
);
6512 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6513 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6516 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6519 struct bgp_node
*rn
;
6520 struct bgp_aggregate
*aggregate
;
6521 uint8_t as_set_new
= as_set
;
6523 /* Convert string to prefix structure. */
6524 ret
= str2prefix(prefix_str
, &p
);
6526 vty_out(vty
, "Malformed prefix\n");
6527 return CMD_WARNING_CONFIG_FAILED
;
6531 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6532 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6533 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6535 return CMD_WARNING_CONFIG_FAILED
;
6538 /* Old configuration check. */
6539 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6540 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6543 vty_out(vty
, "There is already same aggregate network.\n");
6544 /* try to remove the old entry */
6545 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6547 vty_out(vty
, "Error deleting aggregate.\n");
6548 bgp_unlock_node(rn
);
6549 return CMD_WARNING_CONFIG_FAILED
;
6553 /* Make aggregate address structure. */
6554 aggregate
= bgp_aggregate_new();
6555 aggregate
->summary_only
= summary_only
;
6557 /* Network operators MUST NOT locally generate any new
6558 * announcements containing AS_SET or AS_CONFED_SET. If they have
6559 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6560 * SHOULD withdraw those routes and re-announce routes for the
6561 * aggregate or component prefixes (i.e., the more-specific routes
6562 * subsumed by the previously aggregated route) without AS_SET
6563 * or AS_CONFED_SET in the updates.
6565 if (bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
) {
6566 if (as_set
== AGGREGATE_AS_SET
) {
6567 as_set_new
= AGGREGATE_AS_UNSET
;
6569 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
6572 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6576 aggregate
->as_set
= as_set_new
;
6577 aggregate
->safi
= safi
;
6580 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6581 route_map_counter_decrement(aggregate
->rmap
.map
);
6582 aggregate
->rmap
.name
=
6583 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6584 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6585 route_map_counter_increment(aggregate
->rmap
.map
);
6587 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6589 /* Aggregate address insert into BGP routing table. */
6590 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6595 DEFUN (aggregate_address
,
6596 aggregate_address_cmd
,
6597 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6598 "Configure BGP aggregate entries\n"
6599 "Aggregate prefix\n"
6600 "Generate AS set path information\n"
6601 "Filter more specific routes from updates\n"
6602 "Filter more specific routes from updates\n"
6603 "Generate AS set path information\n"
6604 "Apply route map to aggregate network\n"
6605 "Name of route map\n")
6608 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6609 char *prefix
= argv
[idx
]->arg
;
6611 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6612 : AGGREGATE_AS_UNSET
;
6614 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6615 ? AGGREGATE_SUMMARY_ONLY
6619 argv_find(argv
, argc
, "WORD", &idx
);
6621 rmap
= argv
[idx
]->arg
;
6623 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6624 rmap
, summary_only
, as_set
);
6627 DEFUN (aggregate_address_mask
,
6628 aggregate_address_mask_cmd
,
6629 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6630 "Configure BGP aggregate entries\n"
6631 "Aggregate address\n"
6633 "Generate AS set path information\n"
6634 "Filter more specific routes from updates\n"
6635 "Filter more specific routes from updates\n"
6636 "Generate AS set path information\n"
6637 "Apply route map to aggregate network\n"
6638 "Name of route map\n")
6641 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6642 char *prefix
= argv
[idx
]->arg
;
6643 char *mask
= argv
[idx
+ 1]->arg
;
6646 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6647 : AGGREGATE_AS_UNSET
;
6649 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6650 ? AGGREGATE_SUMMARY_ONLY
6653 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6655 rmap
= argv
[idx
]->arg
;
6657 char prefix_str
[BUFSIZ
];
6658 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6661 vty_out(vty
, "%% Inconsistent address and mask\n");
6662 return CMD_WARNING_CONFIG_FAILED
;
6665 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6666 rmap
, summary_only
, as_set
);
6669 DEFUN (no_aggregate_address
,
6670 no_aggregate_address_cmd
,
6671 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6673 "Configure BGP aggregate entries\n"
6674 "Aggregate prefix\n"
6675 "Generate AS set path information\n"
6676 "Filter more specific routes from updates\n"
6677 "Filter more specific routes from updates\n"
6678 "Generate AS set path information\n"
6679 "Apply route map to aggregate network\n"
6680 "Name of route map\n")
6683 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6684 char *prefix
= argv
[idx
]->arg
;
6685 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6688 DEFUN (no_aggregate_address_mask
,
6689 no_aggregate_address_mask_cmd
,
6690 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6692 "Configure BGP aggregate entries\n"
6693 "Aggregate address\n"
6695 "Generate AS set path information\n"
6696 "Filter more specific routes from updates\n"
6697 "Filter more specific routes from updates\n"
6698 "Generate AS set path information\n"
6699 "Apply route map to aggregate network\n"
6700 "Name of route map\n")
6703 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6704 char *prefix
= argv
[idx
]->arg
;
6705 char *mask
= argv
[idx
+ 1]->arg
;
6707 char prefix_str
[BUFSIZ
];
6708 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6711 vty_out(vty
, "%% Inconsistent address and mask\n");
6712 return CMD_WARNING_CONFIG_FAILED
;
6715 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6718 DEFUN (ipv6_aggregate_address
,
6719 ipv6_aggregate_address_cmd
,
6720 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6721 "Configure BGP aggregate entries\n"
6722 "Aggregate prefix\n"
6723 "Generate AS set path information\n"
6724 "Filter more specific routes from updates\n"
6725 "Filter more specific routes from updates\n"
6726 "Generate AS set path information\n"
6727 "Apply route map to aggregate network\n"
6728 "Name of route map\n")
6731 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6732 char *prefix
= argv
[idx
]->arg
;
6735 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6736 : AGGREGATE_AS_UNSET
;
6739 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6740 ? AGGREGATE_SUMMARY_ONLY
6743 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6745 rmap
= argv
[idx
]->arg
;
6747 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6751 DEFUN (no_ipv6_aggregate_address
,
6752 no_ipv6_aggregate_address_cmd
,
6753 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6755 "Configure BGP aggregate entries\n"
6756 "Aggregate prefix\n"
6757 "Generate AS set path information\n"
6758 "Filter more specific routes from updates\n"
6759 "Filter more specific routes from updates\n"
6760 "Generate AS set path information\n"
6761 "Apply route map to aggregate network\n"
6762 "Name of route map\n")
6765 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6766 char *prefix
= argv
[idx
]->arg
;
6767 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6770 /* Redistribute route treatment. */
6771 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6772 const union g_addr
*nexthop
, ifindex_t ifindex
,
6773 enum nexthop_types_t nhtype
, uint32_t metric
,
6774 uint8_t type
, unsigned short instance
,
6777 struct bgp_path_info
*new;
6778 struct bgp_path_info
*bpi
;
6779 struct bgp_path_info rmap_path
;
6780 struct bgp_node
*bn
;
6782 struct attr
*new_attr
;
6784 route_map_result_t ret
;
6785 struct bgp_redist
*red
;
6787 /* Make default attribute. */
6788 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6790 * This must not be NULL to satisfy Coverity SA
6792 assert(attr
.aspath
);
6795 case NEXTHOP_TYPE_IFINDEX
:
6797 case NEXTHOP_TYPE_IPV4
:
6798 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6799 attr
.nexthop
= nexthop
->ipv4
;
6801 case NEXTHOP_TYPE_IPV6
:
6802 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6803 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6804 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6806 case NEXTHOP_TYPE_BLACKHOLE
:
6807 switch (p
->family
) {
6809 attr
.nexthop
.s_addr
= INADDR_ANY
;
6812 memset(&attr
.mp_nexthop_global
, 0,
6813 sizeof(attr
.mp_nexthop_global
));
6814 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6819 attr
.nh_ifindex
= ifindex
;
6822 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6825 afi
= family2afi(p
->family
);
6827 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6829 struct attr attr_new
;
6831 /* Copy attribute for modification. */
6834 if (red
->redist_metric_flag
)
6835 attr_new
.med
= red
->redist_metric
;
6837 /* Apply route-map. */
6838 if (red
->rmap
.name
) {
6839 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6840 rmap_path
.peer
= bgp
->peer_self
;
6841 rmap_path
.attr
= &attr_new
;
6843 SET_FLAG(bgp
->peer_self
->rmap_type
,
6844 PEER_RMAP_TYPE_REDISTRIBUTE
);
6846 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6849 bgp
->peer_self
->rmap_type
= 0;
6851 if (ret
== RMAP_DENYMATCH
) {
6852 /* Free uninterned attribute. */
6853 bgp_attr_flush(&attr_new
);
6855 /* Unintern original. */
6856 aspath_unintern(&attr
.aspath
);
6857 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6862 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6863 bgp_attr_add_gshut_community(&attr_new
);
6865 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6866 SAFI_UNICAST
, p
, NULL
);
6868 new_attr
= bgp_attr_intern(&attr_new
);
6870 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6872 if (bpi
->peer
== bgp
->peer_self
6873 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6877 /* Ensure the (source route) type is updated. */
6879 if (attrhash_cmp(bpi
->attr
, new_attr
)
6880 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6881 bgp_attr_unintern(&new_attr
);
6882 aspath_unintern(&attr
.aspath
);
6883 bgp_unlock_node(bn
);
6886 /* The attribute is changed. */
6887 bgp_path_info_set_flag(bn
, bpi
,
6888 BGP_PATH_ATTR_CHANGED
);
6890 /* Rewrite BGP route information. */
6891 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6892 bgp_path_info_restore(bn
, bpi
);
6894 bgp_aggregate_decrement(
6895 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6896 bgp_attr_unintern(&bpi
->attr
);
6897 bpi
->attr
= new_attr
;
6898 bpi
->uptime
= bgp_clock();
6900 /* Process change. */
6901 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6903 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6904 bgp_unlock_node(bn
);
6905 aspath_unintern(&attr
.aspath
);
6907 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6909 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6911 vpn_leak_from_vrf_update(
6912 bgp_get_default(), bgp
, bpi
);
6918 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6919 bgp
->peer_self
, new_attr
, bn
);
6920 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6922 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6923 bgp_path_info_add(bn
, new);
6924 bgp_unlock_node(bn
);
6925 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6927 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6928 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6930 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6934 /* Unintern original. */
6935 aspath_unintern(&attr
.aspath
);
6938 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6939 unsigned short instance
)
6942 struct bgp_node
*rn
;
6943 struct bgp_path_info
*pi
;
6944 struct bgp_redist
*red
;
6946 afi
= family2afi(p
->family
);
6948 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6950 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6951 SAFI_UNICAST
, p
, NULL
);
6953 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6954 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6958 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6959 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6961 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6964 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6965 bgp_path_info_delete(rn
, pi
);
6966 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6968 bgp_unlock_node(rn
);
6972 /* Withdraw specified route type's route. */
6973 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6974 unsigned short instance
)
6976 struct bgp_node
*rn
;
6977 struct bgp_path_info
*pi
;
6978 struct bgp_table
*table
;
6980 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6982 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6983 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6984 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6985 && pi
->instance
== instance
)
6989 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6990 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6992 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6995 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6997 bgp_path_info_delete(rn
, pi
);
6998 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7003 /* Static function to display route. */
7004 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
7011 if (p
->family
== AF_INET
) {
7015 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7018 json_object_string_add(json
, "prefix",
7019 inet_ntop(p
->family
,
7022 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7023 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7024 json_object_string_add(json
, "network", buf2
);
7026 } else if (p
->family
== AF_ETHERNET
) {
7027 prefix2str(p
, buf
, PREFIX_STRLEN
);
7028 len
= vty_out(vty
, "%s", buf
);
7029 } else if (p
->family
== AF_EVPN
) {
7033 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7036 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7037 } else if (p
->family
== AF_FLOWSPEC
) {
7038 route_vty_out_flowspec(vty
, p
, NULL
,
7040 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7041 NLRI_STRING_FORMAT_MIN
, json
);
7046 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7049 json_object_string_add(json
, "prefix",
7050 inet_ntop(p
->family
,
7053 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7054 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7055 json_object_string_add(json
, "network", buf2
);
7062 vty_out(vty
, "\n%*s", 20, " ");
7064 vty_out(vty
, "%*s", len
, " ");
7068 enum bgp_display_type
{
7072 /* Print the short form route status for a bgp_path_info */
7073 static void route_vty_short_status_out(struct vty
*vty
,
7074 struct bgp_path_info
*path
,
7075 json_object
*json_path
)
7079 /* Route status display. */
7080 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7081 json_object_boolean_true_add(json_path
, "removed");
7083 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7084 json_object_boolean_true_add(json_path
, "stale");
7086 if (path
->extra
&& path
->extra
->suppress
)
7087 json_object_boolean_true_add(json_path
, "suppressed");
7089 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7090 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7091 json_object_boolean_true_add(json_path
, "valid");
7094 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7095 json_object_boolean_true_add(json_path
, "history");
7097 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7098 json_object_boolean_true_add(json_path
, "damped");
7100 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7101 json_object_boolean_true_add(json_path
, "bestpath");
7103 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7104 json_object_boolean_true_add(json_path
, "multipath");
7106 /* Internal route. */
7107 if ((path
->peer
->as
)
7108 && (path
->peer
->as
== path
->peer
->local_as
))
7109 json_object_string_add(json_path
, "pathFrom",
7112 json_object_string_add(json_path
, "pathFrom",
7118 /* Route status display. */
7119 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7121 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7123 else if (path
->extra
&& path
->extra
->suppress
)
7125 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7126 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7132 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7134 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7136 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7138 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7143 /* Internal route. */
7144 if (path
->peer
&& (path
->peer
->as
)
7145 && (path
->peer
->as
== path
->peer
->local_as
))
7151 static char *bgp_nexthop_fqdn(struct peer
*peer
)
7153 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
))
7154 return peer
->hostname
;
7158 /* called from terminal list command */
7159 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7160 struct bgp_path_info
*path
, int display
, safi_t safi
,
7161 json_object
*json_paths
)
7164 json_object
*json_path
= NULL
;
7165 json_object
*json_nexthops
= NULL
;
7166 json_object
*json_nexthop_global
= NULL
;
7167 json_object
*json_nexthop_ll
= NULL
;
7168 json_object
*json_ext_community
= NULL
;
7169 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7171 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7172 bool nexthop_othervrf
= false;
7173 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7174 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7175 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
7178 json_path
= json_object_new_object();
7180 /* short status lead text */
7181 route_vty_short_status_out(vty
, path
, json_path
);
7184 /* print prefix and mask */
7186 route_vty_out_route(p
, vty
, json_path
);
7188 vty_out(vty
, "%*s", 17, " ");
7190 route_vty_out_route(p
, vty
, json_path
);
7193 /* Print attribute */
7197 * If vrf id of nexthop is different from that of prefix,
7198 * set up printable string to append
7200 if (path
->extra
&& path
->extra
->bgp_orig
) {
7201 const char *self
= "";
7206 nexthop_othervrf
= true;
7207 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7209 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7210 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7211 "@%s%s", VRFID_NONE_STR
, self
);
7213 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7214 path
->extra
->bgp_orig
->vrf_id
, self
);
7216 if (path
->extra
->bgp_orig
->inst_type
7217 != BGP_INSTANCE_TYPE_DEFAULT
)
7219 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7221 const char *self
= "";
7226 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7230 * For ENCAP and EVPN routes, nexthop address family is not
7231 * neccessarily the same as the prefix address family.
7232 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7233 * EVPN routes are also exchanged with a MP nexthop. Currently,
7235 * is only IPv4, the value will be present in either
7237 * attr->mp_nexthop_global_in
7239 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7242 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7246 sprintf(nexthop
, "%s",
7247 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7251 sprintf(nexthop
, "%s",
7252 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7256 sprintf(nexthop
, "?");
7261 json_nexthop_global
= json_object_new_object();
7263 json_object_string_add(
7264 json_nexthop_global
, "afi",
7265 nexthop_fqdn
? "fqdn"
7266 : (af
== AF_INET
) ? "ip" : "ipv6");
7267 json_object_string_add(
7268 json_nexthop_global
,
7269 nexthop_fqdn
? "fqdn"
7270 : (af
== AF_INET
) ? "ip" : "ipv6",
7271 nexthop_fqdn
? nexthop_fqdn
: nexthop
);
7272 json_object_boolean_true_add(json_nexthop_global
,
7275 vty_out(vty
, "%s%s",
7276 nexthop_fqdn
? nexthop_fqdn
: nexthop
,
7278 } else if (safi
== SAFI_EVPN
) {
7280 json_nexthop_global
= json_object_new_object();
7282 json_object_string_add(
7283 json_nexthop_global
,
7284 nexthop_fqdn
? "fqdn" : "ip",
7285 nexthop_fqdn
? nexthop_fqdn
7286 : inet_ntoa(attr
->nexthop
));
7287 json_object_string_add(json_nexthop_global
, "afi",
7289 json_object_boolean_true_add(json_nexthop_global
,
7292 vty_out(vty
, "%-16s%s",
7293 nexthop_fqdn
?: inet_ntoa(attr
->nexthop
),
7295 } else if (safi
== SAFI_FLOWSPEC
) {
7296 if (attr
->nexthop
.s_addr
!= 0) {
7298 json_nexthop_global
= json_object_new_object();
7299 json_object_string_add(
7300 json_nexthop_global
,
7301 nexthop_fqdn
? "fqdn" : "ip",
7304 : inet_ntoa(attr
->nexthop
));
7305 json_object_string_add(json_nexthop_global
,
7307 json_object_boolean_true_add(
7308 json_nexthop_global
,
7311 vty_out(vty
, "%-16s",
7314 : inet_ntoa(attr
->nexthop
));
7317 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7319 json_nexthop_global
= json_object_new_object();
7321 json_object_string_add(json_nexthop_global
,
7322 nexthop_fqdn
? "fqdn" : "ip",
7325 : inet_ntoa(attr
->nexthop
));
7327 json_object_string_add(json_nexthop_global
, "afi",
7329 json_object_boolean_true_add(json_nexthop_global
,
7334 snprintf(buf
, sizeof(buf
), "%s%s",
7335 nexthop_fqdn
? nexthop_fqdn
7336 : inet_ntoa(attr
->nexthop
),
7338 vty_out(vty
, "%-16s", buf
);
7343 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7348 json_nexthop_global
= json_object_new_object();
7349 json_object_string_add(
7350 json_nexthop_global
,
7351 nexthop_fqdn
? "fqdn" : "ip",
7354 : inet_ntop(AF_INET6
,
7355 &attr
->mp_nexthop_global
,
7357 json_object_string_add(json_nexthop_global
, "afi",
7359 json_object_string_add(json_nexthop_global
, "scope",
7362 /* We display both LL & GL if both have been
7364 if ((attr
->mp_nexthop_len
7365 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7366 || (path
->peer
->conf_if
)) {
7367 json_nexthop_ll
= json_object_new_object();
7368 json_object_string_add(
7370 nexthop_fqdn
? "fqdn" : "ip",
7375 &attr
->mp_nexthop_local
,
7377 json_object_string_add(json_nexthop_ll
, "afi",
7379 json_object_string_add(json_nexthop_ll
, "scope",
7382 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7383 &attr
->mp_nexthop_local
)
7385 && !attr
->mp_nexthop_prefer_global
)
7386 json_object_boolean_true_add(
7387 json_nexthop_ll
, "used");
7389 json_object_boolean_true_add(
7390 json_nexthop_global
, "used");
7392 json_object_boolean_true_add(
7393 json_nexthop_global
, "used");
7395 /* Display LL if LL/Global both in table unless
7396 * prefer-global is set */
7397 if (((attr
->mp_nexthop_len
7398 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7399 && !attr
->mp_nexthop_prefer_global
)
7400 || (path
->peer
->conf_if
)) {
7401 if (path
->peer
->conf_if
) {
7402 len
= vty_out(vty
, "%s",
7403 path
->peer
->conf_if
);
7404 len
= 16 - len
; /* len of IPv6
7410 vty_out(vty
, "\n%*s", 36, " ");
7412 vty_out(vty
, "%*s", len
, " ");
7420 &attr
->mp_nexthop_local
,
7426 vty_out(vty
, "\n%*s", 36, " ");
7428 vty_out(vty
, "%*s", len
, " ");
7437 &attr
->mp_nexthop_global
,
7443 vty_out(vty
, "\n%*s", 36, " ");
7445 vty_out(vty
, "%*s", len
, " ");
7451 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7455 * Adding "metric" field to match with corresponding
7456 * CLI. "med" will be deprecated in future.
7458 json_object_int_add(json_path
, "med", attr
->med
);
7459 json_object_int_add(json_path
, "metric", attr
->med
);
7461 vty_out(vty
, "%10u", attr
->med
);
7462 else if (!json_paths
)
7466 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7470 * Adding "locPrf" field to match with corresponding
7471 * CLI. "localPref" will be deprecated in future.
7473 json_object_int_add(json_path
, "localpref",
7475 json_object_int_add(json_path
, "locPrf",
7478 vty_out(vty
, "%7u", attr
->local_pref
);
7479 else if (!json_paths
)
7483 json_object_int_add(json_path
, "weight", attr
->weight
);
7485 vty_out(vty
, "%7u ", attr
->weight
);
7489 json_object_string_add(
7490 json_path
, "peerId",
7491 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7499 * Adding "path" field to match with corresponding
7500 * CLI. "aspath" will be deprecated in future.
7502 json_object_string_add(json_path
, "aspath",
7504 json_object_string_add(json_path
, "path",
7507 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7512 json_object_string_add(json_path
, "origin",
7513 bgp_origin_long_str
[attr
->origin
]);
7515 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7518 if (safi
== SAFI_EVPN
&&
7519 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7520 json_ext_community
= json_object_new_object();
7521 json_object_string_add(json_ext_community
,
7523 attr
->ecommunity
->str
);
7524 json_object_object_add(json_path
,
7525 "extendedCommunity",
7526 json_ext_community
);
7530 json_object_boolean_true_add(json_path
,
7531 "announceNexthopSelf");
7532 if (nexthop_othervrf
) {
7533 json_object_string_add(json_path
, "nhVrfName",
7536 json_object_int_add(json_path
, "nhVrfId",
7537 ((nexthop_vrfid
== VRF_UNKNOWN
)
7539 : (int)nexthop_vrfid
));
7544 if (json_nexthop_global
|| json_nexthop_ll
) {
7545 json_nexthops
= json_object_new_array();
7547 if (json_nexthop_global
)
7548 json_object_array_add(json_nexthops
,
7549 json_nexthop_global
);
7551 if (json_nexthop_ll
)
7552 json_object_array_add(json_nexthops
,
7555 json_object_object_add(json_path
, "nexthops",
7559 json_object_array_add(json_paths
, json_path
);
7563 if (safi
== SAFI_EVPN
&&
7564 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7565 vty_out(vty
, "%*s", 20, " ");
7566 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7570 /* prints an additional line, indented, with VNC info, if
7572 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7573 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7578 /* called from terminal list command */
7579 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7580 safi_t safi
, bool use_json
, json_object
*json_ar
)
7582 json_object
*json_status
= NULL
;
7583 json_object
*json_net
= NULL
;
7586 /* Route status display. */
7588 json_status
= json_object_new_object();
7589 json_net
= json_object_new_object();
7596 /* print prefix and mask */
7598 if (safi
== SAFI_EVPN
)
7599 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7600 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7601 json_object_string_add(
7602 json_net
, "addrPrefix",
7603 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7605 json_object_int_add(json_net
, "prefixLen",
7607 prefix2str(p
, buff
, PREFIX_STRLEN
);
7608 json_object_string_add(json_net
, "network", buff
);
7611 route_vty_out_route(p
, vty
, NULL
);
7613 /* Print attribute */
7616 if (p
->family
== AF_INET
7617 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7618 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7619 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7620 json_object_string_add(
7621 json_net
, "nextHop",
7623 attr
->mp_nexthop_global_in
));
7625 json_object_string_add(
7626 json_net
, "nextHop",
7627 inet_ntoa(attr
->nexthop
));
7628 } else if (p
->family
== AF_INET6
7629 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7632 json_object_string_add(
7633 json_net
, "nextHopGlobal",
7635 &attr
->mp_nexthop_global
, buf
,
7637 } else if (p
->family
== AF_EVPN
&&
7638 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7639 json_object_string_add(json_net
,
7640 "nextHop", inet_ntoa(
7641 attr
->mp_nexthop_global_in
));
7644 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7645 json_object_int_add(json_net
, "metric",
7648 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7651 * Adding "locPrf" field to match with
7652 * corresponding CLI. "localPref" will be
7653 * deprecated in future.
7655 json_object_int_add(json_net
, "localPref",
7657 json_object_int_add(json_net
, "locPrf",
7661 json_object_int_add(json_net
, "weight", attr
->weight
);
7667 * Adding "path" field to match with
7668 * corresponding CLI. "localPref" will be
7669 * deprecated in future.
7671 json_object_string_add(json_net
, "asPath",
7673 json_object_string_add(json_net
, "path",
7678 json_object_string_add(json_net
, "bgpOriginCode",
7679 bgp_origin_str
[attr
->origin
]);
7681 if (p
->family
== AF_INET
7682 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7683 || safi
== SAFI_EVPN
7684 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7685 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7686 || safi
== SAFI_EVPN
)
7687 vty_out(vty
, "%-16s",
7689 attr
->mp_nexthop_global_in
));
7691 vty_out(vty
, "%-16s",
7692 inet_ntoa(attr
->nexthop
));
7693 } else if (p
->family
== AF_INET6
7694 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7701 &attr
->mp_nexthop_global
, buf
,
7705 vty_out(vty
, "\n%*s", 36, " ");
7707 vty_out(vty
, "%*s", len
, " ");
7710 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7711 vty_out(vty
, "%10u", attr
->med
);
7715 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7716 vty_out(vty
, "%7u", attr
->local_pref
);
7720 vty_out(vty
, "%7u ", attr
->weight
);
7724 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7727 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7731 json_object_boolean_true_add(json_status
, "*");
7732 json_object_boolean_true_add(json_status
, ">");
7733 json_object_object_add(json_net
, "appliedStatusSymbols",
7736 prefix2str(p
, buff
, PREFIX_STRLEN
);
7737 json_object_object_add(json_ar
, buff
, json_net
);
7742 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7743 struct bgp_path_info
*path
, int display
, safi_t safi
,
7746 json_object
*json_out
= NULL
;
7748 mpls_label_t label
= MPLS_INVALID_LABEL
;
7754 json_out
= json_object_new_object();
7756 /* short status lead text */
7757 route_vty_short_status_out(vty
, path
, json_out
);
7759 /* print prefix and mask */
7762 route_vty_out_route(p
, vty
, NULL
);
7764 vty_out(vty
, "%*s", 17, " ");
7767 /* Print attribute */
7769 if (((p
->family
== AF_INET
)
7770 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7771 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7772 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7773 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7774 || safi
== SAFI_EVPN
) {
7776 json_object_string_add(
7777 json_out
, "mpNexthopGlobalIn",
7778 inet_ntoa(attr
->mp_nexthop_global_in
));
7780 vty_out(vty
, "%-16s",
7781 inet_ntoa(attr
->mp_nexthop_global_in
));
7784 json_object_string_add(
7785 json_out
, "nexthop",
7786 inet_ntoa(attr
->nexthop
));
7788 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
7790 } else if (((p
->family
== AF_INET6
)
7791 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7792 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7793 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7796 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7798 json_object_string_add(
7799 json_out
, "mpNexthopGlobalIn",
7801 &attr
->mp_nexthop_global
,
7802 buf_a
, sizeof(buf_a
)));
7806 &attr
->mp_nexthop_global
,
7807 buf_a
, sizeof(buf_a
)));
7808 } else if (attr
->mp_nexthop_len
7809 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7810 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
7811 &attr
->mp_nexthop_global
,
7812 &attr
->mp_nexthop_local
);
7814 json_object_string_add(json_out
,
7815 "mpNexthopGlobalLocal",
7818 vty_out(vty
, "%s", buf_a
);
7822 label
= decode_label(&path
->extra
->label
[0]);
7824 if (bgp_is_valid_label(&label
)) {
7826 json_object_int_add(json_out
, "notag", label
);
7827 json_object_array_add(json
, json_out
);
7829 vty_out(vty
, "notag/%d", label
);
7835 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7836 struct bgp_path_info
*path
, int display
,
7837 json_object
*json_paths
)
7840 char buf
[BUFSIZ
] = {0};
7841 json_object
*json_path
= NULL
;
7842 json_object
*json_nexthop
= NULL
;
7843 json_object
*json_overlay
= NULL
;
7849 json_path
= json_object_new_object();
7850 json_overlay
= json_object_new_object();
7851 json_nexthop
= json_object_new_object();
7854 /* short status lead text */
7855 route_vty_short_status_out(vty
, path
, json_path
);
7857 /* print prefix and mask */
7859 route_vty_out_route(p
, vty
, json_path
);
7861 vty_out(vty
, "%*s", 17, " ");
7863 /* Print attribute */
7866 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7870 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
7872 vty_out(vty
, "%-16s", buf
);
7874 json_object_string_add(json_nexthop
, "ip", buf
);
7876 json_object_string_add(json_nexthop
, "afi", "ipv4");
7878 json_object_object_add(json_path
, "nexthop",
7883 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
7884 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
7886 vty_out(vty
, "%s(%s)", buf
, buf1
);
7888 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
7890 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
7893 json_object_string_add(json_nexthop
, "afi", "ipv6");
7895 json_object_object_add(json_path
, "nexthop",
7903 json_object_string_add(json_nexthop
, "Error",
7904 "Unsupported address-family");
7908 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7911 vty_out(vty
, "%s", str
);
7913 json_object_string_add(json_overlay
, "esi", str
);
7915 XFREE(MTYPE_TMP
, str
);
7917 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7918 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
7920 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7921 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7926 vty_out(vty
, "/%s", buf
);
7928 json_object_string_add(json_overlay
, "gw", buf
);
7930 if (attr
->ecommunity
) {
7932 struct ecommunity_val
*routermac
= ecommunity_lookup(
7933 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7934 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7937 mac
= ecom_mac2str((char *)routermac
->val
);
7940 vty_out(vty
, "/%s", (char *)mac
);
7942 json_object_string_add(json_overlay
, "rmac",
7945 XFREE(MTYPE_TMP
, mac
);
7952 json_object_object_add(json_path
, "overlay", json_overlay
);
7954 json_object_array_add(json_paths
, json_path
);
7958 /* dampening route */
7959 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7960 struct bgp_path_info
*path
, int display
, afi_t afi
,
7961 safi_t safi
, bool use_json
, json_object
*json
)
7965 char timebuf
[BGP_UPTIME_LEN
];
7967 /* short status lead text */
7968 route_vty_short_status_out(vty
, path
, json
);
7970 /* print prefix and mask */
7973 route_vty_out_route(p
, vty
, NULL
);
7975 vty_out(vty
, "%*s", 17, " ");
7978 len
= vty_out(vty
, "%s", path
->peer
->host
);
7982 vty_out(vty
, "\n%*s", 34, " ");
7985 json_object_int_add(json
, "peerHost", len
);
7987 vty_out(vty
, "%*s", len
, " ");
7991 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
7992 safi
, use_json
, json
);
7995 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7996 BGP_UPTIME_LEN
, afi
, safi
,
7999 /* Print attribute */
8005 json_object_string_add(json
, "asPath",
8008 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8013 json_object_string_add(json
, "origin",
8014 bgp_origin_str
[attr
->origin
]);
8016 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8023 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8024 struct bgp_path_info
*path
, int display
, afi_t afi
,
8025 safi_t safi
, bool use_json
, json_object
*json
)
8028 struct bgp_damp_info
*bdi
;
8029 char timebuf
[BGP_UPTIME_LEN
];
8035 bdi
= path
->extra
->damp_info
;
8037 /* short status lead text */
8038 route_vty_short_status_out(vty
, path
, json
);
8040 /* print prefix and mask */
8043 route_vty_out_route(p
, vty
, NULL
);
8045 vty_out(vty
, "%*s", 17, " ");
8048 len
= vty_out(vty
, "%s", path
->peer
->host
);
8052 vty_out(vty
, "\n%*s", 33, " ");
8055 json_object_int_add(json
, "peerHost", len
);
8057 vty_out(vty
, "%*s", len
, " ");
8060 len
= vty_out(vty
, "%d", bdi
->flap
);
8067 json_object_int_add(json
, "bdiFlap", len
);
8069 vty_out(vty
, "%*s", len
, " ");
8073 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8076 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8077 BGP_UPTIME_LEN
, 0, NULL
));
8079 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8080 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8082 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8083 BGP_UPTIME_LEN
, afi
, safi
,
8087 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8088 BGP_UPTIME_LEN
, afi
,
8089 safi
, use_json
, json
));
8092 vty_out(vty
, "%*s ", 8, " ");
8095 /* Print attribute */
8101 json_object_string_add(json
, "asPath",
8104 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8109 json_object_string_add(json
, "origin",
8110 bgp_origin_str
[attr
->origin
]);
8112 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8118 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8119 int *first
, const char *header
,
8120 json_object
*json_adv_to
)
8122 char buf1
[INET6_ADDRSTRLEN
];
8123 json_object
*json_peer
= NULL
;
8126 /* 'advertised-to' is a dictionary of peers we have advertised
8128 * prefix too. The key is the peer's IP or swpX, the value is
8130 * hostname if we know it and "" if not.
8132 json_peer
= json_object_new_object();
8135 json_object_string_add(json_peer
, "hostname",
8139 json_object_object_add(json_adv_to
, peer
->conf_if
,
8142 json_object_object_add(
8144 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8148 vty_out(vty
, "%s", header
);
8153 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8155 vty_out(vty
, " %s(%s)", peer
->hostname
,
8158 vty_out(vty
, " %s(%s)", peer
->hostname
,
8159 sockunion2str(&peer
->su
, buf1
,
8163 vty_out(vty
, " %s", peer
->conf_if
);
8166 sockunion2str(&peer
->su
, buf1
,
8172 static void route_vty_out_tx_ids(struct vty
*vty
,
8173 struct bgp_addpath_info_data
*d
)
8177 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8178 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8179 d
->addpath_tx_id
[i
],
8180 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8184 static const char *bgp_path_selection_reason2str(
8185 enum bgp_path_selection_reason reason
)
8188 case bgp_path_selection_none
:
8189 return "Nothing to Select";
8191 case bgp_path_selection_first
:
8192 return "First path received";
8194 case bgp_path_selection_evpn_sticky_mac
:
8195 return "EVPN Sticky Mac";
8197 case bgp_path_selection_evpn_seq
:
8198 return "EVPN sequence number";
8200 case bgp_path_selection_evpn_lower_ip
:
8201 return "EVPN lower IP";
8203 case bgp_path_selection_weight
:
8206 case bgp_path_selection_local_pref
:
8207 return "Local Pref";
8209 case bgp_path_selection_local_route
:
8210 return "Local Route";
8212 case bgp_path_selection_confed_as_path
:
8213 return "Confederation based AS Path";
8215 case bgp_path_selection_as_path
:
8218 case bgp_path_selection_origin
:
8221 case bgp_path_selection_med
:
8224 case bgp_path_selection_peer
:
8227 case bgp_path_selection_confed
:
8228 return "Confed Peer Type";
8230 case bgp_path_selection_igp_metric
:
8231 return "IGP Metric";
8233 case bgp_path_selection_older
:
8234 return "Older Path";
8236 case bgp_path_selection_router_id
:
8239 case bgp_path_selection_cluster_length
:
8240 return "Cluser length";
8242 case bgp_path_selection_stale
:
8243 return "Path Staleness";
8245 case bgp_path_selection_local_configured
:
8246 return "Locally configured route";
8248 case bgp_path_selection_neighbor_ip
:
8249 return "Neighbor IP";
8251 case bgp_path_selection_default
:
8252 return "Nothing left to compare";
8255 return "Invalid (internal error)";
8258 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8259 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8260 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8262 char buf
[INET6_ADDRSTRLEN
];
8264 char buf2
[EVPN_ROUTE_STRLEN
];
8266 int sockunion_vty_out(struct vty
*, union sockunion
*);
8268 json_object
*json_bestpath
= NULL
;
8269 json_object
*json_cluster_list
= NULL
;
8270 json_object
*json_cluster_list_list
= NULL
;
8271 json_object
*json_ext_community
= NULL
;
8272 json_object
*json_last_update
= NULL
;
8273 json_object
*json_pmsi
= NULL
;
8274 json_object
*json_nexthop_global
= NULL
;
8275 json_object
*json_nexthop_ll
= NULL
;
8276 json_object
*json_nexthops
= NULL
;
8277 json_object
*json_path
= NULL
;
8278 json_object
*json_peer
= NULL
;
8279 json_object
*json_string
= NULL
;
8280 json_object
*json_adv_to
= NULL
;
8282 struct listnode
*node
, *nnode
;
8284 int addpath_capable
;
8286 unsigned int first_as
;
8288 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8290 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
8293 json_path
= json_object_new_object();
8294 json_peer
= json_object_new_object();
8295 json_nexthop_global
= json_object_new_object();
8303 if (path
->extra
&& path
->extra
->num_labels
) {
8304 bgp_evpn_label2str(path
->extra
->label
,
8305 path
->extra
->num_labels
, tag_buf
,
8308 if (safi
== SAFI_EVPN
) {
8310 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8311 buf2
, sizeof(buf2
));
8312 vty_out(vty
, " Route %s", buf2
);
8313 if (tag_buf
[0] != '\0')
8314 vty_out(vty
, " VNI %s", tag_buf
);
8318 json_object_string_add(json_path
, "VNI",
8323 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8324 struct bgp_path_info
*parent_ri
;
8325 struct bgp_node
*rn
, *prn
;
8327 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8328 rn
= parent_ri
->net
;
8329 if (rn
&& rn
->prn
) {
8331 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8332 buf1
, sizeof(buf1
));
8333 if (is_pi_family_evpn(parent_ri
)) {
8334 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8335 buf2
, sizeof(buf2
));
8336 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8338 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8345 /* Line1 display AS-path, Aggregator */
8348 if (!attr
->aspath
->json
)
8349 aspath_str_update(attr
->aspath
, true);
8350 json_object_lock(attr
->aspath
->json
);
8351 json_object_object_add(json_path
, "aspath",
8352 attr
->aspath
->json
);
8354 if (attr
->aspath
->segments
)
8355 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8357 vty_out(vty
, " Local");
8361 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8363 json_object_boolean_true_add(json_path
, "removed");
8365 vty_out(vty
, ", (removed)");
8368 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8370 json_object_boolean_true_add(json_path
, "stale");
8372 vty_out(vty
, ", (stale)");
8375 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8377 json_object_int_add(json_path
, "aggregatorAs",
8378 attr
->aggregator_as
);
8379 json_object_string_add(
8380 json_path
, "aggregatorId",
8381 inet_ntoa(attr
->aggregator_addr
));
8383 vty_out(vty
, ", (aggregated by %u %s)",
8384 attr
->aggregator_as
,
8385 inet_ntoa(attr
->aggregator_addr
));
8389 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8390 PEER_FLAG_REFLECTOR_CLIENT
)) {
8392 json_object_boolean_true_add(json_path
,
8393 "rxedFromRrClient");
8395 vty_out(vty
, ", (Received from a RR-client)");
8398 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8399 PEER_FLAG_RSERVER_CLIENT
)) {
8401 json_object_boolean_true_add(json_path
,
8402 "rxedFromRsClient");
8404 vty_out(vty
, ", (Received from a RS-client)");
8407 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8409 json_object_boolean_true_add(json_path
,
8410 "dampeningHistoryEntry");
8412 vty_out(vty
, ", (history entry)");
8413 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8415 json_object_boolean_true_add(json_path
,
8416 "dampeningSuppressed");
8418 vty_out(vty
, ", (suppressed due to dampening)");
8424 /* Line2 display Next-hop, Neighbor, Router-id */
8425 /* Display the nexthop */
8426 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8427 || bn
->p
.family
== AF_EVPN
)
8428 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8429 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8430 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8431 || safi
== SAFI_EVPN
) {
8433 json_object_string_add(
8434 json_nexthop_global
,
8435 nexthop_fqdn
? "fqdn" : "ip",
8439 attr
->mp_nexthop_global_in
));
8445 attr
->mp_nexthop_global_in
));
8448 json_object_string_add(
8449 json_nexthop_global
,
8450 nexthop_fqdn
? "fqdn" : "ip",
8453 : inet_ntoa(attr
->nexthop
));
8458 : inet_ntoa(attr
->nexthop
));
8462 json_object_string_add(json_nexthop_global
, "afi",
8466 json_object_string_add(
8467 json_nexthop_global
,
8468 nexthop_fqdn
? "fqdn" : "ip",
8471 : inet_ntop(AF_INET6
,
8472 &attr
->mp_nexthop_global
,
8473 buf
, INET6_ADDRSTRLEN
));
8474 json_object_string_add(json_nexthop_global
, "afi",
8476 json_object_string_add(json_nexthop_global
, "scope",
8482 : inet_ntop(AF_INET6
,
8483 &attr
->mp_nexthop_global
,
8484 buf
, INET6_ADDRSTRLEN
));
8488 /* Display the IGP cost or 'inaccessible' */
8489 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8491 json_object_boolean_false_add(json_nexthop_global
,
8494 vty_out(vty
, " (inaccessible)");
8496 if (path
->extra
&& path
->extra
->igpmetric
) {
8498 json_object_int_add(json_nexthop_global
,
8500 path
->extra
->igpmetric
);
8502 vty_out(vty
, " (metric %u)",
8503 path
->extra
->igpmetric
);
8506 /* IGP cost is 0, display this only for json */
8509 json_object_int_add(json_nexthop_global
,
8514 json_object_boolean_true_add(json_nexthop_global
,
8518 /* Display peer "from" output */
8519 /* This path was originated locally */
8520 if (path
->peer
== bgp
->peer_self
) {
8522 if (safi
== SAFI_EVPN
8523 || (bn
->p
.family
== AF_INET
8524 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8526 json_object_string_add(json_peer
, "peerId",
8529 vty_out(vty
, " from 0.0.0.0 ");
8532 json_object_string_add(json_peer
, "peerId",
8535 vty_out(vty
, " from :: ");
8539 json_object_string_add(json_peer
, "routerId",
8540 inet_ntoa(bgp
->router_id
));
8542 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8545 /* We RXed this path from one of our peers */
8549 json_object_string_add(json_peer
, "peerId",
8550 sockunion2str(&path
->peer
->su
,
8553 json_object_string_add(json_peer
, "routerId",
8555 &path
->peer
->remote_id
,
8556 buf1
, sizeof(buf1
)));
8558 if (path
->peer
->hostname
)
8559 json_object_string_add(json_peer
, "hostname",
8560 path
->peer
->hostname
);
8562 if (path
->peer
->domainname
)
8563 json_object_string_add(json_peer
, "domainname",
8564 path
->peer
->domainname
);
8566 if (path
->peer
->conf_if
)
8567 json_object_string_add(json_peer
, "interface",
8568 path
->peer
->conf_if
);
8570 if (path
->peer
->conf_if
) {
8571 if (path
->peer
->hostname
8572 && bgp_flag_check(path
->peer
->bgp
,
8573 BGP_FLAG_SHOW_HOSTNAME
))
8574 vty_out(vty
, " from %s(%s)",
8575 path
->peer
->hostname
,
8576 path
->peer
->conf_if
);
8578 vty_out(vty
, " from %s",
8579 path
->peer
->conf_if
);
8581 if (path
->peer
->hostname
8582 && bgp_flag_check(path
->peer
->bgp
,
8583 BGP_FLAG_SHOW_HOSTNAME
))
8584 vty_out(vty
, " from %s(%s)",
8585 path
->peer
->hostname
,
8588 vty_out(vty
, " from %s",
8589 sockunion2str(&path
->peer
->su
,
8594 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8595 vty_out(vty
, " (%s)",
8596 inet_ntoa(attr
->originator_id
));
8598 vty_out(vty
, " (%s)",
8600 &path
->peer
->remote_id
, buf1
,
8606 * Note when vrfid of nexthop is different from that of prefix
8608 if (path
->extra
&& path
->extra
->bgp_orig
) {
8609 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8614 if (path
->extra
->bgp_orig
->inst_type
8615 == BGP_INSTANCE_TYPE_DEFAULT
)
8616 vn
= VRF_DEFAULT_NAME
;
8618 vn
= path
->extra
->bgp_orig
->name
;
8620 json_object_string_add(json_path
, "nhVrfName", vn
);
8622 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8623 json_object_int_add(json_path
, "nhVrfId", -1);
8625 json_object_int_add(json_path
, "nhVrfId",
8626 (int)nexthop_vrfid
);
8629 if (nexthop_vrfid
== VRF_UNKNOWN
)
8630 vty_out(vty
, " vrf ?");
8632 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8638 json_object_boolean_true_add(json_path
,
8639 "announceNexthopSelf");
8641 vty_out(vty
, " announce-nh-self");
8648 /* display the link-local nexthop */
8649 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8651 json_nexthop_ll
= json_object_new_object();
8652 json_object_string_add(
8653 json_nexthop_ll
, nexthop_fqdn
? "fqdn" : "ip",
8656 : inet_ntop(AF_INET6
,
8657 &attr
->mp_nexthop_local
,
8658 buf
, INET6_ADDRSTRLEN
));
8659 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8660 json_object_string_add(json_nexthop_ll
, "scope",
8663 json_object_boolean_true_add(json_nexthop_ll
,
8666 if (!attr
->mp_nexthop_prefer_global
)
8667 json_object_boolean_true_add(json_nexthop_ll
,
8670 json_object_boolean_true_add(
8671 json_nexthop_global
, "used");
8673 vty_out(vty
, " (%s) %s\n",
8674 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8675 buf
, INET6_ADDRSTRLEN
),
8676 attr
->mp_nexthop_prefer_global
8681 /* If we do not have a link-local nexthop then we must flag the
8685 json_object_boolean_true_add(json_nexthop_global
,
8689 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8690 * Int/Ext/Local, Atomic, best */
8692 json_object_string_add(json_path
, "origin",
8693 bgp_origin_long_str
[attr
->origin
]);
8695 vty_out(vty
, " Origin %s",
8696 bgp_origin_long_str
[attr
->origin
]);
8698 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8701 * Adding "metric" field to match with
8702 * corresponding CLI. "med" will be
8703 * deprecated in future.
8705 json_object_int_add(json_path
, "med", attr
->med
);
8706 json_object_int_add(json_path
, "metric", attr
->med
);
8708 vty_out(vty
, ", metric %u", attr
->med
);
8711 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8713 json_object_int_add(json_path
, "localpref",
8716 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8719 if (attr
->weight
!= 0) {
8721 json_object_int_add(json_path
, "weight", attr
->weight
);
8723 vty_out(vty
, ", weight %u", attr
->weight
);
8726 if (attr
->tag
!= 0) {
8728 json_object_int_add(json_path
, "tag", attr
->tag
);
8730 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
8733 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8735 json_object_boolean_false_add(json_path
, "valid");
8737 vty_out(vty
, ", invalid");
8738 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8740 json_object_boolean_true_add(json_path
, "valid");
8742 vty_out(vty
, ", valid");
8745 if (path
->peer
!= bgp
->peer_self
) {
8746 if (path
->peer
->as
== path
->peer
->local_as
) {
8747 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
8749 json_object_string_add(
8753 vty_out(vty
, ", confed-internal");
8756 json_object_string_add(
8757 json_peer
, "type", "internal");
8759 vty_out(vty
, ", internal");
8762 if (bgp_confederation_peers_check(bgp
,
8765 json_object_string_add(
8769 vty_out(vty
, ", confed-external");
8772 json_object_string_add(
8773 json_peer
, "type", "external");
8775 vty_out(vty
, ", external");
8778 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8780 json_object_boolean_true_add(json_path
, "aggregated");
8781 json_object_boolean_true_add(json_path
, "local");
8783 vty_out(vty
, ", aggregated, local");
8785 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8787 json_object_boolean_true_add(json_path
, "sourced");
8789 vty_out(vty
, ", sourced");
8792 json_object_boolean_true_add(json_path
, "sourced");
8793 json_object_boolean_true_add(json_path
, "local");
8795 vty_out(vty
, ", sourced, local");
8799 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8801 json_object_boolean_true_add(json_path
,
8804 vty_out(vty
, ", atomic-aggregate");
8807 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8808 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8809 && bgp_path_info_mpath_count(path
))) {
8811 json_object_boolean_true_add(json_path
, "multipath");
8813 vty_out(vty
, ", multipath");
8816 // Mark the bestpath(s)
8817 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8818 first_as
= aspath_get_first_as(attr
->aspath
);
8822 json_bestpath
= json_object_new_object();
8823 json_object_int_add(json_bestpath
, "bestpathFromAs",
8827 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
8829 vty_out(vty
, ", bestpath-from-AS Local");
8833 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8836 json_bestpath
= json_object_new_object();
8837 json_object_boolean_true_add(json_bestpath
, "overall");
8838 json_object_string_add(
8839 json_bestpath
, "selectionReason",
8840 bgp_path_selection_reason2str(bn
->reason
));
8842 vty_out(vty
, ", best");
8843 vty_out(vty
, " (%s)",
8844 bgp_path_selection_reason2str(bn
->reason
));
8849 json_object_object_add(json_path
, "bestpath", json_bestpath
);
8854 /* Line 4 display Community */
8855 if (attr
->community
) {
8857 if (!attr
->community
->json
)
8858 community_str(attr
->community
, true);
8859 json_object_lock(attr
->community
->json
);
8860 json_object_object_add(json_path
, "community",
8861 attr
->community
->json
);
8863 vty_out(vty
, " Community: %s\n",
8864 attr
->community
->str
);
8868 /* Line 5 display Extended-community */
8869 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8871 json_ext_community
= json_object_new_object();
8872 json_object_string_add(json_ext_community
, "string",
8873 attr
->ecommunity
->str
);
8874 json_object_object_add(json_path
, "extendedCommunity",
8875 json_ext_community
);
8877 vty_out(vty
, " Extended Community: %s\n",
8878 attr
->ecommunity
->str
);
8882 /* Line 6 display Large community */
8883 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8885 if (!attr
->lcommunity
->json
)
8886 lcommunity_str(attr
->lcommunity
, true);
8887 json_object_lock(attr
->lcommunity
->json
);
8888 json_object_object_add(json_path
, "largeCommunity",
8889 attr
->lcommunity
->json
);
8891 vty_out(vty
, " Large Community: %s\n",
8892 attr
->lcommunity
->str
);
8896 /* Line 7 display Originator, Cluster-id */
8897 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8898 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8899 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8901 json_object_string_add(
8902 json_path
, "originatorId",
8903 inet_ntoa(attr
->originator_id
));
8905 vty_out(vty
, " Originator: %s",
8906 inet_ntoa(attr
->originator_id
));
8909 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8913 json_cluster_list
= json_object_new_object();
8914 json_cluster_list_list
=
8915 json_object_new_array();
8917 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8919 json_string
= json_object_new_string(
8920 inet_ntoa(attr
->cluster
8922 json_object_array_add(
8923 json_cluster_list_list
,
8928 * struct cluster_list does not have
8929 * "str" variable like aspath and community
8930 * do. Add this someday if someone asks
8932 * json_object_string_add(json_cluster_list,
8933 * "string", attr->cluster->str);
8935 json_object_object_add(json_cluster_list
,
8937 json_cluster_list_list
);
8938 json_object_object_add(json_path
, "clusterList",
8941 vty_out(vty
, ", Cluster list: ");
8943 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8946 inet_ntoa(attr
->cluster
8956 if (path
->extra
&& path
->extra
->damp_info
)
8957 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
8960 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8961 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
8962 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8965 json_object_int_add(json_path
, "remoteLabel", label
);
8967 vty_out(vty
, " Remote label: %d\n", label
);
8971 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8973 json_object_int_add(json_path
, "labelIndex",
8976 vty_out(vty
, " Label Index: %d\n",
8980 /* Line 8 display Addpath IDs */
8981 if (path
->addpath_rx_id
8982 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8984 json_object_int_add(json_path
, "addpathRxId",
8985 path
->addpath_rx_id
);
8987 /* Keep backwards compatibility with the old API
8988 * by putting TX All's ID in the old field
8990 json_object_int_add(
8991 json_path
, "addpathTxId",
8993 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
8995 /* ... but create a specific field for each
8998 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8999 json_object_int_add(
9001 bgp_addpath_names(i
)->id_json_name
,
9002 path
->tx_addpath
.addpath_tx_id
[i
]);
9005 vty_out(vty
, " AddPath ID: RX %u, ",
9006 path
->addpath_rx_id
);
9008 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9012 /* If we used addpath to TX a non-bestpath we need to display
9013 * "Advertised to" on a path-by-path basis
9015 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9018 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9020 bgp_addpath_encode_tx(peer
, afi
, safi
);
9021 has_adj
= bgp_adj_out_lookup(
9023 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9024 &path
->tx_addpath
));
9026 if ((addpath_capable
&& has_adj
)
9027 || (!addpath_capable
&& has_adj
9028 && CHECK_FLAG(path
->flags
,
9029 BGP_PATH_SELECTED
))) {
9030 if (json_path
&& !json_adv_to
)
9031 json_adv_to
= json_object_new_object();
9033 route_vty_out_advertised_to(
9035 " Advertised to:", json_adv_to
);
9041 json_object_object_add(
9042 json_path
, "advertisedTo", json_adv_to
);
9051 /* Line 9 display Uptime */
9052 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9054 json_last_update
= json_object_new_object();
9055 json_object_int_add(json_last_update
, "epoch", tbuf
);
9056 json_object_string_add(json_last_update
, "string",
9058 json_object_object_add(json_path
, "lastUpdate",
9061 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9063 /* Line 10 display PMSI tunnel attribute, if present */
9064 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9066 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9067 PMSI_TNLTYPE_STR_DEFAULT
);
9070 json_pmsi
= json_object_new_object();
9071 json_object_string_add(json_pmsi
, "tunnelType", str
);
9072 json_object_int_add(json_pmsi
, "label",
9073 label2vni(&attr
->label
));
9074 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9076 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9077 str
, label2vni(&attr
->label
));
9080 /* We've constructed the json object for this path, add it to the json
9084 if (json_nexthop_global
|| json_nexthop_ll
) {
9085 json_nexthops
= json_object_new_array();
9087 if (json_nexthop_global
)
9088 json_object_array_add(json_nexthops
,
9089 json_nexthop_global
);
9091 if (json_nexthop_ll
)
9092 json_object_array_add(json_nexthops
,
9095 json_object_object_add(json_path
, "nexthops",
9099 json_object_object_add(json_path
, "peer", json_peer
);
9100 json_object_array_add(json_paths
, json_path
);
9104 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9105 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9106 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9108 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9109 const char *prefix_list_str
, afi_t afi
,
9110 safi_t safi
, enum bgp_show_type type
);
9111 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9112 const char *filter
, afi_t afi
, safi_t safi
,
9113 enum bgp_show_type type
);
9114 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9115 const char *rmap_str
, afi_t afi
, safi_t safi
,
9116 enum bgp_show_type type
);
9117 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9118 const char *com
, int exact
, afi_t afi
,
9120 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9121 const char *prefix
, afi_t afi
, safi_t safi
,
9122 enum bgp_show_type type
);
9123 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9124 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
9125 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9126 const char *comstr
, int exact
, afi_t afi
,
9127 safi_t safi
, bool use_json
);
9130 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9131 struct bgp_table
*table
, enum bgp_show_type type
,
9132 void *output_arg
, bool use_json
, char *rd
,
9133 int is_last
, unsigned long *output_cum
,
9134 unsigned long *total_cum
,
9135 unsigned long *json_header_depth
)
9137 struct bgp_path_info
*pi
;
9138 struct bgp_node
*rn
;
9141 unsigned long output_count
= 0;
9142 unsigned long total_count
= 0;
9145 json_object
*json_paths
= NULL
;
9148 if (output_cum
&& *output_cum
!= 0)
9151 if (use_json
&& !*json_header_depth
) {
9153 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9154 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9155 " \"localAS\": %u,\n \"routes\": { ",
9156 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9157 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9160 table
->version
, inet_ntoa(bgp
->router_id
),
9161 bgp
->default_local_pref
, bgp
->as
);
9162 *json_header_depth
= 2;
9164 vty_out(vty
, " \"routeDistinguishers\" : {");
9165 ++*json_header_depth
;
9169 if (use_json
&& rd
) {
9170 vty_out(vty
, " \"%s\" : { ", rd
);
9173 /* Start processing of routes. */
9174 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9175 pi
= bgp_node_get_bgp_path_info(rn
);
9181 json_paths
= json_object_new_array();
9185 for (; pi
; pi
= pi
->next
) {
9187 if (type
== bgp_show_type_flap_statistics
9188 || type
== bgp_show_type_flap_neighbor
9189 || type
== bgp_show_type_dampend_paths
9190 || type
== bgp_show_type_damp_neighbor
) {
9191 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9194 if (type
== bgp_show_type_regexp
) {
9195 regex_t
*regex
= output_arg
;
9197 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9201 if (type
== bgp_show_type_prefix_list
) {
9202 struct prefix_list
*plist
= output_arg
;
9204 if (prefix_list_apply(plist
, &rn
->p
)
9208 if (type
== bgp_show_type_filter_list
) {
9209 struct as_list
*as_list
= output_arg
;
9211 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9212 != AS_FILTER_PERMIT
)
9215 if (type
== bgp_show_type_route_map
) {
9216 struct route_map
*rmap
= output_arg
;
9217 struct bgp_path_info path
;
9218 struct attr dummy_attr
;
9219 route_map_result_t ret
;
9221 dummy_attr
= *pi
->attr
;
9223 path
.peer
= pi
->peer
;
9224 path
.attr
= &dummy_attr
;
9226 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9228 if (ret
== RMAP_DENYMATCH
)
9231 if (type
== bgp_show_type_neighbor
9232 || type
== bgp_show_type_flap_neighbor
9233 || type
== bgp_show_type_damp_neighbor
) {
9234 union sockunion
*su
= output_arg
;
9236 if (pi
->peer
== NULL
9237 || pi
->peer
->su_remote
== NULL
9238 || !sockunion_same(pi
->peer
->su_remote
, su
))
9241 if (type
== bgp_show_type_cidr_only
) {
9242 uint32_t destination
;
9244 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9245 if (IN_CLASSC(destination
)
9246 && rn
->p
.prefixlen
== 24)
9248 if (IN_CLASSB(destination
)
9249 && rn
->p
.prefixlen
== 16)
9251 if (IN_CLASSA(destination
)
9252 && rn
->p
.prefixlen
== 8)
9255 if (type
== bgp_show_type_prefix_longer
) {
9257 if (!prefix_match(p
, &rn
->p
))
9260 if (type
== bgp_show_type_community_all
) {
9261 if (!pi
->attr
->community
)
9264 if (type
== bgp_show_type_community
) {
9265 struct community
*com
= output_arg
;
9267 if (!pi
->attr
->community
9268 || !community_match(pi
->attr
->community
,
9272 if (type
== bgp_show_type_community_exact
) {
9273 struct community
*com
= output_arg
;
9275 if (!pi
->attr
->community
9276 || !community_cmp(pi
->attr
->community
, com
))
9279 if (type
== bgp_show_type_community_list
) {
9280 struct community_list
*list
= output_arg
;
9282 if (!community_list_match(pi
->attr
->community
,
9286 if (type
== bgp_show_type_community_list_exact
) {
9287 struct community_list
*list
= output_arg
;
9289 if (!community_list_exact_match(
9290 pi
->attr
->community
, list
))
9293 if (type
== bgp_show_type_lcommunity
) {
9294 struct lcommunity
*lcom
= output_arg
;
9296 if (!pi
->attr
->lcommunity
9297 || !lcommunity_match(pi
->attr
->lcommunity
,
9302 if (type
== bgp_show_type_lcommunity_exact
) {
9303 struct lcommunity
*lcom
= output_arg
;
9305 if (!pi
->attr
->lcommunity
9306 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9310 if (type
== bgp_show_type_lcommunity_list
) {
9311 struct community_list
*list
= output_arg
;
9313 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9318 == bgp_show_type_lcommunity_list_exact
) {
9319 struct community_list
*list
= output_arg
;
9321 if (!lcommunity_list_exact_match(
9322 pi
->attr
->lcommunity
, list
))
9325 if (type
== bgp_show_type_lcommunity_all
) {
9326 if (!pi
->attr
->lcommunity
)
9329 if (type
== bgp_show_type_dampend_paths
9330 || type
== bgp_show_type_damp_neighbor
) {
9331 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9332 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9336 if (!use_json
&& header
) {
9337 vty_out(vty
, "BGP table version is %" PRIu64
9338 ", local router ID is %s, vrf id ",
9340 inet_ntoa(bgp
->router_id
));
9341 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9342 vty_out(vty
, "%s", VRFID_NONE_STR
);
9344 vty_out(vty
, "%u", bgp
->vrf_id
);
9346 vty_out(vty
, "Default local pref %u, ",
9347 bgp
->default_local_pref
);
9348 vty_out(vty
, "local AS %u\n", bgp
->as
);
9349 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9350 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9351 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9352 if (type
== bgp_show_type_dampend_paths
9353 || type
== bgp_show_type_damp_neighbor
)
9354 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9355 else if (type
== bgp_show_type_flap_statistics
9356 || type
== bgp_show_type_flap_neighbor
)
9357 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9359 vty_out(vty
, BGP_SHOW_HEADER
);
9362 if (rd
!= NULL
&& !display
&& !output_count
) {
9365 "Route Distinguisher: %s\n",
9368 if (type
== bgp_show_type_dampend_paths
9369 || type
== bgp_show_type_damp_neighbor
)
9370 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9371 safi
, use_json
, json_paths
);
9372 else if (type
== bgp_show_type_flap_statistics
9373 || type
== bgp_show_type_flap_neighbor
)
9374 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9375 safi
, use_json
, json_paths
);
9377 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9389 if (p
->family
== AF_FLOWSPEC
) {
9390 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9392 bgp_fs_nlri_get_string((unsigned char *)
9393 p
->u
.prefix_flowspec
.ptr
,
9394 p
->u
.prefix_flowspec
9397 NLRI_STRING_FORMAT_MIN
,
9400 vty_out(vty
, "\"%s/%d\": ",
9402 p
->u
.prefix_flowspec
.prefixlen
);
9404 vty_out(vty
, ",\"%s/%d\": ",
9406 p
->u
.prefix_flowspec
.prefixlen
);
9408 prefix2str(p
, buf2
, sizeof(buf2
));
9410 vty_out(vty
, "\"%s\": ", buf2
);
9412 vty_out(vty
, ",\"%s\": ", buf2
);
9415 json_object_to_json_string(json_paths
));
9416 json_object_free(json_paths
);
9420 json_object_free(json_paths
);
9424 output_count
+= *output_cum
;
9425 *output_cum
= output_count
;
9428 total_count
+= *total_cum
;
9429 *total_cum
= total_count
;
9433 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9437 for (i
= 0; i
< *json_header_depth
; ++i
)
9438 vty_out(vty
, " } ");
9443 /* No route is displayed */
9444 if (output_count
== 0) {
9445 if (type
== bgp_show_type_normal
)
9447 "No BGP prefixes displayed, %ld exist\n",
9451 "\nDisplayed %ld routes and %ld total paths\n",
9452 output_count
, total_count
);
9459 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9460 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9461 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9463 struct bgp_node
*rn
, *next
;
9464 unsigned long output_cum
= 0;
9465 unsigned long total_cum
= 0;
9466 unsigned long json_header_depth
= 0;
9467 struct bgp_table
*itable
;
9470 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9472 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9473 next
= bgp_route_next(rn
);
9474 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9477 itable
= bgp_node_get_bgp_table_info(rn
);
9478 if (itable
!= NULL
) {
9479 struct prefix_rd prd
;
9480 char rd
[RD_ADDRSTRLEN
];
9482 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9483 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9484 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9485 use_json
, rd
, next
== NULL
, &output_cum
,
9486 &total_cum
, &json_header_depth
);
9492 if (output_cum
== 0)
9493 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9497 "\nDisplayed %ld routes and %ld total paths\n",
9498 output_cum
, total_cum
);
9502 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9503 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9505 struct bgp_table
*table
;
9506 unsigned long json_header_depth
= 0;
9509 bgp
= bgp_get_default();
9514 vty_out(vty
, "No BGP process is configured\n");
9516 vty_out(vty
, "{}\n");
9520 table
= bgp
->rib
[afi
][safi
];
9521 /* use MPLS and ENCAP specific shows until they are merged */
9522 if (safi
== SAFI_MPLS_VPN
) {
9523 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9524 output_arg
, use_json
);
9527 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9528 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9529 output_arg
, use_json
,
9532 /* labeled-unicast routes live in the unicast table */
9533 else if (safi
== SAFI_LABELED_UNICAST
)
9534 safi
= SAFI_UNICAST
;
9536 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9537 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9540 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9541 safi_t safi
, bool use_json
)
9543 struct listnode
*node
, *nnode
;
9546 bool route_output
= false;
9549 vty_out(vty
, "{\n");
9551 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9552 route_output
= true;
9555 vty_out(vty
, ",\n");
9559 vty_out(vty
, "\"%s\":",
9560 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9564 vty_out(vty
, "\nInstance %s:\n",
9565 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9569 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9574 vty_out(vty
, "}\n");
9575 else if (!route_output
)
9576 vty_out(vty
, "%% BGP instance not found\n");
9579 /* Header of detailed BGP route information */
9580 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9581 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9582 afi_t afi
, safi_t safi
, json_object
*json
)
9584 struct bgp_path_info
*pi
;
9587 struct listnode
*node
, *nnode
;
9588 char buf1
[RD_ADDRSTRLEN
];
9589 char buf2
[INET6_ADDRSTRLEN
];
9590 char buf3
[EVPN_ROUTE_STRLEN
];
9591 char prefix_str
[BUFSIZ
];
9596 int route_filter_translated_v4
= 0;
9597 int route_filter_v4
= 0;
9598 int route_filter_translated_v6
= 0;
9599 int route_filter_v6
= 0;
9602 int accept_own_nexthop
= 0;
9605 int no_advertise
= 0;
9609 int has_valid_label
= 0;
9610 mpls_label_t label
= 0;
9611 json_object
*json_adv_to
= NULL
;
9614 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9616 if (has_valid_label
)
9617 label
= label_pton(&rn
->local_label
);
9619 if (safi
== SAFI_EVPN
) {
9622 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9623 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9624 : "", prd
? ":" : "",
9625 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9626 buf3
, sizeof(buf3
)));
9628 json_object_string_add(json
, "rd",
9629 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9631 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9635 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9636 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9637 ? prefix_rd2str(prd
, buf1
,
9640 safi
== SAFI_MPLS_VPN
? ":" : "",
9641 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9646 json_object_string_add(json
, "prefix",
9647 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9650 if (has_valid_label
) {
9652 json_object_int_add(json
, "localLabel", label
);
9654 vty_out(vty
, "Local label: %d\n", label
);
9658 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9659 vty_out(vty
, "not allocated\n");
9661 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9663 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9665 if (pi
->extra
&& pi
->extra
->suppress
)
9668 if (pi
->attr
->community
== NULL
)
9671 no_advertise
+= community_include(
9672 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9673 no_export
+= community_include(pi
->attr
->community
,
9674 COMMUNITY_NO_EXPORT
);
9675 local_as
+= community_include(pi
->attr
->community
,
9676 COMMUNITY_LOCAL_AS
);
9677 accept_own
+= community_include(pi
->attr
->community
,
9678 COMMUNITY_ACCEPT_OWN
);
9679 route_filter_translated_v4
+= community_include(
9680 pi
->attr
->community
,
9681 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9682 route_filter_translated_v6
+= community_include(
9683 pi
->attr
->community
,
9684 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9685 route_filter_v4
+= community_include(
9686 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9687 route_filter_v6
+= community_include(
9688 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9689 llgr_stale
+= community_include(pi
->attr
->community
,
9690 COMMUNITY_LLGR_STALE
);
9691 no_llgr
+= community_include(pi
->attr
->community
,
9693 accept_own_nexthop
+=
9694 community_include(pi
->attr
->community
,
9695 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9696 blackhole
+= community_include(pi
->attr
->community
,
9697 COMMUNITY_BLACKHOLE
);
9698 no_peer
+= community_include(pi
->attr
->community
,
9704 vty_out(vty
, "Paths: (%d available", count
);
9706 vty_out(vty
, ", best #%d", best
);
9707 if (safi
== SAFI_UNICAST
) {
9708 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9709 vty_out(vty
, ", table %s",
9712 vty_out(vty
, ", vrf %s",
9716 vty_out(vty
, ", no best path");
9720 ", accept own local route exported and imported in different VRF");
9721 else if (route_filter_translated_v4
)
9723 ", mark translated RTs for VPNv4 route filtering");
9724 else if (route_filter_v4
)
9726 ", attach RT as-is for VPNv4 route filtering");
9727 else if (route_filter_translated_v6
)
9729 ", mark translated RTs for VPNv6 route filtering");
9730 else if (route_filter_v6
)
9732 ", attach RT as-is for VPNv6 route filtering");
9733 else if (llgr_stale
)
9735 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9738 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9739 else if (accept_own_nexthop
)
9741 ", accept local nexthop");
9743 vty_out(vty
, ", inform peer to blackhole prefix");
9745 vty_out(vty
, ", not advertised to EBGP peer");
9746 else if (no_advertise
)
9747 vty_out(vty
, ", not advertised to any peer");
9749 vty_out(vty
, ", not advertised outside local AS");
9752 ", inform EBGP peer not to advertise to their EBGP peers");
9756 ", Advertisements suppressed by an aggregate.");
9757 vty_out(vty
, ")\n");
9760 /* If we are not using addpath then we can display Advertised to and
9762 * show what peers we advertised the bestpath to. If we are using
9764 * though then we must display Advertised to on a path-by-path basis. */
9765 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9766 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9767 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9768 if (json
&& !json_adv_to
)
9769 json_adv_to
= json_object_new_object();
9771 route_vty_out_advertised_to(
9773 " Advertised to non peer-group peers:\n ",
9780 json_object_object_add(json
, "advertisedTo",
9785 vty_out(vty
, " Not advertised to any peer");
9791 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
9792 struct bgp_node
*bgp_node
, struct vty
*vty
,
9793 struct bgp
*bgp
, afi_t afi
,
9794 safi_t safi
, json_object
*json
,
9795 enum bgp_path_type pathtype
, int *display
)
9797 struct bgp_path_info
*pi
;
9799 char rdbuf
[RD_ADDRSTRLEN
];
9800 json_object
*json_header
= NULL
;
9801 json_object
*json_paths
= NULL
;
9803 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
9806 if (json
&& !json_paths
) {
9807 /* Instantiate json_paths only if path is valid */
9808 json_paths
= json_object_new_array();
9810 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
9811 json_header
= json_object_new_object();
9817 route_vty_out_detail_header(
9818 vty
, bgp
, bgp_node
, pfx_rd
,
9819 AFI_IP
, safi
, json_header
);
9824 if (pathtype
== BGP_PATH_SHOW_ALL
9825 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9826 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
9827 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9828 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
9829 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
9830 route_vty_out_detail(vty
, bgp
, bgp_node
,
9835 if (json
&& json_paths
) {
9836 json_object_object_add(json_header
, "paths", json_paths
);
9839 json_object_object_add(json
, rdbuf
, json_header
);
9843 /* Display specified route of BGP table. */
9844 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9845 struct bgp_table
*rib
, const char *ip_str
,
9846 afi_t afi
, safi_t safi
,
9847 struct prefix_rd
*prd
, int prefix_check
,
9848 enum bgp_path_type pathtype
, bool use_json
)
9852 struct prefix match
;
9853 struct bgp_node
*rn
;
9854 struct bgp_node
*rm
;
9855 struct bgp_table
*table
;
9856 json_object
*json
= NULL
;
9857 json_object
*json_paths
= NULL
;
9859 /* Check IP address argument. */
9860 ret
= str2prefix(ip_str
, &match
);
9862 vty_out(vty
, "address is malformed\n");
9866 match
.family
= afi2family(afi
);
9869 json
= json_object_new_object();
9871 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
9872 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9873 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9875 table
= bgp_node_get_bgp_table_info(rn
);
9879 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9883 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9884 bgp_unlock_node(rm
);
9888 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9889 vty
, bgp
, afi
, safi
, json
,
9890 pathtype
, &display
);
9892 bgp_unlock_node(rm
);
9894 } else if (safi
== SAFI_EVPN
) {
9895 struct bgp_node
*longest_pfx
;
9896 bool is_exact_pfxlen_match
= FALSE
;
9898 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9899 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9901 table
= bgp_node_get_bgp_table_info(rn
);
9906 is_exact_pfxlen_match
= FALSE
;
9908 * Search through all the prefixes for a match. The
9909 * pfx's are enumerated in ascending order of pfxlens.
9910 * So, the last pfx match is the longest match. Set
9911 * is_exact_pfxlen_match when we get exact pfxlen match
9913 for (rm
= bgp_table_top(table
); rm
;
9914 rm
= bgp_route_next(rm
)) {
9916 * Get prefixlen of the ip-prefix within type5
9919 if (evpn_type5_prefix_match(&rm
->p
,
9920 &match
) && rm
->info
) {
9923 bgp_evpn_get_type5_prefixlen(&rm
->p
);
9924 if (type5_pfxlen
== match
.prefixlen
) {
9925 is_exact_pfxlen_match
= TRUE
;
9926 bgp_unlock_node(rm
);
9935 if (prefix_check
&& !is_exact_pfxlen_match
)
9941 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9942 vty
, bgp
, afi
, safi
, json
,
9943 pathtype
, &display
);
9945 bgp_unlock_node(rm
);
9947 } else if (safi
== SAFI_FLOWSPEC
) {
9949 json_paths
= json_object_new_array();
9951 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9952 &match
, prefix_check
,
9956 if (use_json
&& display
)
9957 json_object_object_add(json
, "paths", json_paths
);
9959 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9961 || rn
->p
.prefixlen
== match
.prefixlen
) {
9962 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
9964 pathtype
, &display
);
9967 bgp_unlock_node(rn
);
9972 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9973 json
, JSON_C_TO_STRING_PRETTY
|
9974 JSON_C_TO_STRING_NOSLASHESCAPE
));
9975 json_object_free(json
);
9978 vty_out(vty
, "%% Network not in table\n");
9986 /* Display specified route of Main RIB */
9987 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9988 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9989 int prefix_check
, enum bgp_path_type pathtype
,
9993 bgp
= bgp_get_default();
9996 vty_out(vty
, "No BGP process is configured\n");
9998 vty_out(vty
, "{}\n");
10003 /* labeled-unicast routes live in the unicast table */
10004 if (safi
== SAFI_LABELED_UNICAST
)
10005 safi
= SAFI_UNICAST
;
10007 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10008 afi
, safi
, prd
, prefix_check
, pathtype
,
10012 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10013 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10014 safi_t safi
, bool uj
)
10016 struct lcommunity
*lcom
;
10022 b
= buffer_new(1024);
10023 for (i
= 0; i
< argc
; i
++) {
10025 buffer_putc(b
, ' ');
10027 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10029 buffer_putstr(b
, argv
[i
]->arg
);
10033 buffer_putc(b
, '\0');
10035 str
= buffer_getstr(b
);
10038 lcom
= lcommunity_str2com(str
);
10039 XFREE(MTYPE_TMP
, str
);
10041 vty_out(vty
, "%% Large-community malformed\n");
10042 return CMD_WARNING
;
10045 return bgp_show(vty
, bgp
, afi
, safi
,
10046 (exact
? bgp_show_type_lcommunity_exact
10047 : bgp_show_type_lcommunity
),
10051 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10052 const char *lcom
, bool exact
, afi_t afi
,
10053 safi_t safi
, bool uj
)
10055 struct community_list
*list
;
10057 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10058 LARGE_COMMUNITY_LIST_MASTER
);
10059 if (list
== NULL
) {
10060 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10062 return CMD_WARNING
;
10065 return bgp_show(vty
, bgp
, afi
, safi
,
10066 (exact
? bgp_show_type_lcommunity_list_exact
10067 : bgp_show_type_lcommunity_list
),
10071 DEFUN (show_ip_bgp_large_community_list
,
10072 show_ip_bgp_large_community_list_cmd
,
10073 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
10077 BGP_INSTANCE_HELP_STR
10079 BGP_SAFI_WITH_LABEL_HELP_STR
10080 "Display routes matching the large-community-list\n"
10081 "large-community-list number\n"
10082 "large-community-list name\n"
10083 "Exact match of the large-communities\n"
10087 afi_t afi
= AFI_IP6
;
10088 safi_t safi
= SAFI_UNICAST
;
10090 bool exact_match
= 0;
10092 if (argv_find(argv
, argc
, "ip", &idx
))
10094 if (argv_find(argv
, argc
, "view", &idx
)
10095 || argv_find(argv
, argc
, "vrf", &idx
))
10096 vrf
= argv
[++idx
]->arg
;
10097 if (argv_find(argv
, argc
, "ipv4", &idx
)
10098 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10099 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10100 if (argv_find(argv
, argc
, "unicast", &idx
)
10101 || argv_find(argv
, argc
, "multicast", &idx
))
10102 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10105 bool uj
= use_json(argc
, argv
);
10107 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10109 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10110 return CMD_WARNING
;
10113 argv_find(argv
, argc
, "large-community-list", &idx
);
10115 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10117 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10120 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10121 exact_match
, afi
, safi
, uj
);
10123 DEFUN (show_ip_bgp_large_community
,
10124 show_ip_bgp_large_community_cmd
,
10125 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10129 BGP_INSTANCE_HELP_STR
10131 BGP_SAFI_WITH_LABEL_HELP_STR
10132 "Display routes matching the large-communities\n"
10133 "List of large-community numbers\n"
10134 "Exact match of the large-communities\n"
10138 afi_t afi
= AFI_IP6
;
10139 safi_t safi
= SAFI_UNICAST
;
10141 bool exact_match
= 0;
10143 if (argv_find(argv
, argc
, "ip", &idx
))
10145 if (argv_find(argv
, argc
, "view", &idx
)
10146 || argv_find(argv
, argc
, "vrf", &idx
))
10147 vrf
= argv
[++idx
]->arg
;
10148 if (argv_find(argv
, argc
, "ipv4", &idx
)
10149 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10150 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10151 if (argv_find(argv
, argc
, "unicast", &idx
)
10152 || argv_find(argv
, argc
, "multicast", &idx
))
10153 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10156 bool uj
= use_json(argc
, argv
);
10158 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10160 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10161 return CMD_WARNING
;
10164 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10165 if (argv_find(argv
, argc
, "exact-match", &idx
))
10167 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10168 exact_match
, afi
, safi
, uj
);
10170 return bgp_show(vty
, bgp
, afi
, safi
,
10171 bgp_show_type_lcommunity_all
, NULL
, uj
);
10174 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10178 /* BGP route print out function without JSON */
10179 DEFUN (show_ip_bgp
,
10181 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10182 <dampening <parameters>\
10187 |community-list <(1-500)|WORD> [exact-match]\
10188 |A.B.C.D/M longer-prefixes\
10189 |X:X::X:X/M longer-prefixes\
10194 BGP_INSTANCE_HELP_STR
10196 BGP_SAFI_WITH_LABEL_HELP_STR
10197 "Display detailed information about dampening\n"
10198 "Display detail of configured dampening parameters\n"
10199 "Display routes matching the route-map\n"
10200 "A route-map to match on\n"
10201 "Display routes conforming to the prefix-list\n"
10202 "Prefix-list name\n"
10203 "Display routes conforming to the filter-list\n"
10204 "Regular expression access list name\n"
10205 "BGP RIB advertisement statistics\n"
10206 "Display routes matching the community-list\n"
10207 "community-list number\n"
10208 "community-list name\n"
10209 "Exact match of the communities\n"
10211 "Display route and more specific routes\n"
10213 "Display route and more specific routes\n")
10215 afi_t afi
= AFI_IP6
;
10216 safi_t safi
= SAFI_UNICAST
;
10217 int exact_match
= 0;
10218 struct bgp
*bgp
= NULL
;
10221 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10224 return CMD_WARNING
;
10226 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10227 if (argv_find(argv
, argc
, "parameters", &idx
))
10228 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10231 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10232 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10233 safi
, bgp_show_type_prefix_list
);
10235 if (argv_find(argv
, argc
, "filter-list", &idx
))
10236 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10237 safi
, bgp_show_type_filter_list
);
10239 if (argv_find(argv
, argc
, "statistics", &idx
))
10240 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10242 if (argv_find(argv
, argc
, "route-map", &idx
))
10243 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10244 safi
, bgp_show_type_route_map
);
10246 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10247 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10248 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10250 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10251 exact_match
, afi
, safi
);
10253 /* prefix-longer */
10254 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10255 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10256 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10258 bgp_show_type_prefix_longer
);
10260 return CMD_WARNING
;
10263 /* BGP route print out function with JSON */
10264 DEFUN (show_ip_bgp_json
,
10265 show_ip_bgp_json_cmd
,
10266 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10268 |dampening <flap-statistics|dampened-paths>\
10269 |community [AA:NN|local-AS|no-advertise|no-export\
10270 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10271 |accept-own|accept-own-nexthop|route-filter-v6\
10272 |route-filter-v4|route-filter-translated-v6\
10273 |route-filter-translated-v4] [exact-match]\
10278 BGP_INSTANCE_HELP_STR
10280 BGP_SAFI_WITH_LABEL_HELP_STR
10281 "Display only routes with non-natural netmasks\n"
10282 "Display detailed information about dampening\n"
10283 "Display flap statistics of routes\n"
10284 "Display paths suppressed due to dampening\n"
10285 "Display routes matching the communities\n"
10287 "Do not send outside local AS (well-known community)\n"
10288 "Do not advertise to any peer (well-known community)\n"
10289 "Do not export to next AS (well-known community)\n"
10290 "Graceful shutdown (well-known community)\n"
10291 "Do not export to any peer (well-known community)\n"
10292 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10293 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10294 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10295 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10296 "Should accept VPN route with local nexthop (well-known community)\n"
10297 "RT VPNv6 route filtering (well-known community)\n"
10298 "RT VPNv4 route filtering (well-known community)\n"
10299 "RT translated VPNv6 route filtering (well-known community)\n"
10300 "RT translated VPNv4 route filtering (well-known community)\n"
10301 "Exact match of the communities\n"
10304 afi_t afi
= AFI_IP6
;
10305 safi_t safi
= SAFI_UNICAST
;
10306 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10307 struct bgp
*bgp
= NULL
;
10309 int exact_match
= 0;
10310 bool uj
= use_json(argc
, argv
);
10315 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10318 return CMD_WARNING
;
10320 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10321 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10324 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10325 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10326 return bgp_show(vty
, bgp
, afi
, safi
,
10327 bgp_show_type_dampend_paths
, NULL
, uj
);
10328 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10329 return bgp_show(vty
, bgp
, afi
, safi
,
10330 bgp_show_type_flap_statistics
, NULL
,
10334 if (argv_find(argv
, argc
, "community", &idx
)) {
10335 char *maybecomm
= NULL
;
10336 char *community
= NULL
;
10338 if (idx
+ 1 < argc
) {
10339 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10340 maybecomm
= argv
[idx
+ 1]->arg
;
10342 maybecomm
= argv
[idx
+ 1]->text
;
10345 if (maybecomm
&& !strmatch(maybecomm
, "json")
10346 && !strmatch(maybecomm
, "exact-match"))
10347 community
= maybecomm
;
10349 if (argv_find(argv
, argc
, "exact-match", &idx
))
10353 return bgp_show_community(vty
, bgp
, community
,
10354 exact_match
, afi
, safi
, uj
);
10356 return (bgp_show(vty
, bgp
, afi
, safi
,
10357 bgp_show_type_community_all
, NULL
,
10361 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10364 DEFUN (show_ip_bgp_route
,
10365 show_ip_bgp_route_cmd
,
10366 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10367 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10371 BGP_INSTANCE_HELP_STR
10373 BGP_SAFI_WITH_LABEL_HELP_STR
10374 "Network in the BGP routing table to display\n"
10376 "Network in the BGP routing table to display\n"
10378 "Display only the bestpath\n"
10379 "Display only multipaths\n"
10382 int prefix_check
= 0;
10384 afi_t afi
= AFI_IP6
;
10385 safi_t safi
= SAFI_UNICAST
;
10386 char *prefix
= NULL
;
10387 struct bgp
*bgp
= NULL
;
10388 enum bgp_path_type path_type
;
10389 bool uj
= use_json(argc
, argv
);
10393 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10396 return CMD_WARNING
;
10400 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10401 return CMD_WARNING
;
10404 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10405 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10406 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10408 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10409 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10412 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10413 && afi
!= AFI_IP6
) {
10415 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10416 return CMD_WARNING
;
10418 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10419 && afi
!= AFI_IP
) {
10421 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10422 return CMD_WARNING
;
10425 prefix
= argv
[idx
]->arg
;
10427 /* [<bestpath|multipath>] */
10428 if (argv_find(argv
, argc
, "bestpath", &idx
))
10429 path_type
= BGP_PATH_SHOW_BESTPATH
;
10430 else if (argv_find(argv
, argc
, "multipath", &idx
))
10431 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10433 path_type
= BGP_PATH_SHOW_ALL
;
10435 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10439 DEFUN (show_ip_bgp_regexp
,
10440 show_ip_bgp_regexp_cmd
,
10441 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10445 BGP_INSTANCE_HELP_STR
10447 BGP_SAFI_WITH_LABEL_HELP_STR
10448 "Display routes matching the AS path regular expression\n"
10449 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10451 afi_t afi
= AFI_IP6
;
10452 safi_t safi
= SAFI_UNICAST
;
10453 struct bgp
*bgp
= NULL
;
10456 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10459 return CMD_WARNING
;
10461 // get index of regex
10462 argv_find(argv
, argc
, "regexp", &idx
);
10465 char *regstr
= argv_concat(argv
, argc
, idx
);
10466 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10467 bgp_show_type_regexp
);
10468 XFREE(MTYPE_TMP
, regstr
);
10472 DEFUN (show_ip_bgp_instance_all
,
10473 show_ip_bgp_instance_all_cmd
,
10474 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10478 BGP_INSTANCE_ALL_HELP_STR
10480 BGP_SAFI_WITH_LABEL_HELP_STR
10483 afi_t afi
= AFI_IP
;
10484 safi_t safi
= SAFI_UNICAST
;
10485 struct bgp
*bgp
= NULL
;
10487 bool uj
= use_json(argc
, argv
);
10492 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10495 return CMD_WARNING
;
10497 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10498 return CMD_SUCCESS
;
10501 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10502 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10507 if (!config_bgp_aspath_validate(regstr
)) {
10508 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10510 return CMD_WARNING_CONFIG_FAILED
;
10513 regex
= bgp_regcomp(regstr
);
10515 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10516 return CMD_WARNING
;
10519 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10520 bgp_regex_free(regex
);
10524 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10525 const char *prefix_list_str
, afi_t afi
,
10526 safi_t safi
, enum bgp_show_type type
)
10528 struct prefix_list
*plist
;
10530 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10531 if (plist
== NULL
) {
10532 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10534 return CMD_WARNING
;
10537 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10540 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10541 const char *filter
, afi_t afi
, safi_t safi
,
10542 enum bgp_show_type type
)
10544 struct as_list
*as_list
;
10546 as_list
= as_list_lookup(filter
);
10547 if (as_list
== NULL
) {
10548 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10550 return CMD_WARNING
;
10553 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10556 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10557 const char *rmap_str
, afi_t afi
, safi_t safi
,
10558 enum bgp_show_type type
)
10560 struct route_map
*rmap
;
10562 rmap
= route_map_lookup_by_name(rmap_str
);
10564 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10565 return CMD_WARNING
;
10568 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10571 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10572 const char *comstr
, int exact
, afi_t afi
,
10573 safi_t safi
, bool use_json
)
10575 struct community
*com
;
10578 com
= community_str2com(comstr
);
10580 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10581 return CMD_WARNING
;
10584 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10585 (exact
? bgp_show_type_community_exact
10586 : bgp_show_type_community
),
10588 community_free(&com
);
10593 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10594 const char *com
, int exact
, afi_t afi
,
10597 struct community_list
*list
;
10599 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10600 if (list
== NULL
) {
10601 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10602 return CMD_WARNING
;
10605 return bgp_show(vty
, bgp
, afi
, safi
,
10606 (exact
? bgp_show_type_community_list_exact
10607 : bgp_show_type_community_list
),
10611 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10612 const char *prefix
, afi_t afi
, safi_t safi
,
10613 enum bgp_show_type type
)
10620 ret
= str2prefix(prefix
, p
);
10622 vty_out(vty
, "%% Malformed Prefix\n");
10623 return CMD_WARNING
;
10626 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10632 BGP_STATS_MAXBITLEN
= 0,
10634 BGP_STATS_PREFIXES
,
10636 BGP_STATS_UNAGGREGATEABLE
,
10637 BGP_STATS_MAX_AGGREGATEABLE
,
10638 BGP_STATS_AGGREGATES
,
10640 BGP_STATS_ASPATH_COUNT
,
10641 BGP_STATS_ASPATH_MAXHOPS
,
10642 BGP_STATS_ASPATH_TOTHOPS
,
10643 BGP_STATS_ASPATH_MAXSIZE
,
10644 BGP_STATS_ASPATH_TOTSIZE
,
10645 BGP_STATS_ASN_HIGHEST
,
10649 static const char *const table_stats_strs
[] = {
10650 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10651 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10652 [BGP_STATS_RIB
] = "Total Advertisements",
10653 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10654 [BGP_STATS_MAX_AGGREGATEABLE
] =
10655 "Maximum aggregateable prefixes",
10656 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10657 [BGP_STATS_SPACE
] = "Address space advertised",
10658 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10659 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10660 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10661 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10662 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10663 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10664 [BGP_STATS_MAX
] = NULL
,
10667 struct bgp_table_stats
{
10668 struct bgp_table
*table
;
10669 unsigned long long counts
[BGP_STATS_MAX
];
10670 double total_space
;
10674 #define TALLY_SIGFIG 100000
10675 static unsigned long
10676 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10678 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10679 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10680 unsigned long ret
= newtot
/ count
;
10682 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10689 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10690 struct bgp_table_stats
*ts
, unsigned int space
)
10692 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10693 struct bgp_path_info
*pi
;
10698 if (!bgp_node_has_bgp_path_info_data(rn
))
10701 ts
->counts
[BGP_STATS_PREFIXES
]++;
10702 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10705 ts
->counts
[BGP_STATS_AVGPLEN
]
10706 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10707 ts
->counts
[BGP_STATS_AVGPLEN
],
10711 /* check if the prefix is included by any other announcements */
10712 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10713 prn
= bgp_node_parent_nolock(prn
);
10715 if (prn
== NULL
|| prn
== top
) {
10716 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10717 /* announced address space */
10719 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10720 } else if (bgp_node_has_bgp_path_info_data(prn
))
10721 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10724 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10725 ts
->counts
[BGP_STATS_RIB
]++;
10727 if (CHECK_FLAG(pi
->attr
->flag
,
10728 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
10729 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10731 /* as-path stats */
10732 if (pi
->attr
->aspath
) {
10733 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10734 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10735 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10737 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10739 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10740 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10742 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10743 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10745 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10746 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10748 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10749 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10750 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10752 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10753 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10754 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10757 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10758 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10763 static int bgp_table_stats_walker(struct thread
*t
)
10765 struct bgp_node
*rn
, *nrn
;
10766 struct bgp_node
*top
;
10767 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10768 unsigned int space
= 0;
10770 if (!(top
= bgp_table_top(ts
->table
)))
10773 switch (ts
->table
->afi
) {
10775 space
= IPV4_MAX_BITLEN
;
10778 space
= IPV6_MAX_BITLEN
;
10784 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10786 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10787 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10788 struct bgp_table
*table
;
10790 table
= bgp_node_get_bgp_table_info(rn
);
10794 top
= bgp_table_top(table
);
10795 for (nrn
= bgp_table_top(table
); nrn
;
10796 nrn
= bgp_route_next(nrn
))
10797 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10799 bgp_table_stats_rn(rn
, top
, ts
, space
);
10806 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10809 struct bgp_table_stats ts
;
10812 if (!bgp
->rib
[afi
][safi
]) {
10813 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10815 return CMD_WARNING
;
10818 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
10820 /* labeled-unicast routes live in the unicast table */
10821 if (safi
== SAFI_LABELED_UNICAST
)
10822 safi
= SAFI_UNICAST
;
10824 memset(&ts
, 0, sizeof(ts
));
10825 ts
.table
= bgp
->rib
[afi
][safi
];
10826 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10828 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10829 if (!table_stats_strs
[i
])
10834 case BGP_STATS_ASPATH_AVGHOPS
:
10835 case BGP_STATS_ASPATH_AVGSIZE
:
10836 case BGP_STATS_AVGPLEN
:
10837 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10838 vty_out (vty
, "%12.2f",
10839 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10842 case BGP_STATS_ASPATH_TOTHOPS
:
10843 case BGP_STATS_ASPATH_TOTSIZE
:
10844 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10845 vty_out(vty
, "%12.2f",
10847 ? (float)ts
.counts
[i
]
10849 [BGP_STATS_ASPATH_COUNT
]
10852 case BGP_STATS_TOTPLEN
:
10853 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10854 vty_out(vty
, "%12.2f",
10856 ? (float)ts
.counts
[i
]
10858 [BGP_STATS_PREFIXES
]
10861 case BGP_STATS_SPACE
:
10862 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10863 vty_out(vty
, "%12g\n", ts
.total_space
);
10865 if (afi
== AFI_IP6
) {
10866 vty_out(vty
, "%30s: ", "/32 equivalent ");
10867 vty_out(vty
, "%12g\n",
10868 ts
.total_space
* pow(2.0, -128 + 32));
10869 vty_out(vty
, "%30s: ", "/48 equivalent ");
10870 vty_out(vty
, "%12g\n",
10871 ts
.total_space
* pow(2.0, -128 + 48));
10873 vty_out(vty
, "%30s: ", "% announced ");
10874 vty_out(vty
, "%12.2f\n",
10875 ts
.total_space
* 100. * pow(2.0, -32));
10876 vty_out(vty
, "%30s: ", "/8 equivalent ");
10877 vty_out(vty
, "%12.2f\n",
10878 ts
.total_space
* pow(2.0, -32 + 8));
10879 vty_out(vty
, "%30s: ", "/24 equivalent ");
10880 vty_out(vty
, "%12.2f\n",
10881 ts
.total_space
* pow(2.0, -32 + 24));
10885 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10886 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10889 vty_out(vty
, "\n");
10891 return CMD_SUCCESS
;
10903 PCOUNT_PFCNT
, /* the figure we display to users */
10907 static const char *const pcount_strs
[] = {
10908 [PCOUNT_ADJ_IN
] = "Adj-in",
10909 [PCOUNT_DAMPED
] = "Damped",
10910 [PCOUNT_REMOVED
] = "Removed",
10911 [PCOUNT_HISTORY
] = "History",
10912 [PCOUNT_STALE
] = "Stale",
10913 [PCOUNT_VALID
] = "Valid",
10914 [PCOUNT_ALL
] = "All RIB",
10915 [PCOUNT_COUNTED
] = "PfxCt counted",
10916 [PCOUNT_PFCNT
] = "Useable",
10917 [PCOUNT_MAX
] = NULL
,
10920 struct peer_pcounts
{
10921 unsigned int count
[PCOUNT_MAX
];
10922 const struct peer
*peer
;
10923 const struct bgp_table
*table
;
10926 static int bgp_peer_count_walker(struct thread
*t
)
10928 struct bgp_node
*rn
;
10929 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10930 const struct peer
*peer
= pc
->peer
;
10932 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10933 struct bgp_adj_in
*ain
;
10934 struct bgp_path_info
*pi
;
10936 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10937 if (ain
->peer
== peer
)
10938 pc
->count
[PCOUNT_ADJ_IN
]++;
10940 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10942 if (pi
->peer
!= peer
)
10945 pc
->count
[PCOUNT_ALL
]++;
10947 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10948 pc
->count
[PCOUNT_DAMPED
]++;
10949 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10950 pc
->count
[PCOUNT_HISTORY
]++;
10951 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10952 pc
->count
[PCOUNT_REMOVED
]++;
10953 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10954 pc
->count
[PCOUNT_STALE
]++;
10955 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10956 pc
->count
[PCOUNT_VALID
]++;
10957 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10958 pc
->count
[PCOUNT_PFCNT
]++;
10960 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10961 pc
->count
[PCOUNT_COUNTED
]++;
10962 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10964 EC_LIB_DEVELOPMENT
,
10965 "Attempting to count but flags say it is unusable");
10967 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10969 EC_LIB_DEVELOPMENT
,
10970 "Not counted but flags say we should");
10977 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10978 safi_t safi
, bool use_json
)
10980 struct peer_pcounts pcounts
= {.peer
= peer
};
10982 json_object
*json
= NULL
;
10983 json_object
*json_loop
= NULL
;
10986 json
= json_object_new_object();
10987 json_loop
= json_object_new_object();
10990 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10991 || !peer
->bgp
->rib
[afi
][safi
]) {
10993 json_object_string_add(
10995 "No such neighbor or address family");
10996 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10997 json_object_free(json
);
10999 vty_out(vty
, "%% No such neighbor or address family\n");
11001 return CMD_WARNING
;
11004 memset(&pcounts
, 0, sizeof(pcounts
));
11005 pcounts
.peer
= peer
;
11006 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11008 /* in-place call via thread subsystem so as to record execution time
11009 * stats for the thread-walk (i.e. ensure this can't be blamed on
11010 * on just vty_read()).
11012 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11015 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11016 json_object_string_add(json
, "multiProtocol",
11017 get_afi_safi_str(afi
, safi
, true));
11018 json_object_int_add(json
, "pfxCounter",
11019 peer
->pcount
[afi
][safi
]);
11021 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11022 json_object_int_add(json_loop
, pcount_strs
[i
],
11025 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
11027 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11028 json_object_string_add(json
, "pfxctDriftFor",
11030 json_object_string_add(
11031 json
, "recommended",
11032 "Please report this bug, with the above command output");
11034 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11035 json
, JSON_C_TO_STRING_PRETTY
));
11036 json_object_free(json
);
11040 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
11041 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
11042 peer
->hostname
, peer
->host
,
11043 get_afi_safi_str(afi
, safi
, false));
11045 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11046 get_afi_safi_str(afi
, safi
, false));
11049 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
11050 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11052 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11053 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
11056 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11057 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
11059 "Please report this bug, with the above command output\n");
11063 return CMD_SUCCESS
;
11066 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11067 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11068 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11069 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11073 BGP_INSTANCE_HELP_STR
11076 "Detailed information on TCP and BGP neighbor connections\n"
11077 "Neighbor to display information about\n"
11078 "Neighbor to display information about\n"
11079 "Neighbor on BGP configured interface\n"
11080 "Display detailed prefix count information\n"
11083 afi_t afi
= AFI_IP6
;
11084 safi_t safi
= SAFI_UNICAST
;
11087 struct bgp
*bgp
= NULL
;
11088 bool uj
= use_json(argc
, argv
);
11093 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11096 return CMD_WARNING
;
11098 argv_find(argv
, argc
, "neighbors", &idx
);
11099 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11101 return CMD_WARNING
;
11103 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11106 #ifdef KEEP_OLD_VPN_COMMANDS
11107 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11108 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11109 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11114 "Display information about all VPNv4 NLRIs\n"
11115 "Detailed information on TCP and BGP neighbor connections\n"
11116 "Neighbor to display information about\n"
11117 "Neighbor to display information about\n"
11118 "Neighbor on BGP configured interface\n"
11119 "Display detailed prefix count information\n"
11124 bool uj
= use_json(argc
, argv
);
11126 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11128 return CMD_WARNING
;
11130 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11133 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11134 show_ip_bgp_vpn_all_route_prefix_cmd
,
11135 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11140 "Display information about all VPNv4 NLRIs\n"
11141 "Network in the BGP routing table to display\n"
11142 "Network in the BGP routing table to display\n"
11146 char *network
= NULL
;
11147 struct bgp
*bgp
= bgp_get_default();
11149 vty_out(vty
, "Can't find default instance\n");
11150 return CMD_WARNING
;
11153 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11154 network
= argv
[idx
]->arg
;
11155 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11156 network
= argv
[idx
]->arg
;
11158 vty_out(vty
, "Unable to figure out Network\n");
11159 return CMD_WARNING
;
11162 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11163 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11165 #endif /* KEEP_OLD_VPN_COMMANDS */
11167 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11168 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11169 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11174 "Network in the BGP routing table to display\n"
11175 "Network in the BGP routing table to display\n"
11176 "Network in the BGP routing table to display\n"
11177 "Network in the BGP routing table to display\n"
11181 char *network
= NULL
;
11182 int prefix_check
= 0;
11184 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11185 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11186 network
= argv
[idx
]->arg
;
11187 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11188 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11189 network
= argv
[idx
]->arg
;
11192 vty_out(vty
, "Unable to figure out Network\n");
11193 return CMD_WARNING
;
11195 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11196 prefix_check
, BGP_PATH_SHOW_ALL
,
11197 use_json(argc
, argv
));
11200 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11201 safi_t safi
, enum bgp_show_adj_route_type type
,
11202 const char *rmap_name
, bool use_json
,
11205 struct bgp_table
*table
;
11206 struct bgp_adj_in
*ain
;
11207 struct bgp_adj_out
*adj
;
11208 unsigned long output_count
;
11209 unsigned long filtered_count
;
11210 struct bgp_node
*rn
;
11216 struct update_subgroup
*subgrp
;
11217 json_object
*json_scode
= NULL
;
11218 json_object
*json_ocode
= NULL
;
11219 json_object
*json_ar
= NULL
;
11220 struct peer_af
*paf
;
11221 bool route_filtered
;
11224 json_scode
= json_object_new_object();
11225 json_ocode
= json_object_new_object();
11226 json_ar
= json_object_new_object();
11228 json_object_string_add(json_scode
, "suppressed", "s");
11229 json_object_string_add(json_scode
, "damped", "d");
11230 json_object_string_add(json_scode
, "history", "h");
11231 json_object_string_add(json_scode
, "valid", "*");
11232 json_object_string_add(json_scode
, "best", ">");
11233 json_object_string_add(json_scode
, "multipath", "=");
11234 json_object_string_add(json_scode
, "internal", "i");
11235 json_object_string_add(json_scode
, "ribFailure", "r");
11236 json_object_string_add(json_scode
, "stale", "S");
11237 json_object_string_add(json_scode
, "removed", "R");
11239 json_object_string_add(json_ocode
, "igp", "i");
11240 json_object_string_add(json_ocode
, "egp", "e");
11241 json_object_string_add(json_ocode
, "incomplete", "?");
11248 json_object_string_add(json
, "alert", "no BGP");
11249 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11250 json_object_free(json
);
11252 vty_out(vty
, "%% No bgp\n");
11256 /* labeled-unicast routes live in the unicast table */
11257 if (safi
== SAFI_LABELED_UNICAST
)
11258 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11260 table
= bgp
->rib
[afi
][safi
];
11262 output_count
= filtered_count
= 0;
11263 subgrp
= peer_subgroup(peer
, afi
, safi
);
11265 if (type
== bgp_show_adj_route_advertised
&& subgrp
11266 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11268 json_object_int_add(json
, "bgpTableVersion",
11270 json_object_string_add(json
, "bgpLocalRouterId",
11271 inet_ntoa(bgp
->router_id
));
11272 json_object_int_add(json
, "defaultLocPrf",
11273 bgp
->default_local_pref
);
11274 json_object_int_add(json
, "localAS", bgp
->as
);
11275 json_object_object_add(json
, "bgpStatusCodes",
11277 json_object_object_add(json
, "bgpOriginCodes",
11279 json_object_string_add(
11280 json
, "bgpOriginatingDefaultNetwork",
11281 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11283 vty_out(vty
, "BGP table version is %" PRIu64
11284 ", local router ID is %s, vrf id ",
11285 table
->version
, inet_ntoa(bgp
->router_id
));
11286 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11287 vty_out(vty
, "%s", VRFID_NONE_STR
);
11289 vty_out(vty
, "%u", bgp
->vrf_id
);
11290 vty_out(vty
, "\n");
11291 vty_out(vty
, "Default local pref %u, ",
11292 bgp
->default_local_pref
);
11293 vty_out(vty
, "local AS %u\n", bgp
->as
);
11294 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11295 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11296 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11298 vty_out(vty
, "Originating default network %s\n\n",
11299 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11304 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11305 if (type
== bgp_show_adj_route_received
11306 || type
== bgp_show_adj_route_filtered
) {
11307 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11308 if (ain
->peer
!= peer
)
11313 json_object_int_add(
11314 json
, "bgpTableVersion",
11316 json_object_string_add(
11318 "bgpLocalRouterId",
11321 json_object_int_add(json
,
11323 bgp
->default_local_pref
);
11324 json_object_int_add(json
,
11325 "localAS", bgp
->as
);
11326 json_object_object_add(
11327 json
, "bgpStatusCodes",
11329 json_object_object_add(
11330 json
, "bgpOriginCodes",
11334 "BGP table version is 0, local router ID is %s, vrf id ",
11337 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11343 vty_out(vty
, "\n");
11345 "Default local pref %u, ",
11346 bgp
->default_local_pref
);
11347 vty_out(vty
, "local AS %u\n",
11350 BGP_SHOW_SCODE_HEADER
);
11352 BGP_SHOW_NCODE_HEADER
);
11354 BGP_SHOW_OCODE_HEADER
);
11360 vty_out(vty
, BGP_SHOW_HEADER
);
11365 route_filtered
= false;
11367 /* Filter prefix using distribute list,
11368 * filter list or prefix list
11370 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11371 safi
)) == FILTER_DENY
)
11372 route_filtered
= true;
11374 /* Filter prefix using route-map */
11375 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11376 afi
, safi
, rmap_name
, NULL
, 0,
11379 if (type
== bgp_show_adj_route_filtered
&&
11380 !route_filtered
&& ret
!= RMAP_DENY
) {
11381 bgp_attr_undup(&attr
, ain
->attr
);
11385 if (type
== bgp_show_adj_route_received
&&
11386 (route_filtered
|| ret
== RMAP_DENY
))
11389 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11390 use_json
, json_ar
);
11391 bgp_attr_undup(&attr
, ain
->attr
);
11394 } else if (type
== bgp_show_adj_route_advertised
) {
11395 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11396 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11397 if (paf
->peer
!= peer
|| !adj
->attr
)
11402 json_object_int_add(
11406 json_object_string_add(
11408 "bgpLocalRouterId",
11411 json_object_int_add(
11412 json
, "defaultLocPrf",
11413 bgp
->default_local_pref
11415 json_object_int_add(
11418 json_object_object_add(
11422 json_object_object_add(
11428 "BGP table version is %" PRIu64
11429 ", local router ID is %s, vrf id ",
11442 vty_out(vty
, "\n");
11444 "Default local pref %u, ",
11445 bgp
->default_local_pref
11451 BGP_SHOW_SCODE_HEADER
);
11453 BGP_SHOW_NCODE_HEADER
);
11455 BGP_SHOW_OCODE_HEADER
);
11467 ret
= bgp_output_modifier(
11468 peer
, &rn
->p
, &attr
, afi
, safi
,
11471 if (ret
!= RMAP_DENY
) {
11472 route_vty_out_tmp(vty
, &rn
->p
,
11481 bgp_attr_undup(&attr
, adj
->attr
);
11487 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11488 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11489 json_object_int_add(json
, "filteredPrefixCounter",
11492 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11493 json
, JSON_C_TO_STRING_PRETTY
));
11494 json_object_free(json
);
11495 } else if (output_count
> 0) {
11496 if (filtered_count
> 0)
11498 "\nTotal number of prefixes %ld (%ld filtered)\n",
11499 output_count
, filtered_count
);
11501 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11506 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11507 safi_t safi
, enum bgp_show_adj_route_type type
,
11508 const char *rmap_name
, bool use_json
)
11510 json_object
*json
= NULL
;
11513 json
= json_object_new_object();
11515 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11517 json_object_string_add(
11519 "No such neighbor or address family");
11520 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11521 json_object_free(json
);
11523 vty_out(vty
, "%% No such neighbor or address family\n");
11525 return CMD_WARNING
;
11528 if ((type
== bgp_show_adj_route_received
11529 || type
== bgp_show_adj_route_filtered
)
11530 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11531 PEER_FLAG_SOFT_RECONFIG
)) {
11533 json_object_string_add(
11535 "Inbound soft reconfiguration not enabled");
11536 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11537 json_object_free(json
);
11540 "%% Inbound soft reconfiguration not enabled\n");
11542 return CMD_WARNING
;
11545 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11547 return CMD_SUCCESS
;
11550 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11551 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11552 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11553 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11557 BGP_INSTANCE_HELP_STR
11559 BGP_SAFI_WITH_LABEL_HELP_STR
11560 "Detailed information on TCP and BGP neighbor connections\n"
11561 "Neighbor to display information about\n"
11562 "Neighbor to display information about\n"
11563 "Neighbor on BGP configured interface\n"
11564 "Display the routes advertised to a BGP neighbor\n"
11565 "Display the received routes from neighbor\n"
11566 "Display the filtered routes received from neighbor\n"
11567 "Route-map to modify the attributes\n"
11568 "Name of the route map\n"
11571 afi_t afi
= AFI_IP6
;
11572 safi_t safi
= SAFI_UNICAST
;
11573 char *rmap_name
= NULL
;
11574 char *peerstr
= NULL
;
11575 struct bgp
*bgp
= NULL
;
11577 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11579 bool uj
= use_json(argc
, argv
);
11584 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11587 return CMD_WARNING
;
11589 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11590 argv_find(argv
, argc
, "neighbors", &idx
);
11591 peerstr
= argv
[++idx
]->arg
;
11593 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11595 return CMD_WARNING
;
11597 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11598 type
= bgp_show_adj_route_advertised
;
11599 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11600 type
= bgp_show_adj_route_received
;
11601 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11602 type
= bgp_show_adj_route_filtered
;
11604 if (argv_find(argv
, argc
, "route-map", &idx
))
11605 rmap_name
= argv
[++idx
]->arg
;
11607 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11610 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11611 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11612 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11618 "Address Family modifier\n"
11619 "Detailed information on TCP and BGP neighbor connections\n"
11620 "Neighbor to display information about\n"
11621 "Neighbor to display information about\n"
11622 "Neighbor on BGP configured interface\n"
11623 "Display information received from a BGP neighbor\n"
11624 "Display the prefixlist filter\n"
11627 afi_t afi
= AFI_IP6
;
11628 safi_t safi
= SAFI_UNICAST
;
11629 char *peerstr
= NULL
;
11632 union sockunion su
;
11638 /* show [ip] bgp */
11639 if (argv_find(argv
, argc
, "ip", &idx
))
11641 /* [<ipv4|ipv6> [unicast]] */
11642 if (argv_find(argv
, argc
, "ipv4", &idx
))
11644 if (argv_find(argv
, argc
, "ipv6", &idx
))
11646 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11647 argv_find(argv
, argc
, "neighbors", &idx
);
11648 peerstr
= argv
[++idx
]->arg
;
11650 bool uj
= use_json(argc
, argv
);
11652 ret
= str2sockunion(peerstr
, &su
);
11654 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11657 vty_out(vty
, "{}\n");
11660 "%% Malformed address or name: %s\n",
11662 return CMD_WARNING
;
11665 peer
= peer_lookup(NULL
, &su
);
11668 vty_out(vty
, "{}\n");
11670 vty_out(vty
, "No peer\n");
11671 return CMD_WARNING
;
11675 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11676 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11679 vty_out(vty
, "Address Family: %s\n",
11680 get_afi_safi_str(afi
, safi
, false));
11681 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11684 vty_out(vty
, "{}\n");
11686 vty_out(vty
, "No functional output\n");
11689 return CMD_SUCCESS
;
11692 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11693 afi_t afi
, safi_t safi
,
11694 enum bgp_show_type type
, bool use_json
)
11696 /* labeled-unicast routes live in the unicast table */
11697 if (safi
== SAFI_LABELED_UNICAST
)
11698 safi
= SAFI_UNICAST
;
11700 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11702 json_object
*json_no
= NULL
;
11703 json_no
= json_object_new_object();
11704 json_object_string_add(
11705 json_no
, "warning",
11706 "No such neighbor or address family");
11707 vty_out(vty
, "%s\n",
11708 json_object_to_json_string(json_no
));
11709 json_object_free(json_no
);
11711 vty_out(vty
, "%% No such neighbor or address family\n");
11712 return CMD_WARNING
;
11715 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11718 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11719 show_ip_bgp_flowspec_routes_detailed_cmd
,
11720 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11724 BGP_INSTANCE_HELP_STR
11727 "Detailed information on flowspec entries\n"
11730 afi_t afi
= AFI_IP
;
11731 safi_t safi
= SAFI_UNICAST
;
11732 struct bgp
*bgp
= NULL
;
11734 bool uj
= use_json(argc
, argv
);
11739 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11742 return CMD_WARNING
;
11744 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11747 DEFUN (show_ip_bgp_neighbor_routes
,
11748 show_ip_bgp_neighbor_routes_cmd
,
11749 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11750 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11754 BGP_INSTANCE_HELP_STR
11756 BGP_SAFI_WITH_LABEL_HELP_STR
11757 "Detailed information on TCP and BGP neighbor connections\n"
11758 "Neighbor to display information about\n"
11759 "Neighbor to display information about\n"
11760 "Neighbor on BGP configured interface\n"
11761 "Display flap statistics of the routes learned from neighbor\n"
11762 "Display the dampened routes received from neighbor\n"
11763 "Display routes learned from neighbor\n"
11766 char *peerstr
= NULL
;
11767 struct bgp
*bgp
= NULL
;
11768 afi_t afi
= AFI_IP6
;
11769 safi_t safi
= SAFI_UNICAST
;
11771 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11773 bool uj
= use_json(argc
, argv
);
11778 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11781 return CMD_WARNING
;
11783 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11784 argv_find(argv
, argc
, "neighbors", &idx
);
11785 peerstr
= argv
[++idx
]->arg
;
11787 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11789 return CMD_WARNING
;
11791 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11792 sh_type
= bgp_show_type_flap_neighbor
;
11793 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11794 sh_type
= bgp_show_type_damp_neighbor
;
11795 else if (argv_find(argv
, argc
, "routes", &idx
))
11796 sh_type
= bgp_show_type_neighbor
;
11798 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11801 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11803 struct bgp_distance
{
11804 /* Distance value for the IP source prefix. */
11807 /* Name of the access-list to be matched. */
11811 DEFUN (show_bgp_afi_vpn_rd_route
,
11812 show_bgp_afi_vpn_rd_route_cmd
,
11813 "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]",
11817 "Address Family modifier\n"
11818 "Display information for a route distinguisher\n"
11819 "Route Distinguisher\n"
11820 "Network in the BGP routing table to display\n"
11821 "Network in the BGP routing table to display\n"
11825 struct prefix_rd prd
;
11826 afi_t afi
= AFI_MAX
;
11829 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11830 vty_out(vty
, "%% Malformed Address Family\n");
11831 return CMD_WARNING
;
11834 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11836 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11837 return CMD_WARNING
;
11840 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11841 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11844 static struct bgp_distance
*bgp_distance_new(void)
11846 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11849 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11851 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11854 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11855 const char *ip_str
, const char *access_list_str
)
11862 struct bgp_node
*rn
;
11863 struct bgp_distance
*bdistance
;
11865 afi
= bgp_node_afi(vty
);
11866 safi
= bgp_node_safi(vty
);
11868 ret
= str2prefix(ip_str
, &p
);
11870 vty_out(vty
, "Malformed prefix\n");
11871 return CMD_WARNING_CONFIG_FAILED
;
11874 distance
= atoi(distance_str
);
11876 /* Get BGP distance node. */
11877 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11878 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11880 bgp_unlock_node(rn
);
11882 bdistance
= bgp_distance_new();
11883 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11886 /* Set distance value. */
11887 bdistance
->distance
= distance
;
11889 /* Reset access-list configuration. */
11890 if (bdistance
->access_list
) {
11891 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11892 bdistance
->access_list
= NULL
;
11894 if (access_list_str
)
11895 bdistance
->access_list
=
11896 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11898 return CMD_SUCCESS
;
11901 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11902 const char *ip_str
, const char *access_list_str
)
11909 struct bgp_node
*rn
;
11910 struct bgp_distance
*bdistance
;
11912 afi
= bgp_node_afi(vty
);
11913 safi
= bgp_node_safi(vty
);
11915 ret
= str2prefix(ip_str
, &p
);
11917 vty_out(vty
, "Malformed prefix\n");
11918 return CMD_WARNING_CONFIG_FAILED
;
11921 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11922 (struct prefix
*)&p
);
11924 vty_out(vty
, "Can't find specified prefix\n");
11925 return CMD_WARNING_CONFIG_FAILED
;
11928 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11929 distance
= atoi(distance_str
);
11931 if (bdistance
->distance
!= distance
) {
11932 vty_out(vty
, "Distance does not match configured\n");
11933 return CMD_WARNING_CONFIG_FAILED
;
11936 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11937 bgp_distance_free(bdistance
);
11939 bgp_node_set_bgp_path_info(rn
, NULL
);
11940 bgp_unlock_node(rn
);
11941 bgp_unlock_node(rn
);
11943 return CMD_SUCCESS
;
11946 /* Apply BGP information to distance method. */
11947 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11948 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11950 struct bgp_node
*rn
;
11953 struct bgp_distance
*bdistance
;
11954 struct access_list
*alist
;
11955 struct bgp_static
*bgp_static
;
11960 peer
= pinfo
->peer
;
11962 if (pinfo
->attr
->distance
)
11963 return pinfo
->attr
->distance
;
11965 /* Check source address. */
11966 sockunion2hostprefix(&peer
->su
, &q
);
11967 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11969 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11970 bgp_unlock_node(rn
);
11972 if (bdistance
->access_list
) {
11973 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11975 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11976 return bdistance
->distance
;
11978 return bdistance
->distance
;
11981 /* Backdoor check. */
11982 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11984 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11985 bgp_unlock_node(rn
);
11987 if (bgp_static
->backdoor
) {
11988 if (bgp
->distance_local
[afi
][safi
])
11989 return bgp
->distance_local
[afi
][safi
];
11991 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11995 if (peer
->sort
== BGP_PEER_EBGP
) {
11996 if (bgp
->distance_ebgp
[afi
][safi
])
11997 return bgp
->distance_ebgp
[afi
][safi
];
11998 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
12000 if (bgp
->distance_ibgp
[afi
][safi
])
12001 return bgp
->distance_ibgp
[afi
][safi
];
12002 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12006 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12007 * we should tell ZEBRA update the routes for a specific
12008 * AFI/SAFI to reflect changes in RIB.
12010 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
12012 safi_t update_safi
)
12017 FOREACH_AFI_SAFI (afi
, safi
) {
12018 if (!bgp_fibupd_safi(safi
))
12021 if (afi
!= update_afi
&& safi
!= update_safi
)
12024 if (BGP_DEBUG(zebra
, ZEBRA
))
12026 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12027 __func__
, afi
, safi
);
12028 bgp_zebra_announce_table(bgp
, afi
, safi
);
12032 DEFUN (bgp_distance
,
12034 "distance bgp (1-255) (1-255) (1-255)",
12035 "Define an administrative distance\n"
12037 "Distance for routes external to the AS\n"
12038 "Distance for routes internal to the AS\n"
12039 "Distance for local routes\n")
12041 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12042 int idx_number
= 2;
12043 int idx_number_2
= 3;
12044 int idx_number_3
= 4;
12045 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
12046 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
12047 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
12051 afi
= bgp_node_afi(vty
);
12052 safi
= bgp_node_safi(vty
);
12054 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
12055 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
12056 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
12057 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
12058 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
12059 bgp
->distance_local
[afi
][safi
] = distance_local
;
12060 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12062 return CMD_SUCCESS
;
12065 DEFUN (no_bgp_distance
,
12066 no_bgp_distance_cmd
,
12067 "no distance bgp [(1-255) (1-255) (1-255)]",
12069 "Define an administrative distance\n"
12071 "Distance for routes external to the AS\n"
12072 "Distance for routes internal to the AS\n"
12073 "Distance for local routes\n")
12075 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12079 afi
= bgp_node_afi(vty
);
12080 safi
= bgp_node_safi(vty
);
12082 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12083 || bgp
->distance_ibgp
[afi
][safi
] != 0
12084 || bgp
->distance_local
[afi
][safi
] != 0) {
12085 bgp
->distance_ebgp
[afi
][safi
] = 0;
12086 bgp
->distance_ibgp
[afi
][safi
] = 0;
12087 bgp
->distance_local
[afi
][safi
] = 0;
12088 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12090 return CMD_SUCCESS
;
12094 DEFUN (bgp_distance_source
,
12095 bgp_distance_source_cmd
,
12096 "distance (1-255) A.B.C.D/M",
12097 "Define an administrative distance\n"
12098 "Administrative distance\n"
12099 "IP source prefix\n")
12101 int idx_number
= 1;
12102 int idx_ipv4_prefixlen
= 2;
12103 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12104 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12105 return CMD_SUCCESS
;
12108 DEFUN (no_bgp_distance_source
,
12109 no_bgp_distance_source_cmd
,
12110 "no distance (1-255) A.B.C.D/M",
12112 "Define an administrative distance\n"
12113 "Administrative distance\n"
12114 "IP source prefix\n")
12116 int idx_number
= 2;
12117 int idx_ipv4_prefixlen
= 3;
12118 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12119 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12120 return CMD_SUCCESS
;
12123 DEFUN (bgp_distance_source_access_list
,
12124 bgp_distance_source_access_list_cmd
,
12125 "distance (1-255) A.B.C.D/M WORD",
12126 "Define an administrative distance\n"
12127 "Administrative distance\n"
12128 "IP source prefix\n"
12129 "Access list name\n")
12131 int idx_number
= 1;
12132 int idx_ipv4_prefixlen
= 2;
12134 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12135 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12136 return CMD_SUCCESS
;
12139 DEFUN (no_bgp_distance_source_access_list
,
12140 no_bgp_distance_source_access_list_cmd
,
12141 "no distance (1-255) A.B.C.D/M WORD",
12143 "Define an administrative distance\n"
12144 "Administrative distance\n"
12145 "IP source prefix\n"
12146 "Access list name\n")
12148 int idx_number
= 2;
12149 int idx_ipv4_prefixlen
= 3;
12151 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12152 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12153 return CMD_SUCCESS
;
12156 DEFUN (ipv6_bgp_distance_source
,
12157 ipv6_bgp_distance_source_cmd
,
12158 "distance (1-255) X:X::X:X/M",
12159 "Define an administrative distance\n"
12160 "Administrative distance\n"
12161 "IP source prefix\n")
12163 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12164 return CMD_SUCCESS
;
12167 DEFUN (no_ipv6_bgp_distance_source
,
12168 no_ipv6_bgp_distance_source_cmd
,
12169 "no distance (1-255) X:X::X:X/M",
12171 "Define an administrative distance\n"
12172 "Administrative distance\n"
12173 "IP source prefix\n")
12175 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12176 return CMD_SUCCESS
;
12179 DEFUN (ipv6_bgp_distance_source_access_list
,
12180 ipv6_bgp_distance_source_access_list_cmd
,
12181 "distance (1-255) X:X::X:X/M WORD",
12182 "Define an administrative distance\n"
12183 "Administrative distance\n"
12184 "IP source prefix\n"
12185 "Access list name\n")
12187 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12188 return CMD_SUCCESS
;
12191 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12192 no_ipv6_bgp_distance_source_access_list_cmd
,
12193 "no distance (1-255) X:X::X:X/M WORD",
12195 "Define an administrative distance\n"
12196 "Administrative distance\n"
12197 "IP source prefix\n"
12198 "Access list name\n")
12200 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12201 return CMD_SUCCESS
;
12204 DEFUN (bgp_damp_set
,
12206 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12207 "BGP Specific commands\n"
12208 "Enable route-flap dampening\n"
12209 "Half-life time for the penalty\n"
12210 "Value to start reusing a route\n"
12211 "Value to start suppressing a route\n"
12212 "Maximum duration to suppress a stable route\n")
12214 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12215 int idx_half_life
= 2;
12217 int idx_suppress
= 4;
12218 int idx_max_suppress
= 5;
12219 int half
= DEFAULT_HALF_LIFE
* 60;
12220 int reuse
= DEFAULT_REUSE
;
12221 int suppress
= DEFAULT_SUPPRESS
;
12222 int max
= 4 * half
;
12225 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12226 reuse
= atoi(argv
[idx_reuse
]->arg
);
12227 suppress
= atoi(argv
[idx_suppress
]->arg
);
12228 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12229 } else if (argc
== 3) {
12230 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12235 * These can't be 0 but our SA doesn't understand the
12236 * way our cli is constructed
12240 if (suppress
< reuse
) {
12242 "Suppress value cannot be less than reuse value \n");
12246 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12247 reuse
, suppress
, max
);
12250 DEFUN (bgp_damp_unset
,
12251 bgp_damp_unset_cmd
,
12252 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12254 "BGP Specific commands\n"
12255 "Enable route-flap dampening\n"
12256 "Half-life time for the penalty\n"
12257 "Value to start reusing a route\n"
12258 "Value to start suppressing a route\n"
12259 "Maximum duration to suppress a stable route\n")
12261 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12262 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12265 /* Display specified route of BGP table. */
12266 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12267 const char *ip_str
, afi_t afi
, safi_t safi
,
12268 struct prefix_rd
*prd
, int prefix_check
)
12271 struct prefix match
;
12272 struct bgp_node
*rn
;
12273 struct bgp_node
*rm
;
12274 struct bgp_path_info
*pi
;
12275 struct bgp_path_info
*pi_temp
;
12277 struct bgp_table
*table
;
12279 /* BGP structure lookup. */
12281 bgp
= bgp_lookup_by_name(view_name
);
12283 vty_out(vty
, "%% Can't find BGP instance %s\n",
12285 return CMD_WARNING
;
12288 bgp
= bgp_get_default();
12290 vty_out(vty
, "%% No BGP process is configured\n");
12291 return CMD_WARNING
;
12295 /* Check IP address argument. */
12296 ret
= str2prefix(ip_str
, &match
);
12298 vty_out(vty
, "%% address is malformed\n");
12299 return CMD_WARNING
;
12302 match
.family
= afi2family(afi
);
12304 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12305 || (safi
== SAFI_EVPN
)) {
12306 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12307 rn
= bgp_route_next(rn
)) {
12308 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12310 table
= bgp_node_get_bgp_table_info(rn
);
12313 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12317 || rm
->p
.prefixlen
== match
.prefixlen
) {
12318 pi
= bgp_node_get_bgp_path_info(rm
);
12320 if (pi
->extra
&& pi
->extra
->damp_info
) {
12321 pi_temp
= pi
->next
;
12322 bgp_damp_info_free(
12323 pi
->extra
->damp_info
,
12331 bgp_unlock_node(rm
);
12334 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12337 || rn
->p
.prefixlen
== match
.prefixlen
) {
12338 pi
= bgp_node_get_bgp_path_info(rn
);
12340 if (pi
->extra
&& pi
->extra
->damp_info
) {
12341 pi_temp
= pi
->next
;
12342 bgp_damp_info_free(
12343 pi
->extra
->damp_info
,
12351 bgp_unlock_node(rn
);
12355 return CMD_SUCCESS
;
12358 DEFUN (clear_ip_bgp_dampening
,
12359 clear_ip_bgp_dampening_cmd
,
12360 "clear ip bgp dampening",
12364 "Clear route flap dampening information\n")
12366 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
12367 return CMD_SUCCESS
;
12370 DEFUN (clear_ip_bgp_dampening_prefix
,
12371 clear_ip_bgp_dampening_prefix_cmd
,
12372 "clear ip bgp dampening A.B.C.D/M",
12376 "Clear route flap dampening information\n"
12379 int idx_ipv4_prefixlen
= 4;
12380 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12381 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12384 DEFUN (clear_ip_bgp_dampening_address
,
12385 clear_ip_bgp_dampening_address_cmd
,
12386 "clear ip bgp dampening A.B.C.D",
12390 "Clear route flap dampening information\n"
12391 "Network to clear damping information\n")
12394 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12395 SAFI_UNICAST
, NULL
, 0);
12398 DEFUN (clear_ip_bgp_dampening_address_mask
,
12399 clear_ip_bgp_dampening_address_mask_cmd
,
12400 "clear ip bgp dampening A.B.C.D A.B.C.D",
12404 "Clear route flap dampening information\n"
12405 "Network to clear damping information\n"
12409 int idx_ipv4_2
= 5;
12411 char prefix_str
[BUFSIZ
];
12413 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12416 vty_out(vty
, "%% Inconsistent address and mask\n");
12417 return CMD_WARNING
;
12420 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12424 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12426 struct vty
*vty
= arg
;
12427 struct peer
*peer
= bucket
->data
;
12428 char buf
[SU_ADDRSTRLEN
];
12430 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12431 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12434 DEFUN (show_bgp_peerhash
,
12435 show_bgp_peerhash_cmd
,
12436 "show bgp peerhash",
12439 "Display information about the BGP peerhash\n")
12441 struct list
*instances
= bm
->bgp
;
12442 struct listnode
*node
;
12445 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12446 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12447 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12451 return CMD_SUCCESS
;
12454 /* also used for encap safi */
12455 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12456 afi_t afi
, safi_t safi
)
12458 struct bgp_node
*prn
;
12459 struct bgp_node
*rn
;
12460 struct bgp_table
*table
;
12462 struct prefix_rd
*prd
;
12463 struct bgp_static
*bgp_static
;
12464 mpls_label_t label
;
12465 char buf
[SU_ADDRSTRLEN
];
12466 char rdbuf
[RD_ADDRSTRLEN
];
12468 /* Network configuration. */
12469 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12470 prn
= bgp_route_next(prn
)) {
12471 table
= bgp_node_get_bgp_table_info(prn
);
12475 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12476 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12477 if (bgp_static
== NULL
)
12481 prd
= (struct prefix_rd
*)&prn
->p
;
12483 /* "network" configuration display. */
12484 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12485 label
= decode_label(&bgp_static
->label
);
12487 vty_out(vty
, " network %s/%d rd %s",
12488 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12490 p
->prefixlen
, rdbuf
);
12491 if (safi
== SAFI_MPLS_VPN
)
12492 vty_out(vty
, " label %u", label
);
12494 if (bgp_static
->rmap
.name
)
12495 vty_out(vty
, " route-map %s",
12496 bgp_static
->rmap
.name
);
12498 if (bgp_static
->backdoor
)
12499 vty_out(vty
, " backdoor");
12501 vty_out(vty
, "\n");
12506 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12507 afi_t afi
, safi_t safi
)
12509 struct bgp_node
*prn
;
12510 struct bgp_node
*rn
;
12511 struct bgp_table
*table
;
12513 struct prefix_rd
*prd
;
12514 struct bgp_static
*bgp_static
;
12515 char buf
[PREFIX_STRLEN
* 2];
12516 char buf2
[SU_ADDRSTRLEN
];
12517 char rdbuf
[RD_ADDRSTRLEN
];
12519 /* Network configuration. */
12520 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12521 prn
= bgp_route_next(prn
)) {
12522 table
= bgp_node_get_bgp_table_info(prn
);
12526 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12527 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12528 if (bgp_static
== NULL
)
12531 char *macrouter
= NULL
;
12534 if (bgp_static
->router_mac
)
12535 macrouter
= prefix_mac2str(
12536 bgp_static
->router_mac
, NULL
, 0);
12537 if (bgp_static
->eth_s_id
)
12538 esi
= esi2str(bgp_static
->eth_s_id
);
12540 prd
= (struct prefix_rd
*)&prn
->p
;
12542 /* "network" configuration display. */
12543 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12544 if (p
->u
.prefix_evpn
.route_type
== 5) {
12545 char local_buf
[PREFIX_STRLEN
];
12546 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12547 struct prefix_evpn
*)p
)
12551 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12552 local_buf
, PREFIX_STRLEN
);
12553 sprintf(buf
, "%s/%u", local_buf
,
12554 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12556 prefix2str(p
, buf
, sizeof(buf
));
12559 if (bgp_static
->gatewayIp
.family
== AF_INET
12560 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12561 inet_ntop(bgp_static
->gatewayIp
.family
,
12562 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12565 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12567 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12568 decode_label(&bgp_static
->label
), esi
, buf2
,
12571 XFREE(MTYPE_TMP
, macrouter
);
12572 XFREE(MTYPE_TMP
, esi
);
12577 /* Configuration of static route announcement and aggregate
12579 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12582 struct bgp_node
*rn
;
12584 struct bgp_static
*bgp_static
;
12585 struct bgp_aggregate
*bgp_aggregate
;
12586 char buf
[SU_ADDRSTRLEN
];
12588 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12589 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12593 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12594 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12598 /* Network configuration. */
12599 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12600 rn
= bgp_route_next(rn
)) {
12601 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12602 if (bgp_static
== NULL
)
12607 vty_out(vty
, " network %s/%d",
12608 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12611 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12612 vty_out(vty
, " label-index %u",
12613 bgp_static
->label_index
);
12615 if (bgp_static
->rmap
.name
)
12616 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12618 if (bgp_static
->backdoor
)
12619 vty_out(vty
, " backdoor");
12621 vty_out(vty
, "\n");
12624 /* Aggregate-address configuration. */
12625 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12626 rn
= bgp_route_next(rn
)) {
12627 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12628 if (bgp_aggregate
== NULL
)
12633 vty_out(vty
, " aggregate-address %s/%d",
12634 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12637 if (bgp_aggregate
->as_set
)
12638 vty_out(vty
, " as-set");
12640 if (bgp_aggregate
->summary_only
)
12641 vty_out(vty
, " summary-only");
12643 if (bgp_aggregate
->rmap
.name
)
12644 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12646 vty_out(vty
, "\n");
12650 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12653 struct bgp_node
*rn
;
12654 struct bgp_distance
*bdistance
;
12656 /* Distance configuration. */
12657 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12658 && bgp
->distance_local
[afi
][safi
]
12659 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12660 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12661 || bgp
->distance_local
[afi
][safi
]
12662 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12663 vty_out(vty
, " distance bgp %d %d %d\n",
12664 bgp
->distance_ebgp
[afi
][safi
],
12665 bgp
->distance_ibgp
[afi
][safi
],
12666 bgp
->distance_local
[afi
][safi
]);
12669 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12670 rn
= bgp_route_next(rn
)) {
12671 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12672 if (bdistance
!= NULL
) {
12673 char buf
[PREFIX_STRLEN
];
12675 vty_out(vty
, " distance %d %s %s\n",
12676 bdistance
->distance
,
12677 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12678 bdistance
->access_list
? bdistance
->access_list
12684 /* Allocate routing table structure and install commands. */
12685 void bgp_route_init(void)
12690 /* Init BGP distance table. */
12691 FOREACH_AFI_SAFI (afi
, safi
)
12692 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12694 /* IPv4 BGP commands. */
12695 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12696 install_element(BGP_NODE
, &bgp_network_cmd
);
12697 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12699 install_element(BGP_NODE
, &aggregate_address_cmd
);
12700 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12701 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12702 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12704 /* IPv4 unicast configuration. */
12705 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12706 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12707 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12709 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12710 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12711 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12712 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12714 /* IPv4 multicast configuration. */
12715 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12716 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12717 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12718 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12719 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12720 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12721 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12723 /* IPv4 labeled-unicast configuration. */
12724 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12725 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12726 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12727 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12728 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12730 install_element(VIEW_NODE
,
12731 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12732 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12733 install_element(VIEW_NODE
,
12734 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12735 #ifdef KEEP_OLD_VPN_COMMANDS
12736 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12737 #endif /* KEEP_OLD_VPN_COMMANDS */
12738 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12739 install_element(VIEW_NODE
,
12740 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
12742 /* BGP dampening clear commands */
12743 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12744 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12746 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12747 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12750 install_element(ENABLE_NODE
,
12751 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12752 #ifdef KEEP_OLD_VPN_COMMANDS
12753 install_element(ENABLE_NODE
,
12754 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12755 #endif /* KEEP_OLD_VPN_COMMANDS */
12757 /* New config IPv6 BGP commands. */
12758 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12759 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12760 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12762 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12763 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12765 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12767 install_element(BGP_NODE
, &bgp_distance_cmd
);
12768 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12769 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12770 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12771 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12772 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12773 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12774 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12775 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12776 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12777 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12778 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12779 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12780 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12781 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12782 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12783 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12784 install_element(BGP_IPV4M_NODE
,
12785 &no_bgp_distance_source_access_list_cmd
);
12786 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12787 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12788 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12789 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12790 install_element(BGP_IPV6_NODE
,
12791 &ipv6_bgp_distance_source_access_list_cmd
);
12792 install_element(BGP_IPV6_NODE
,
12793 &no_ipv6_bgp_distance_source_access_list_cmd
);
12794 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12795 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12796 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12797 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12798 install_element(BGP_IPV6M_NODE
,
12799 &ipv6_bgp_distance_source_access_list_cmd
);
12800 install_element(BGP_IPV6M_NODE
,
12801 &no_ipv6_bgp_distance_source_access_list_cmd
);
12803 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12804 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12805 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12806 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12808 /* IPv4 Multicast Mode */
12809 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12810 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12812 /* Large Communities */
12813 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12814 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12816 /* show bgp ipv4 flowspec detailed */
12817 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12819 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12822 void bgp_route_finish(void)
12827 FOREACH_AFI_SAFI (afi
, safi
) {
12828 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12829 bgp_distance_table
[afi
][safi
] = NULL
;