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_hostname(struct peer
*peer
, struct attr
*attr
)
7153 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)
7154 && !(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))
7155 return peer
->hostname
;
7159 /* called from terminal list command */
7160 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7161 struct bgp_path_info
*path
, int display
, safi_t safi
,
7162 json_object
*json_paths
)
7164 struct attr
*attr
= path
->attr
;
7165 json_object
*json_path
= NULL
;
7166 json_object
*json_nexthops
= NULL
;
7167 json_object
*json_nexthop_global
= NULL
;
7168 json_object
*json_nexthop_ll
= NULL
;
7169 json_object
*json_ext_community
= NULL
;
7170 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7172 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7173 bool nexthop_othervrf
= false;
7174 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7175 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7176 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
7179 json_path
= json_object_new_object();
7181 /* short status lead text */
7182 route_vty_short_status_out(vty
, path
, json_path
);
7185 /* print prefix and mask */
7187 route_vty_out_route(p
, vty
, json_path
);
7189 vty_out(vty
, "%*s", 17, " ");
7191 route_vty_out_route(p
, vty
, json_path
);
7195 * If vrf id of nexthop is different from that of prefix,
7196 * set up printable string to append
7198 if (path
->extra
&& path
->extra
->bgp_orig
) {
7199 const char *self
= "";
7204 nexthop_othervrf
= true;
7205 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7207 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7208 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7209 "@%s%s", VRFID_NONE_STR
, self
);
7211 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7212 path
->extra
->bgp_orig
->vrf_id
, self
);
7214 if (path
->extra
->bgp_orig
->inst_type
7215 != BGP_INSTANCE_TYPE_DEFAULT
)
7217 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7219 const char *self
= "";
7224 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7228 * For ENCAP and EVPN routes, nexthop address family is not
7229 * neccessarily the same as the prefix address family.
7230 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7231 * EVPN routes are also exchanged with a MP nexthop. Currently,
7233 * is only IPv4, the value will be present in either
7235 * attr->mp_nexthop_global_in
7237 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7240 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7244 sprintf(nexthop
, "%s",
7245 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7249 sprintf(nexthop
, "%s",
7250 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7254 sprintf(nexthop
, "?");
7259 json_nexthop_global
= json_object_new_object();
7261 json_object_string_add(json_nexthop_global
, "ip",
7264 if (nexthop_hostname
)
7265 json_object_string_add(json_nexthop_global
,
7269 json_object_string_add(json_nexthop_global
, "afi",
7270 (af
== AF_INET
) ? "ipv4"
7272 json_object_boolean_true_add(json_nexthop_global
,
7275 vty_out(vty
, "%s%s",
7276 nexthop_hostname
? nexthop_hostname
: nexthop
,
7278 } else if (safi
== SAFI_EVPN
) {
7280 json_nexthop_global
= json_object_new_object();
7282 json_object_string_add(json_nexthop_global
, "ip",
7283 inet_ntoa(attr
->nexthop
));
7285 if (nexthop_hostname
)
7286 json_object_string_add(json_nexthop_global
,
7290 json_object_string_add(json_nexthop_global
, "afi",
7292 json_object_boolean_true_add(json_nexthop_global
,
7295 vty_out(vty
, "%-16s%s",
7296 nexthop_hostname
? nexthop_hostname
7297 : inet_ntoa(attr
->nexthop
),
7299 } else if (safi
== SAFI_FLOWSPEC
) {
7300 if (attr
->nexthop
.s_addr
!= 0) {
7302 json_nexthop_global
= json_object_new_object();
7304 json_object_string_add(json_nexthop_global
,
7306 json_object_string_add(
7307 json_nexthop_global
, "ip",
7308 inet_ntoa(attr
->nexthop
));
7310 if (nexthop_hostname
)
7311 json_object_string_add(
7312 json_nexthop_global
, "hostname",
7315 json_object_boolean_true_add(
7316 json_nexthop_global
,
7319 vty_out(vty
, "%-16s",
7322 : inet_ntoa(attr
->nexthop
));
7325 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7327 json_nexthop_global
= json_object_new_object();
7329 json_object_string_add(json_nexthop_global
, "ip",
7330 inet_ntoa(attr
->nexthop
));
7332 if (nexthop_hostname
)
7333 json_object_string_add(json_nexthop_global
,
7337 json_object_string_add(json_nexthop_global
, "afi",
7339 json_object_boolean_true_add(json_nexthop_global
,
7344 snprintf(buf
, sizeof(buf
), "%s%s",
7345 nexthop_hostname
? nexthop_hostname
7346 : inet_ntoa(attr
->nexthop
),
7348 vty_out(vty
, "%-16s", buf
);
7353 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7358 json_nexthop_global
= json_object_new_object();
7359 json_object_string_add(
7360 json_nexthop_global
, "ip",
7361 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7364 if (nexthop_hostname
)
7365 json_object_string_add(json_nexthop_global
,
7369 json_object_string_add(json_nexthop_global
, "afi",
7371 json_object_string_add(json_nexthop_global
, "scope",
7374 /* We display both LL & GL if both have been
7376 if ((attr
->mp_nexthop_len
7377 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7378 || (path
->peer
->conf_if
)) {
7379 json_nexthop_ll
= json_object_new_object();
7380 json_object_string_add(
7381 json_nexthop_ll
, "ip",
7383 &attr
->mp_nexthop_local
, buf
,
7386 if (nexthop_hostname
)
7387 json_object_string_add(
7388 json_nexthop_ll
, "hostname",
7391 json_object_string_add(json_nexthop_ll
, "afi",
7393 json_object_string_add(json_nexthop_ll
, "scope",
7396 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7397 &attr
->mp_nexthop_local
)
7399 && !attr
->mp_nexthop_prefer_global
)
7400 json_object_boolean_true_add(
7401 json_nexthop_ll
, "used");
7403 json_object_boolean_true_add(
7404 json_nexthop_global
, "used");
7406 json_object_boolean_true_add(
7407 json_nexthop_global
, "used");
7409 /* Display LL if LL/Global both in table unless
7410 * prefer-global is set */
7411 if (((attr
->mp_nexthop_len
7412 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7413 && !attr
->mp_nexthop_prefer_global
)
7414 || (path
->peer
->conf_if
)) {
7415 if (path
->peer
->conf_if
) {
7416 len
= vty_out(vty
, "%s",
7417 path
->peer
->conf_if
);
7418 len
= 16 - len
; /* len of IPv6
7424 vty_out(vty
, "\n%*s", 36, " ");
7426 vty_out(vty
, "%*s", len
, " ");
7434 &attr
->mp_nexthop_local
,
7440 vty_out(vty
, "\n%*s", 36, " ");
7442 vty_out(vty
, "%*s", len
, " ");
7451 &attr
->mp_nexthop_global
,
7457 vty_out(vty
, "\n%*s", 36, " ");
7459 vty_out(vty
, "%*s", len
, " ");
7465 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7469 * Adding "metric" field to match with corresponding
7470 * CLI. "med" will be deprecated in future.
7472 json_object_int_add(json_path
, "med", attr
->med
);
7473 json_object_int_add(json_path
, "metric", attr
->med
);
7475 vty_out(vty
, "%10u", attr
->med
);
7476 else if (!json_paths
)
7480 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7484 * Adding "locPrf" field to match with corresponding
7485 * CLI. "localPref" will be deprecated in future.
7487 json_object_int_add(json_path
, "localpref",
7489 json_object_int_add(json_path
, "locPrf",
7492 vty_out(vty
, "%7u", attr
->local_pref
);
7493 else if (!json_paths
)
7497 json_object_int_add(json_path
, "weight", attr
->weight
);
7499 vty_out(vty
, "%7u ", attr
->weight
);
7503 json_object_string_add(
7504 json_path
, "peerId",
7505 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7513 * Adding "path" field to match with corresponding
7514 * CLI. "aspath" will be deprecated in future.
7516 json_object_string_add(json_path
, "aspath",
7518 json_object_string_add(json_path
, "path",
7521 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7526 json_object_string_add(json_path
, "origin",
7527 bgp_origin_long_str
[attr
->origin
]);
7529 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7532 if (safi
== SAFI_EVPN
&&
7533 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7534 json_ext_community
= json_object_new_object();
7535 json_object_string_add(json_ext_community
,
7537 attr
->ecommunity
->str
);
7538 json_object_object_add(json_path
,
7539 "extendedCommunity",
7540 json_ext_community
);
7544 json_object_boolean_true_add(json_path
,
7545 "announceNexthopSelf");
7546 if (nexthop_othervrf
) {
7547 json_object_string_add(json_path
, "nhVrfName",
7550 json_object_int_add(json_path
, "nhVrfId",
7551 ((nexthop_vrfid
== VRF_UNKNOWN
)
7553 : (int)nexthop_vrfid
));
7558 if (json_nexthop_global
|| json_nexthop_ll
) {
7559 json_nexthops
= json_object_new_array();
7561 if (json_nexthop_global
)
7562 json_object_array_add(json_nexthops
,
7563 json_nexthop_global
);
7565 if (json_nexthop_ll
)
7566 json_object_array_add(json_nexthops
,
7569 json_object_object_add(json_path
, "nexthops",
7573 json_object_array_add(json_paths
, json_path
);
7577 if (safi
== SAFI_EVPN
&&
7578 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7579 vty_out(vty
, "%*s", 20, " ");
7580 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7584 /* prints an additional line, indented, with VNC info, if
7586 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7587 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7592 /* called from terminal list command */
7593 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7594 safi_t safi
, bool use_json
, json_object
*json_ar
)
7596 json_object
*json_status
= NULL
;
7597 json_object
*json_net
= NULL
;
7600 /* Route status display. */
7602 json_status
= json_object_new_object();
7603 json_net
= json_object_new_object();
7610 /* print prefix and mask */
7612 if (safi
== SAFI_EVPN
)
7613 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7614 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7615 json_object_string_add(
7616 json_net
, "addrPrefix",
7617 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7619 json_object_int_add(json_net
, "prefixLen",
7621 prefix2str(p
, buff
, PREFIX_STRLEN
);
7622 json_object_string_add(json_net
, "network", buff
);
7625 route_vty_out_route(p
, vty
, NULL
);
7627 /* Print attribute */
7630 if (p
->family
== AF_INET
7631 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7632 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7633 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7634 json_object_string_add(
7635 json_net
, "nextHop",
7637 attr
->mp_nexthop_global_in
));
7639 json_object_string_add(
7640 json_net
, "nextHop",
7641 inet_ntoa(attr
->nexthop
));
7642 } else if (p
->family
== AF_INET6
7643 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7646 json_object_string_add(
7647 json_net
, "nextHopGlobal",
7649 &attr
->mp_nexthop_global
, buf
,
7651 } else if (p
->family
== AF_EVPN
&&
7652 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7653 json_object_string_add(json_net
,
7654 "nextHop", inet_ntoa(
7655 attr
->mp_nexthop_global_in
));
7658 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7659 json_object_int_add(json_net
, "metric",
7662 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7665 * Adding "locPrf" field to match with
7666 * corresponding CLI. "localPref" will be
7667 * deprecated in future.
7669 json_object_int_add(json_net
, "localPref",
7671 json_object_int_add(json_net
, "locPrf",
7675 json_object_int_add(json_net
, "weight", attr
->weight
);
7681 * Adding "path" field to match with
7682 * corresponding CLI. "localPref" will be
7683 * deprecated in future.
7685 json_object_string_add(json_net
, "asPath",
7687 json_object_string_add(json_net
, "path",
7692 json_object_string_add(json_net
, "bgpOriginCode",
7693 bgp_origin_str
[attr
->origin
]);
7695 if (p
->family
== AF_INET
7696 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7697 || safi
== SAFI_EVPN
7698 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7699 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7700 || safi
== SAFI_EVPN
)
7701 vty_out(vty
, "%-16s",
7703 attr
->mp_nexthop_global_in
));
7705 vty_out(vty
, "%-16s",
7706 inet_ntoa(attr
->nexthop
));
7707 } else if (p
->family
== AF_INET6
7708 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7715 &attr
->mp_nexthop_global
, buf
,
7719 vty_out(vty
, "\n%*s", 36, " ");
7721 vty_out(vty
, "%*s", len
, " ");
7724 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7725 vty_out(vty
, "%10u", attr
->med
);
7729 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7730 vty_out(vty
, "%7u", attr
->local_pref
);
7734 vty_out(vty
, "%7u ", attr
->weight
);
7738 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7741 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7745 json_object_boolean_true_add(json_status
, "*");
7746 json_object_boolean_true_add(json_status
, ">");
7747 json_object_object_add(json_net
, "appliedStatusSymbols",
7750 prefix2str(p
, buff
, PREFIX_STRLEN
);
7751 json_object_object_add(json_ar
, buff
, json_net
);
7756 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7757 struct bgp_path_info
*path
, int display
, safi_t safi
,
7760 json_object
*json_out
= NULL
;
7762 mpls_label_t label
= MPLS_INVALID_LABEL
;
7768 json_out
= json_object_new_object();
7770 /* short status lead text */
7771 route_vty_short_status_out(vty
, path
, json_out
);
7773 /* print prefix and mask */
7776 route_vty_out_route(p
, vty
, NULL
);
7778 vty_out(vty
, "%*s", 17, " ");
7781 /* Print attribute */
7783 if (((p
->family
== AF_INET
)
7784 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7785 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7786 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7787 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7788 || safi
== SAFI_EVPN
) {
7790 json_object_string_add(
7791 json_out
, "mpNexthopGlobalIn",
7792 inet_ntoa(attr
->mp_nexthop_global_in
));
7794 vty_out(vty
, "%-16s",
7795 inet_ntoa(attr
->mp_nexthop_global_in
));
7798 json_object_string_add(
7799 json_out
, "nexthop",
7800 inet_ntoa(attr
->nexthop
));
7802 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
7804 } else if (((p
->family
== AF_INET6
)
7805 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7806 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7807 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7810 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7812 json_object_string_add(
7813 json_out
, "mpNexthopGlobalIn",
7815 &attr
->mp_nexthop_global
,
7816 buf_a
, sizeof(buf_a
)));
7820 &attr
->mp_nexthop_global
,
7821 buf_a
, sizeof(buf_a
)));
7822 } else if (attr
->mp_nexthop_len
7823 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7824 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
7825 &attr
->mp_nexthop_global
,
7826 &attr
->mp_nexthop_local
);
7828 json_object_string_add(json_out
,
7829 "mpNexthopGlobalLocal",
7832 vty_out(vty
, "%s", buf_a
);
7836 label
= decode_label(&path
->extra
->label
[0]);
7838 if (bgp_is_valid_label(&label
)) {
7840 json_object_int_add(json_out
, "notag", label
);
7841 json_object_array_add(json
, json_out
);
7843 vty_out(vty
, "notag/%d", label
);
7849 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7850 struct bgp_path_info
*path
, int display
,
7851 json_object
*json_paths
)
7854 char buf
[BUFSIZ
] = {0};
7855 json_object
*json_path
= NULL
;
7856 json_object
*json_nexthop
= NULL
;
7857 json_object
*json_overlay
= NULL
;
7863 json_path
= json_object_new_object();
7864 json_overlay
= json_object_new_object();
7865 json_nexthop
= json_object_new_object();
7868 /* short status lead text */
7869 route_vty_short_status_out(vty
, path
, json_path
);
7871 /* print prefix and mask */
7873 route_vty_out_route(p
, vty
, json_path
);
7875 vty_out(vty
, "%*s", 17, " ");
7877 /* Print attribute */
7880 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7884 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
7886 vty_out(vty
, "%-16s", buf
);
7888 json_object_string_add(json_nexthop
, "ip", buf
);
7890 json_object_string_add(json_nexthop
, "afi", "ipv4");
7892 json_object_object_add(json_path
, "nexthop",
7897 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
7898 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
7900 vty_out(vty
, "%s(%s)", buf
, buf1
);
7902 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
7904 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
7907 json_object_string_add(json_nexthop
, "afi", "ipv6");
7909 json_object_object_add(json_path
, "nexthop",
7917 json_object_string_add(json_nexthop
, "Error",
7918 "Unsupported address-family");
7922 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7925 vty_out(vty
, "%s", str
);
7927 json_object_string_add(json_overlay
, "esi", str
);
7929 XFREE(MTYPE_TMP
, str
);
7931 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7932 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
7934 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7935 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7940 vty_out(vty
, "/%s", buf
);
7942 json_object_string_add(json_overlay
, "gw", buf
);
7944 if (attr
->ecommunity
) {
7946 struct ecommunity_val
*routermac
= ecommunity_lookup(
7947 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7948 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7951 mac
= ecom_mac2str((char *)routermac
->val
);
7954 vty_out(vty
, "/%s", (char *)mac
);
7956 json_object_string_add(json_overlay
, "rmac",
7959 XFREE(MTYPE_TMP
, mac
);
7966 json_object_object_add(json_path
, "overlay", json_overlay
);
7968 json_object_array_add(json_paths
, json_path
);
7972 /* dampening route */
7973 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7974 struct bgp_path_info
*path
, int display
, afi_t afi
,
7975 safi_t safi
, bool use_json
, json_object
*json
)
7979 char timebuf
[BGP_UPTIME_LEN
];
7981 /* short status lead text */
7982 route_vty_short_status_out(vty
, path
, json
);
7984 /* print prefix and mask */
7987 route_vty_out_route(p
, vty
, NULL
);
7989 vty_out(vty
, "%*s", 17, " ");
7992 len
= vty_out(vty
, "%s", path
->peer
->host
);
7996 vty_out(vty
, "\n%*s", 34, " ");
7999 json_object_int_add(json
, "peerHost", len
);
8001 vty_out(vty
, "%*s", len
, " ");
8005 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8006 safi
, use_json
, json
);
8009 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8010 BGP_UPTIME_LEN
, afi
, safi
,
8013 /* Print attribute */
8019 json_object_string_add(json
, "asPath",
8022 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8027 json_object_string_add(json
, "origin",
8028 bgp_origin_str
[attr
->origin
]);
8030 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8037 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8038 struct bgp_path_info
*path
, int display
, afi_t afi
,
8039 safi_t safi
, bool use_json
, json_object
*json
)
8042 struct bgp_damp_info
*bdi
;
8043 char timebuf
[BGP_UPTIME_LEN
];
8049 bdi
= path
->extra
->damp_info
;
8051 /* short status lead text */
8052 route_vty_short_status_out(vty
, path
, json
);
8054 /* print prefix and mask */
8057 route_vty_out_route(p
, vty
, NULL
);
8059 vty_out(vty
, "%*s", 17, " ");
8062 len
= vty_out(vty
, "%s", path
->peer
->host
);
8066 vty_out(vty
, "\n%*s", 33, " ");
8069 json_object_int_add(json
, "peerHost", len
);
8071 vty_out(vty
, "%*s", len
, " ");
8074 len
= vty_out(vty
, "%d", bdi
->flap
);
8081 json_object_int_add(json
, "bdiFlap", len
);
8083 vty_out(vty
, "%*s", len
, " ");
8087 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8090 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8091 BGP_UPTIME_LEN
, 0, NULL
));
8093 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8094 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8096 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8097 BGP_UPTIME_LEN
, afi
, safi
,
8101 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8102 BGP_UPTIME_LEN
, afi
,
8103 safi
, use_json
, json
));
8106 vty_out(vty
, "%*s ", 8, " ");
8109 /* Print attribute */
8115 json_object_string_add(json
, "asPath",
8118 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8123 json_object_string_add(json
, "origin",
8124 bgp_origin_str
[attr
->origin
]);
8126 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8132 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8133 int *first
, const char *header
,
8134 json_object
*json_adv_to
)
8136 char buf1
[INET6_ADDRSTRLEN
];
8137 json_object
*json_peer
= NULL
;
8140 /* 'advertised-to' is a dictionary of peers we have advertised
8142 * prefix too. The key is the peer's IP or swpX, the value is
8144 * hostname if we know it and "" if not.
8146 json_peer
= json_object_new_object();
8149 json_object_string_add(json_peer
, "hostname",
8153 json_object_object_add(json_adv_to
, peer
->conf_if
,
8156 json_object_object_add(
8158 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8162 vty_out(vty
, "%s", header
);
8167 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8169 vty_out(vty
, " %s(%s)", peer
->hostname
,
8172 vty_out(vty
, " %s(%s)", peer
->hostname
,
8173 sockunion2str(&peer
->su
, buf1
,
8177 vty_out(vty
, " %s", peer
->conf_if
);
8180 sockunion2str(&peer
->su
, buf1
,
8186 static void route_vty_out_tx_ids(struct vty
*vty
,
8187 struct bgp_addpath_info_data
*d
)
8191 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8192 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8193 d
->addpath_tx_id
[i
],
8194 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8198 static const char *bgp_path_selection_reason2str(
8199 enum bgp_path_selection_reason reason
)
8202 case bgp_path_selection_none
:
8203 return "Nothing to Select";
8205 case bgp_path_selection_first
:
8206 return "First path received";
8208 case bgp_path_selection_evpn_sticky_mac
:
8209 return "EVPN Sticky Mac";
8211 case bgp_path_selection_evpn_seq
:
8212 return "EVPN sequence number";
8214 case bgp_path_selection_evpn_lower_ip
:
8215 return "EVPN lower IP";
8217 case bgp_path_selection_weight
:
8220 case bgp_path_selection_local_pref
:
8221 return "Local Pref";
8223 case bgp_path_selection_local_route
:
8224 return "Local Route";
8226 case bgp_path_selection_confed_as_path
:
8227 return "Confederation based AS Path";
8229 case bgp_path_selection_as_path
:
8232 case bgp_path_selection_origin
:
8235 case bgp_path_selection_med
:
8238 case bgp_path_selection_peer
:
8241 case bgp_path_selection_confed
:
8242 return "Confed Peer Type";
8244 case bgp_path_selection_igp_metric
:
8245 return "IGP Metric";
8247 case bgp_path_selection_older
:
8248 return "Older Path";
8250 case bgp_path_selection_router_id
:
8253 case bgp_path_selection_cluster_length
:
8254 return "Cluser length";
8256 case bgp_path_selection_stale
:
8257 return "Path Staleness";
8259 case bgp_path_selection_local_configured
:
8260 return "Locally configured route";
8262 case bgp_path_selection_neighbor_ip
:
8263 return "Neighbor IP";
8265 case bgp_path_selection_default
:
8266 return "Nothing left to compare";
8269 return "Invalid (internal error)";
8272 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8273 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8274 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8276 char buf
[INET6_ADDRSTRLEN
];
8278 char buf2
[EVPN_ROUTE_STRLEN
];
8279 struct attr
*attr
= path
->attr
;
8280 int sockunion_vty_out(struct vty
*, union sockunion
*);
8282 json_object
*json_bestpath
= NULL
;
8283 json_object
*json_cluster_list
= NULL
;
8284 json_object
*json_cluster_list_list
= NULL
;
8285 json_object
*json_ext_community
= NULL
;
8286 json_object
*json_last_update
= NULL
;
8287 json_object
*json_pmsi
= NULL
;
8288 json_object
*json_nexthop_global
= NULL
;
8289 json_object
*json_nexthop_ll
= NULL
;
8290 json_object
*json_nexthops
= NULL
;
8291 json_object
*json_path
= NULL
;
8292 json_object
*json_peer
= NULL
;
8293 json_object
*json_string
= NULL
;
8294 json_object
*json_adv_to
= NULL
;
8296 struct listnode
*node
, *nnode
;
8298 int addpath_capable
;
8300 unsigned int first_as
;
8302 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8304 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
8307 json_path
= json_object_new_object();
8308 json_peer
= json_object_new_object();
8309 json_nexthop_global
= json_object_new_object();
8317 if (path
->extra
&& path
->extra
->num_labels
) {
8318 bgp_evpn_label2str(path
->extra
->label
,
8319 path
->extra
->num_labels
, tag_buf
,
8322 if (safi
== SAFI_EVPN
) {
8324 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8325 buf2
, sizeof(buf2
));
8326 vty_out(vty
, " Route %s", buf2
);
8327 if (tag_buf
[0] != '\0')
8328 vty_out(vty
, " VNI %s", tag_buf
);
8332 json_object_string_add(json_path
, "VNI",
8337 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8338 struct bgp_path_info
*parent_ri
;
8339 struct bgp_node
*rn
, *prn
;
8341 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8342 rn
= parent_ri
->net
;
8343 if (rn
&& rn
->prn
) {
8345 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8346 buf1
, sizeof(buf1
));
8347 if (is_pi_family_evpn(parent_ri
)) {
8348 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8349 buf2
, sizeof(buf2
));
8350 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8352 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8357 /* Line1 display AS-path, Aggregator */
8360 if (!attr
->aspath
->json
)
8361 aspath_str_update(attr
->aspath
, true);
8362 json_object_lock(attr
->aspath
->json
);
8363 json_object_object_add(json_path
, "aspath",
8364 attr
->aspath
->json
);
8366 if (attr
->aspath
->segments
)
8367 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8369 vty_out(vty
, " Local");
8373 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8375 json_object_boolean_true_add(json_path
, "removed");
8377 vty_out(vty
, ", (removed)");
8380 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8382 json_object_boolean_true_add(json_path
, "stale");
8384 vty_out(vty
, ", (stale)");
8387 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8389 json_object_int_add(json_path
, "aggregatorAs",
8390 attr
->aggregator_as
);
8391 json_object_string_add(
8392 json_path
, "aggregatorId",
8393 inet_ntoa(attr
->aggregator_addr
));
8395 vty_out(vty
, ", (aggregated by %u %s)",
8396 attr
->aggregator_as
,
8397 inet_ntoa(attr
->aggregator_addr
));
8401 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8402 PEER_FLAG_REFLECTOR_CLIENT
)) {
8404 json_object_boolean_true_add(json_path
,
8405 "rxedFromRrClient");
8407 vty_out(vty
, ", (Received from a RR-client)");
8410 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8411 PEER_FLAG_RSERVER_CLIENT
)) {
8413 json_object_boolean_true_add(json_path
,
8414 "rxedFromRsClient");
8416 vty_out(vty
, ", (Received from a RS-client)");
8419 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8421 json_object_boolean_true_add(json_path
,
8422 "dampeningHistoryEntry");
8424 vty_out(vty
, ", (history entry)");
8425 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8427 json_object_boolean_true_add(json_path
,
8428 "dampeningSuppressed");
8430 vty_out(vty
, ", (suppressed due to dampening)");
8436 /* Line2 display Next-hop, Neighbor, Router-id */
8437 /* Display the nexthop */
8438 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8439 || bn
->p
.family
== AF_EVPN
)
8440 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8441 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8442 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8443 || safi
== SAFI_EVPN
) {
8445 json_object_string_add(
8446 json_nexthop_global
, "ip",
8447 inet_ntoa(attr
->mp_nexthop_global_in
));
8449 if (nexthop_hostname
)
8450 json_object_string_add(
8451 json_nexthop_global
, "hostname",
8458 attr
->mp_nexthop_global_in
));
8461 json_object_string_add(
8462 json_nexthop_global
, "ip",
8463 inet_ntoa(attr
->nexthop
));
8465 if (nexthop_hostname
)
8466 json_object_string_add(
8467 json_nexthop_global
, "hostname",
8473 : inet_ntoa(attr
->nexthop
));
8477 json_object_string_add(json_nexthop_global
, "afi",
8481 json_object_string_add(
8482 json_nexthop_global
, "ip",
8483 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8484 buf
, INET6_ADDRSTRLEN
));
8486 if (nexthop_hostname
)
8487 json_object_string_add(json_nexthop_global
,
8491 json_object_string_add(json_nexthop_global
, "afi",
8493 json_object_string_add(json_nexthop_global
, "scope",
8499 : inet_ntop(AF_INET6
,
8500 &attr
->mp_nexthop_global
,
8501 buf
, INET6_ADDRSTRLEN
));
8505 /* Display the IGP cost or 'inaccessible' */
8506 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8508 json_object_boolean_false_add(json_nexthop_global
,
8511 vty_out(vty
, " (inaccessible)");
8513 if (path
->extra
&& path
->extra
->igpmetric
) {
8515 json_object_int_add(json_nexthop_global
,
8517 path
->extra
->igpmetric
);
8519 vty_out(vty
, " (metric %u)",
8520 path
->extra
->igpmetric
);
8523 /* IGP cost is 0, display this only for json */
8526 json_object_int_add(json_nexthop_global
,
8531 json_object_boolean_true_add(json_nexthop_global
,
8535 /* Display peer "from" output */
8536 /* This path was originated locally */
8537 if (path
->peer
== bgp
->peer_self
) {
8539 if (safi
== SAFI_EVPN
8540 || (bn
->p
.family
== AF_INET
8541 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8543 json_object_string_add(json_peer
, "peerId",
8546 vty_out(vty
, " from 0.0.0.0 ");
8549 json_object_string_add(json_peer
, "peerId",
8552 vty_out(vty
, " from :: ");
8556 json_object_string_add(json_peer
, "routerId",
8557 inet_ntoa(bgp
->router_id
));
8559 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8562 /* We RXed this path from one of our peers */
8566 json_object_string_add(json_peer
, "peerId",
8567 sockunion2str(&path
->peer
->su
,
8570 json_object_string_add(json_peer
, "routerId",
8572 &path
->peer
->remote_id
,
8573 buf1
, sizeof(buf1
)));
8575 if (path
->peer
->hostname
)
8576 json_object_string_add(json_peer
, "hostname",
8577 path
->peer
->hostname
);
8579 if (path
->peer
->domainname
)
8580 json_object_string_add(json_peer
, "domainname",
8581 path
->peer
->domainname
);
8583 if (path
->peer
->conf_if
)
8584 json_object_string_add(json_peer
, "interface",
8585 path
->peer
->conf_if
);
8587 if (path
->peer
->conf_if
) {
8588 if (path
->peer
->hostname
8589 && bgp_flag_check(path
->peer
->bgp
,
8590 BGP_FLAG_SHOW_HOSTNAME
))
8591 vty_out(vty
, " from %s(%s)",
8592 path
->peer
->hostname
,
8593 path
->peer
->conf_if
);
8595 vty_out(vty
, " from %s",
8596 path
->peer
->conf_if
);
8598 if (path
->peer
->hostname
8599 && bgp_flag_check(path
->peer
->bgp
,
8600 BGP_FLAG_SHOW_HOSTNAME
))
8601 vty_out(vty
, " from %s(%s)",
8602 path
->peer
->hostname
,
8605 vty_out(vty
, " from %s",
8606 sockunion2str(&path
->peer
->su
,
8611 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8612 vty_out(vty
, " (%s)",
8613 inet_ntoa(attr
->originator_id
));
8615 vty_out(vty
, " (%s)",
8617 &path
->peer
->remote_id
, buf1
,
8623 * Note when vrfid of nexthop is different from that of prefix
8625 if (path
->extra
&& path
->extra
->bgp_orig
) {
8626 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8631 if (path
->extra
->bgp_orig
->inst_type
8632 == BGP_INSTANCE_TYPE_DEFAULT
)
8633 vn
= VRF_DEFAULT_NAME
;
8635 vn
= path
->extra
->bgp_orig
->name
;
8637 json_object_string_add(json_path
, "nhVrfName", vn
);
8639 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8640 json_object_int_add(json_path
, "nhVrfId", -1);
8642 json_object_int_add(json_path
, "nhVrfId",
8643 (int)nexthop_vrfid
);
8646 if (nexthop_vrfid
== VRF_UNKNOWN
)
8647 vty_out(vty
, " vrf ?");
8649 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8655 json_object_boolean_true_add(json_path
,
8656 "announceNexthopSelf");
8658 vty_out(vty
, " announce-nh-self");
8665 /* display the link-local nexthop */
8666 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8668 json_nexthop_ll
= json_object_new_object();
8669 json_object_string_add(
8670 json_nexthop_ll
, "ip",
8671 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8672 buf
, INET6_ADDRSTRLEN
));
8674 if (nexthop_hostname
)
8675 json_object_string_add(json_nexthop_ll
,
8679 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8680 json_object_string_add(json_nexthop_ll
, "scope",
8683 json_object_boolean_true_add(json_nexthop_ll
,
8686 if (!attr
->mp_nexthop_prefer_global
)
8687 json_object_boolean_true_add(json_nexthop_ll
,
8690 json_object_boolean_true_add(
8691 json_nexthop_global
, "used");
8693 vty_out(vty
, " (%s) %s\n",
8694 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8695 buf
, INET6_ADDRSTRLEN
),
8696 attr
->mp_nexthop_prefer_global
8701 /* If we do not have a link-local nexthop then we must flag the
8705 json_object_boolean_true_add(json_nexthop_global
,
8709 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8710 * Int/Ext/Local, Atomic, best */
8712 json_object_string_add(json_path
, "origin",
8713 bgp_origin_long_str
[attr
->origin
]);
8715 vty_out(vty
, " Origin %s",
8716 bgp_origin_long_str
[attr
->origin
]);
8718 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8721 * Adding "metric" field to match with
8722 * corresponding CLI. "med" will be
8723 * deprecated in future.
8725 json_object_int_add(json_path
, "med", attr
->med
);
8726 json_object_int_add(json_path
, "metric", attr
->med
);
8728 vty_out(vty
, ", metric %u", attr
->med
);
8731 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8733 json_object_int_add(json_path
, "localpref",
8736 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8739 if (attr
->weight
!= 0) {
8741 json_object_int_add(json_path
, "weight", attr
->weight
);
8743 vty_out(vty
, ", weight %u", attr
->weight
);
8746 if (attr
->tag
!= 0) {
8748 json_object_int_add(json_path
, "tag", attr
->tag
);
8750 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
8753 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8755 json_object_boolean_false_add(json_path
, "valid");
8757 vty_out(vty
, ", invalid");
8758 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8760 json_object_boolean_true_add(json_path
, "valid");
8762 vty_out(vty
, ", valid");
8765 if (path
->peer
!= bgp
->peer_self
) {
8766 if (path
->peer
->as
== path
->peer
->local_as
) {
8767 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
8769 json_object_string_add(
8773 vty_out(vty
, ", confed-internal");
8776 json_object_string_add(
8777 json_peer
, "type", "internal");
8779 vty_out(vty
, ", internal");
8782 if (bgp_confederation_peers_check(bgp
,
8785 json_object_string_add(
8789 vty_out(vty
, ", confed-external");
8792 json_object_string_add(
8793 json_peer
, "type", "external");
8795 vty_out(vty
, ", external");
8798 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8800 json_object_boolean_true_add(json_path
, "aggregated");
8801 json_object_boolean_true_add(json_path
, "local");
8803 vty_out(vty
, ", aggregated, local");
8805 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8807 json_object_boolean_true_add(json_path
, "sourced");
8809 vty_out(vty
, ", sourced");
8812 json_object_boolean_true_add(json_path
, "sourced");
8813 json_object_boolean_true_add(json_path
, "local");
8815 vty_out(vty
, ", sourced, local");
8819 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8821 json_object_boolean_true_add(json_path
,
8824 vty_out(vty
, ", atomic-aggregate");
8827 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8828 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8829 && bgp_path_info_mpath_count(path
))) {
8831 json_object_boolean_true_add(json_path
, "multipath");
8833 vty_out(vty
, ", multipath");
8836 // Mark the bestpath(s)
8837 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8838 first_as
= aspath_get_first_as(attr
->aspath
);
8842 json_bestpath
= json_object_new_object();
8843 json_object_int_add(json_bestpath
, "bestpathFromAs",
8847 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
8849 vty_out(vty
, ", bestpath-from-AS Local");
8853 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8856 json_bestpath
= json_object_new_object();
8857 json_object_boolean_true_add(json_bestpath
, "overall");
8858 json_object_string_add(
8859 json_bestpath
, "selectionReason",
8860 bgp_path_selection_reason2str(bn
->reason
));
8862 vty_out(vty
, ", best");
8863 vty_out(vty
, " (%s)",
8864 bgp_path_selection_reason2str(bn
->reason
));
8869 json_object_object_add(json_path
, "bestpath", json_bestpath
);
8874 /* Line 4 display Community */
8875 if (attr
->community
) {
8877 if (!attr
->community
->json
)
8878 community_str(attr
->community
, true);
8879 json_object_lock(attr
->community
->json
);
8880 json_object_object_add(json_path
, "community",
8881 attr
->community
->json
);
8883 vty_out(vty
, " Community: %s\n",
8884 attr
->community
->str
);
8888 /* Line 5 display Extended-community */
8889 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8891 json_ext_community
= json_object_new_object();
8892 json_object_string_add(json_ext_community
, "string",
8893 attr
->ecommunity
->str
);
8894 json_object_object_add(json_path
, "extendedCommunity",
8895 json_ext_community
);
8897 vty_out(vty
, " Extended Community: %s\n",
8898 attr
->ecommunity
->str
);
8902 /* Line 6 display Large community */
8903 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8905 if (!attr
->lcommunity
->json
)
8906 lcommunity_str(attr
->lcommunity
, true);
8907 json_object_lock(attr
->lcommunity
->json
);
8908 json_object_object_add(json_path
, "largeCommunity",
8909 attr
->lcommunity
->json
);
8911 vty_out(vty
, " Large Community: %s\n",
8912 attr
->lcommunity
->str
);
8916 /* Line 7 display Originator, Cluster-id */
8917 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8918 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8919 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8921 json_object_string_add(
8922 json_path
, "originatorId",
8923 inet_ntoa(attr
->originator_id
));
8925 vty_out(vty
, " Originator: %s",
8926 inet_ntoa(attr
->originator_id
));
8929 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8933 json_cluster_list
= json_object_new_object();
8934 json_cluster_list_list
=
8935 json_object_new_array();
8937 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8939 json_string
= json_object_new_string(
8940 inet_ntoa(attr
->cluster
8942 json_object_array_add(
8943 json_cluster_list_list
,
8948 * struct cluster_list does not have
8949 * "str" variable like aspath and community
8950 * do. Add this someday if someone asks
8952 * json_object_string_add(json_cluster_list,
8953 * "string", attr->cluster->str);
8955 json_object_object_add(json_cluster_list
,
8957 json_cluster_list_list
);
8958 json_object_object_add(json_path
, "clusterList",
8961 vty_out(vty
, ", Cluster list: ");
8963 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8966 inet_ntoa(attr
->cluster
8976 if (path
->extra
&& path
->extra
->damp_info
)
8977 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
8980 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8981 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
8982 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8985 json_object_int_add(json_path
, "remoteLabel", label
);
8987 vty_out(vty
, " Remote label: %d\n", label
);
8991 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8993 json_object_int_add(json_path
, "labelIndex",
8996 vty_out(vty
, " Label Index: %d\n",
9000 /* Line 8 display Addpath IDs */
9001 if (path
->addpath_rx_id
9002 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9004 json_object_int_add(json_path
, "addpathRxId",
9005 path
->addpath_rx_id
);
9007 /* Keep backwards compatibility with the old API
9008 * by putting TX All's ID in the old field
9010 json_object_int_add(
9011 json_path
, "addpathTxId",
9013 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9015 /* ... but create a specific field for each
9018 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9019 json_object_int_add(
9021 bgp_addpath_names(i
)->id_json_name
,
9022 path
->tx_addpath
.addpath_tx_id
[i
]);
9025 vty_out(vty
, " AddPath ID: RX %u, ",
9026 path
->addpath_rx_id
);
9028 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9032 /* If we used addpath to TX a non-bestpath we need to display
9033 * "Advertised to" on a path-by-path basis
9035 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9038 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9040 bgp_addpath_encode_tx(peer
, afi
, safi
);
9041 has_adj
= bgp_adj_out_lookup(
9043 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9044 &path
->tx_addpath
));
9046 if ((addpath_capable
&& has_adj
)
9047 || (!addpath_capable
&& has_adj
9048 && CHECK_FLAG(path
->flags
,
9049 BGP_PATH_SELECTED
))) {
9050 if (json_path
&& !json_adv_to
)
9051 json_adv_to
= json_object_new_object();
9053 route_vty_out_advertised_to(
9055 " Advertised to:", json_adv_to
);
9061 json_object_object_add(
9062 json_path
, "advertisedTo", json_adv_to
);
9071 /* Line 9 display Uptime */
9072 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9074 json_last_update
= json_object_new_object();
9075 json_object_int_add(json_last_update
, "epoch", tbuf
);
9076 json_object_string_add(json_last_update
, "string",
9078 json_object_object_add(json_path
, "lastUpdate",
9081 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9083 /* Line 10 display PMSI tunnel attribute, if present */
9084 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9086 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9087 PMSI_TNLTYPE_STR_DEFAULT
);
9090 json_pmsi
= json_object_new_object();
9091 json_object_string_add(json_pmsi
, "tunnelType", str
);
9092 json_object_int_add(json_pmsi
, "label",
9093 label2vni(&attr
->label
));
9094 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9096 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9097 str
, label2vni(&attr
->label
));
9100 /* We've constructed the json object for this path, add it to the json
9104 if (json_nexthop_global
|| json_nexthop_ll
) {
9105 json_nexthops
= json_object_new_array();
9107 if (json_nexthop_global
)
9108 json_object_array_add(json_nexthops
,
9109 json_nexthop_global
);
9111 if (json_nexthop_ll
)
9112 json_object_array_add(json_nexthops
,
9115 json_object_object_add(json_path
, "nexthops",
9119 json_object_object_add(json_path
, "peer", json_peer
);
9120 json_object_array_add(json_paths
, json_path
);
9124 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9125 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9126 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9128 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9129 const char *prefix_list_str
, afi_t afi
,
9130 safi_t safi
, enum bgp_show_type type
);
9131 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9132 const char *filter
, afi_t afi
, safi_t safi
,
9133 enum bgp_show_type type
);
9134 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9135 const char *rmap_str
, afi_t afi
, safi_t safi
,
9136 enum bgp_show_type type
);
9137 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9138 const char *com
, int exact
, afi_t afi
,
9140 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9141 const char *prefix
, afi_t afi
, safi_t safi
,
9142 enum bgp_show_type type
);
9143 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9144 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
9145 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9146 const char *comstr
, int exact
, afi_t afi
,
9147 safi_t safi
, bool use_json
);
9150 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9151 struct bgp_table
*table
, enum bgp_show_type type
,
9152 void *output_arg
, bool use_json
, char *rd
,
9153 int is_last
, unsigned long *output_cum
,
9154 unsigned long *total_cum
,
9155 unsigned long *json_header_depth
)
9157 struct bgp_path_info
*pi
;
9158 struct bgp_node
*rn
;
9161 unsigned long output_count
= 0;
9162 unsigned long total_count
= 0;
9165 json_object
*json_paths
= NULL
;
9168 if (output_cum
&& *output_cum
!= 0)
9171 if (use_json
&& !*json_header_depth
) {
9173 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9174 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9175 " \"localAS\": %u,\n \"routes\": { ",
9176 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9177 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9180 table
->version
, inet_ntoa(bgp
->router_id
),
9181 bgp
->default_local_pref
, bgp
->as
);
9182 *json_header_depth
= 2;
9184 vty_out(vty
, " \"routeDistinguishers\" : {");
9185 ++*json_header_depth
;
9189 if (use_json
&& rd
) {
9190 vty_out(vty
, " \"%s\" : { ", rd
);
9193 /* Start processing of routes. */
9194 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9195 pi
= bgp_node_get_bgp_path_info(rn
);
9201 json_paths
= json_object_new_array();
9205 for (; pi
; pi
= pi
->next
) {
9207 if (type
== bgp_show_type_flap_statistics
9208 || type
== bgp_show_type_flap_neighbor
9209 || type
== bgp_show_type_dampend_paths
9210 || type
== bgp_show_type_damp_neighbor
) {
9211 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9214 if (type
== bgp_show_type_regexp
) {
9215 regex_t
*regex
= output_arg
;
9217 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9221 if (type
== bgp_show_type_prefix_list
) {
9222 struct prefix_list
*plist
= output_arg
;
9224 if (prefix_list_apply(plist
, &rn
->p
)
9228 if (type
== bgp_show_type_filter_list
) {
9229 struct as_list
*as_list
= output_arg
;
9231 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9232 != AS_FILTER_PERMIT
)
9235 if (type
== bgp_show_type_route_map
) {
9236 struct route_map
*rmap
= output_arg
;
9237 struct bgp_path_info path
;
9238 struct attr dummy_attr
;
9239 route_map_result_t ret
;
9241 dummy_attr
= *pi
->attr
;
9243 path
.peer
= pi
->peer
;
9244 path
.attr
= &dummy_attr
;
9246 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9248 if (ret
== RMAP_DENYMATCH
)
9251 if (type
== bgp_show_type_neighbor
9252 || type
== bgp_show_type_flap_neighbor
9253 || type
== bgp_show_type_damp_neighbor
) {
9254 union sockunion
*su
= output_arg
;
9256 if (pi
->peer
== NULL
9257 || pi
->peer
->su_remote
== NULL
9258 || !sockunion_same(pi
->peer
->su_remote
, su
))
9261 if (type
== bgp_show_type_cidr_only
) {
9262 uint32_t destination
;
9264 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9265 if (IN_CLASSC(destination
)
9266 && rn
->p
.prefixlen
== 24)
9268 if (IN_CLASSB(destination
)
9269 && rn
->p
.prefixlen
== 16)
9271 if (IN_CLASSA(destination
)
9272 && rn
->p
.prefixlen
== 8)
9275 if (type
== bgp_show_type_prefix_longer
) {
9277 if (!prefix_match(p
, &rn
->p
))
9280 if (type
== bgp_show_type_community_all
) {
9281 if (!pi
->attr
->community
)
9284 if (type
== bgp_show_type_community
) {
9285 struct community
*com
= output_arg
;
9287 if (!pi
->attr
->community
9288 || !community_match(pi
->attr
->community
,
9292 if (type
== bgp_show_type_community_exact
) {
9293 struct community
*com
= output_arg
;
9295 if (!pi
->attr
->community
9296 || !community_cmp(pi
->attr
->community
, com
))
9299 if (type
== bgp_show_type_community_list
) {
9300 struct community_list
*list
= output_arg
;
9302 if (!community_list_match(pi
->attr
->community
,
9306 if (type
== bgp_show_type_community_list_exact
) {
9307 struct community_list
*list
= output_arg
;
9309 if (!community_list_exact_match(
9310 pi
->attr
->community
, list
))
9313 if (type
== bgp_show_type_lcommunity
) {
9314 struct lcommunity
*lcom
= output_arg
;
9316 if (!pi
->attr
->lcommunity
9317 || !lcommunity_match(pi
->attr
->lcommunity
,
9322 if (type
== bgp_show_type_lcommunity_exact
) {
9323 struct lcommunity
*lcom
= output_arg
;
9325 if (!pi
->attr
->lcommunity
9326 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9330 if (type
== bgp_show_type_lcommunity_list
) {
9331 struct community_list
*list
= output_arg
;
9333 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9338 == bgp_show_type_lcommunity_list_exact
) {
9339 struct community_list
*list
= output_arg
;
9341 if (!lcommunity_list_exact_match(
9342 pi
->attr
->lcommunity
, list
))
9345 if (type
== bgp_show_type_lcommunity_all
) {
9346 if (!pi
->attr
->lcommunity
)
9349 if (type
== bgp_show_type_dampend_paths
9350 || type
== bgp_show_type_damp_neighbor
) {
9351 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9352 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9356 if (!use_json
&& header
) {
9357 vty_out(vty
, "BGP table version is %" PRIu64
9358 ", local router ID is %s, vrf id ",
9360 inet_ntoa(bgp
->router_id
));
9361 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9362 vty_out(vty
, "%s", VRFID_NONE_STR
);
9364 vty_out(vty
, "%u", bgp
->vrf_id
);
9366 vty_out(vty
, "Default local pref %u, ",
9367 bgp
->default_local_pref
);
9368 vty_out(vty
, "local AS %u\n", bgp
->as
);
9369 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9370 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9371 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9372 if (type
== bgp_show_type_dampend_paths
9373 || type
== bgp_show_type_damp_neighbor
)
9374 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9375 else if (type
== bgp_show_type_flap_statistics
9376 || type
== bgp_show_type_flap_neighbor
)
9377 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9379 vty_out(vty
, BGP_SHOW_HEADER
);
9382 if (rd
!= NULL
&& !display
&& !output_count
) {
9385 "Route Distinguisher: %s\n",
9388 if (type
== bgp_show_type_dampend_paths
9389 || type
== bgp_show_type_damp_neighbor
)
9390 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9391 safi
, use_json
, json_paths
);
9392 else if (type
== bgp_show_type_flap_statistics
9393 || type
== bgp_show_type_flap_neighbor
)
9394 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9395 safi
, use_json
, json_paths
);
9397 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9409 if (p
->family
== AF_FLOWSPEC
) {
9410 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9412 bgp_fs_nlri_get_string((unsigned char *)
9413 p
->u
.prefix_flowspec
.ptr
,
9414 p
->u
.prefix_flowspec
9417 NLRI_STRING_FORMAT_MIN
,
9420 vty_out(vty
, "\"%s/%d\": ",
9422 p
->u
.prefix_flowspec
.prefixlen
);
9424 vty_out(vty
, ",\"%s/%d\": ",
9426 p
->u
.prefix_flowspec
.prefixlen
);
9428 prefix2str(p
, buf2
, sizeof(buf2
));
9430 vty_out(vty
, "\"%s\": ", buf2
);
9432 vty_out(vty
, ",\"%s\": ", buf2
);
9435 json_object_to_json_string(json_paths
));
9436 json_object_free(json_paths
);
9440 json_object_free(json_paths
);
9444 output_count
+= *output_cum
;
9445 *output_cum
= output_count
;
9448 total_count
+= *total_cum
;
9449 *total_cum
= total_count
;
9453 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9457 for (i
= 0; i
< *json_header_depth
; ++i
)
9458 vty_out(vty
, " } ");
9463 /* No route is displayed */
9464 if (output_count
== 0) {
9465 if (type
== bgp_show_type_normal
)
9467 "No BGP prefixes displayed, %ld exist\n",
9471 "\nDisplayed %ld routes and %ld total paths\n",
9472 output_count
, total_count
);
9479 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9480 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9481 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9483 struct bgp_node
*rn
, *next
;
9484 unsigned long output_cum
= 0;
9485 unsigned long total_cum
= 0;
9486 unsigned long json_header_depth
= 0;
9487 struct bgp_table
*itable
;
9490 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9492 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9493 next
= bgp_route_next(rn
);
9494 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9497 itable
= bgp_node_get_bgp_table_info(rn
);
9498 if (itable
!= NULL
) {
9499 struct prefix_rd prd
;
9500 char rd
[RD_ADDRSTRLEN
];
9502 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9503 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9504 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9505 use_json
, rd
, next
== NULL
, &output_cum
,
9506 &total_cum
, &json_header_depth
);
9512 if (output_cum
== 0)
9513 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9517 "\nDisplayed %ld routes and %ld total paths\n",
9518 output_cum
, total_cum
);
9522 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9523 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9525 struct bgp_table
*table
;
9526 unsigned long json_header_depth
= 0;
9529 bgp
= bgp_get_default();
9534 vty_out(vty
, "No BGP process is configured\n");
9536 vty_out(vty
, "{}\n");
9540 table
= bgp
->rib
[afi
][safi
];
9541 /* use MPLS and ENCAP specific shows until they are merged */
9542 if (safi
== SAFI_MPLS_VPN
) {
9543 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9544 output_arg
, use_json
);
9547 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9548 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9549 output_arg
, use_json
,
9552 /* labeled-unicast routes live in the unicast table */
9553 else if (safi
== SAFI_LABELED_UNICAST
)
9554 safi
= SAFI_UNICAST
;
9556 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9557 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9560 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9561 safi_t safi
, bool use_json
)
9563 struct listnode
*node
, *nnode
;
9566 bool route_output
= false;
9569 vty_out(vty
, "{\n");
9571 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9572 route_output
= true;
9575 vty_out(vty
, ",\n");
9579 vty_out(vty
, "\"%s\":",
9580 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9584 vty_out(vty
, "\nInstance %s:\n",
9585 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9589 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9594 vty_out(vty
, "}\n");
9595 else if (!route_output
)
9596 vty_out(vty
, "%% BGP instance not found\n");
9599 /* Header of detailed BGP route information */
9600 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9601 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9602 afi_t afi
, safi_t safi
, json_object
*json
)
9604 struct bgp_path_info
*pi
;
9607 struct listnode
*node
, *nnode
;
9608 char buf1
[RD_ADDRSTRLEN
];
9609 char buf2
[INET6_ADDRSTRLEN
];
9610 char buf3
[EVPN_ROUTE_STRLEN
];
9611 char prefix_str
[BUFSIZ
];
9616 int route_filter_translated_v4
= 0;
9617 int route_filter_v4
= 0;
9618 int route_filter_translated_v6
= 0;
9619 int route_filter_v6
= 0;
9622 int accept_own_nexthop
= 0;
9625 int no_advertise
= 0;
9629 int has_valid_label
= 0;
9630 mpls_label_t label
= 0;
9631 json_object
*json_adv_to
= NULL
;
9634 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9636 if (has_valid_label
)
9637 label
= label_pton(&rn
->local_label
);
9639 if (safi
== SAFI_EVPN
) {
9642 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9643 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9644 : "", prd
? ":" : "",
9645 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9646 buf3
, sizeof(buf3
)));
9648 json_object_string_add(json
, "rd",
9649 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9651 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9655 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9656 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9657 ? prefix_rd2str(prd
, buf1
,
9660 safi
== SAFI_MPLS_VPN
? ":" : "",
9661 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9666 json_object_string_add(json
, "prefix",
9667 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9670 if (has_valid_label
) {
9672 json_object_int_add(json
, "localLabel", label
);
9674 vty_out(vty
, "Local label: %d\n", label
);
9678 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9679 vty_out(vty
, "not allocated\n");
9681 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9683 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9685 if (pi
->extra
&& pi
->extra
->suppress
)
9688 if (pi
->attr
->community
== NULL
)
9691 no_advertise
+= community_include(
9692 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9693 no_export
+= community_include(pi
->attr
->community
,
9694 COMMUNITY_NO_EXPORT
);
9695 local_as
+= community_include(pi
->attr
->community
,
9696 COMMUNITY_LOCAL_AS
);
9697 accept_own
+= community_include(pi
->attr
->community
,
9698 COMMUNITY_ACCEPT_OWN
);
9699 route_filter_translated_v4
+= community_include(
9700 pi
->attr
->community
,
9701 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9702 route_filter_translated_v6
+= community_include(
9703 pi
->attr
->community
,
9704 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9705 route_filter_v4
+= community_include(
9706 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9707 route_filter_v6
+= community_include(
9708 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9709 llgr_stale
+= community_include(pi
->attr
->community
,
9710 COMMUNITY_LLGR_STALE
);
9711 no_llgr
+= community_include(pi
->attr
->community
,
9713 accept_own_nexthop
+=
9714 community_include(pi
->attr
->community
,
9715 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9716 blackhole
+= community_include(pi
->attr
->community
,
9717 COMMUNITY_BLACKHOLE
);
9718 no_peer
+= community_include(pi
->attr
->community
,
9724 vty_out(vty
, "Paths: (%d available", count
);
9726 vty_out(vty
, ", best #%d", best
);
9727 if (safi
== SAFI_UNICAST
) {
9728 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9729 vty_out(vty
, ", table %s",
9732 vty_out(vty
, ", vrf %s",
9736 vty_out(vty
, ", no best path");
9740 ", accept own local route exported and imported in different VRF");
9741 else if (route_filter_translated_v4
)
9743 ", mark translated RTs for VPNv4 route filtering");
9744 else if (route_filter_v4
)
9746 ", attach RT as-is for VPNv4 route filtering");
9747 else if (route_filter_translated_v6
)
9749 ", mark translated RTs for VPNv6 route filtering");
9750 else if (route_filter_v6
)
9752 ", attach RT as-is for VPNv6 route filtering");
9753 else if (llgr_stale
)
9755 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9758 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9759 else if (accept_own_nexthop
)
9761 ", accept local nexthop");
9763 vty_out(vty
, ", inform peer to blackhole prefix");
9765 vty_out(vty
, ", not advertised to EBGP peer");
9766 else if (no_advertise
)
9767 vty_out(vty
, ", not advertised to any peer");
9769 vty_out(vty
, ", not advertised outside local AS");
9772 ", inform EBGP peer not to advertise to their EBGP peers");
9776 ", Advertisements suppressed by an aggregate.");
9777 vty_out(vty
, ")\n");
9780 /* If we are not using addpath then we can display Advertised to and
9782 * show what peers we advertised the bestpath to. If we are using
9784 * though then we must display Advertised to on a path-by-path basis. */
9785 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9786 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9787 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9788 if (json
&& !json_adv_to
)
9789 json_adv_to
= json_object_new_object();
9791 route_vty_out_advertised_to(
9793 " Advertised to non peer-group peers:\n ",
9800 json_object_object_add(json
, "advertisedTo",
9805 vty_out(vty
, " Not advertised to any peer");
9811 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
9812 struct bgp_node
*bgp_node
, struct vty
*vty
,
9813 struct bgp
*bgp
, afi_t afi
,
9814 safi_t safi
, json_object
*json
,
9815 enum bgp_path_type pathtype
, int *display
)
9817 struct bgp_path_info
*pi
;
9819 char rdbuf
[RD_ADDRSTRLEN
];
9820 json_object
*json_header
= NULL
;
9821 json_object
*json_paths
= NULL
;
9823 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
9826 if (json
&& !json_paths
) {
9827 /* Instantiate json_paths only if path is valid */
9828 json_paths
= json_object_new_array();
9830 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
9831 json_header
= json_object_new_object();
9837 route_vty_out_detail_header(
9838 vty
, bgp
, bgp_node
, pfx_rd
,
9839 AFI_IP
, safi
, json_header
);
9844 if (pathtype
== BGP_PATH_SHOW_ALL
9845 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9846 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
9847 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9848 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
9849 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
9850 route_vty_out_detail(vty
, bgp
, bgp_node
,
9855 if (json
&& json_paths
) {
9856 json_object_object_add(json_header
, "paths", json_paths
);
9859 json_object_object_add(json
, rdbuf
, json_header
);
9863 /* Display specified route of BGP table. */
9864 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9865 struct bgp_table
*rib
, const char *ip_str
,
9866 afi_t afi
, safi_t safi
,
9867 struct prefix_rd
*prd
, int prefix_check
,
9868 enum bgp_path_type pathtype
, bool use_json
)
9872 struct prefix match
;
9873 struct bgp_node
*rn
;
9874 struct bgp_node
*rm
;
9875 struct bgp_table
*table
;
9876 json_object
*json
= NULL
;
9877 json_object
*json_paths
= NULL
;
9879 /* Check IP address argument. */
9880 ret
= str2prefix(ip_str
, &match
);
9882 vty_out(vty
, "address is malformed\n");
9886 match
.family
= afi2family(afi
);
9889 json
= json_object_new_object();
9891 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
9892 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9893 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9895 table
= bgp_node_get_bgp_table_info(rn
);
9899 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9903 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9904 bgp_unlock_node(rm
);
9908 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9909 vty
, bgp
, afi
, safi
, json
,
9910 pathtype
, &display
);
9912 bgp_unlock_node(rm
);
9914 } else if (safi
== SAFI_EVPN
) {
9915 struct bgp_node
*longest_pfx
;
9916 bool is_exact_pfxlen_match
= FALSE
;
9918 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9919 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9921 table
= bgp_node_get_bgp_table_info(rn
);
9926 is_exact_pfxlen_match
= FALSE
;
9928 * Search through all the prefixes for a match. The
9929 * pfx's are enumerated in ascending order of pfxlens.
9930 * So, the last pfx match is the longest match. Set
9931 * is_exact_pfxlen_match when we get exact pfxlen match
9933 for (rm
= bgp_table_top(table
); rm
;
9934 rm
= bgp_route_next(rm
)) {
9936 * Get prefixlen of the ip-prefix within type5
9939 if (evpn_type5_prefix_match(&rm
->p
,
9940 &match
) && rm
->info
) {
9943 bgp_evpn_get_type5_prefixlen(&rm
->p
);
9944 if (type5_pfxlen
== match
.prefixlen
) {
9945 is_exact_pfxlen_match
= TRUE
;
9946 bgp_unlock_node(rm
);
9955 if (prefix_check
&& !is_exact_pfxlen_match
)
9961 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9962 vty
, bgp
, afi
, safi
, json
,
9963 pathtype
, &display
);
9965 bgp_unlock_node(rm
);
9967 } else if (safi
== SAFI_FLOWSPEC
) {
9969 json_paths
= json_object_new_array();
9971 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9972 &match
, prefix_check
,
9976 if (use_json
&& display
)
9977 json_object_object_add(json
, "paths", json_paths
);
9979 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9981 || rn
->p
.prefixlen
== match
.prefixlen
) {
9982 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
9984 pathtype
, &display
);
9987 bgp_unlock_node(rn
);
9992 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9993 json
, JSON_C_TO_STRING_PRETTY
|
9994 JSON_C_TO_STRING_NOSLASHESCAPE
));
9995 json_object_free(json
);
9998 vty_out(vty
, "%% Network not in table\n");
10003 return CMD_SUCCESS
;
10006 /* Display specified route of Main RIB */
10007 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10008 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10009 int prefix_check
, enum bgp_path_type pathtype
,
10013 bgp
= bgp_get_default();
10016 vty_out(vty
, "No BGP process is configured\n");
10018 vty_out(vty
, "{}\n");
10019 return CMD_WARNING
;
10023 /* labeled-unicast routes live in the unicast table */
10024 if (safi
== SAFI_LABELED_UNICAST
)
10025 safi
= SAFI_UNICAST
;
10027 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10028 afi
, safi
, prd
, prefix_check
, pathtype
,
10032 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10033 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10034 safi_t safi
, bool uj
)
10036 struct lcommunity
*lcom
;
10042 b
= buffer_new(1024);
10043 for (i
= 0; i
< argc
; i
++) {
10045 buffer_putc(b
, ' ');
10047 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10049 buffer_putstr(b
, argv
[i
]->arg
);
10053 buffer_putc(b
, '\0');
10055 str
= buffer_getstr(b
);
10058 lcom
= lcommunity_str2com(str
);
10059 XFREE(MTYPE_TMP
, str
);
10061 vty_out(vty
, "%% Large-community malformed\n");
10062 return CMD_WARNING
;
10065 return bgp_show(vty
, bgp
, afi
, safi
,
10066 (exact
? bgp_show_type_lcommunity_exact
10067 : bgp_show_type_lcommunity
),
10071 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10072 const char *lcom
, bool exact
, afi_t afi
,
10073 safi_t safi
, bool uj
)
10075 struct community_list
*list
;
10077 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10078 LARGE_COMMUNITY_LIST_MASTER
);
10079 if (list
== NULL
) {
10080 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10082 return CMD_WARNING
;
10085 return bgp_show(vty
, bgp
, afi
, safi
,
10086 (exact
? bgp_show_type_lcommunity_list_exact
10087 : bgp_show_type_lcommunity_list
),
10091 DEFUN (show_ip_bgp_large_community_list
,
10092 show_ip_bgp_large_community_list_cmd
,
10093 "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]",
10097 BGP_INSTANCE_HELP_STR
10099 BGP_SAFI_WITH_LABEL_HELP_STR
10100 "Display routes matching the large-community-list\n"
10101 "large-community-list number\n"
10102 "large-community-list name\n"
10103 "Exact match of the large-communities\n"
10107 afi_t afi
= AFI_IP6
;
10108 safi_t safi
= SAFI_UNICAST
;
10110 bool exact_match
= 0;
10112 if (argv_find(argv
, argc
, "ip", &idx
))
10114 if (argv_find(argv
, argc
, "view", &idx
)
10115 || argv_find(argv
, argc
, "vrf", &idx
))
10116 vrf
= argv
[++idx
]->arg
;
10117 if (argv_find(argv
, argc
, "ipv4", &idx
)
10118 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10119 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10120 if (argv_find(argv
, argc
, "unicast", &idx
)
10121 || argv_find(argv
, argc
, "multicast", &idx
))
10122 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10125 bool uj
= use_json(argc
, argv
);
10127 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10129 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10130 return CMD_WARNING
;
10133 argv_find(argv
, argc
, "large-community-list", &idx
);
10135 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10137 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10140 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10141 exact_match
, afi
, safi
, uj
);
10143 DEFUN (show_ip_bgp_large_community
,
10144 show_ip_bgp_large_community_cmd
,
10145 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10149 BGP_INSTANCE_HELP_STR
10151 BGP_SAFI_WITH_LABEL_HELP_STR
10152 "Display routes matching the large-communities\n"
10153 "List of large-community numbers\n"
10154 "Exact match of the large-communities\n"
10158 afi_t afi
= AFI_IP6
;
10159 safi_t safi
= SAFI_UNICAST
;
10161 bool exact_match
= 0;
10163 if (argv_find(argv
, argc
, "ip", &idx
))
10165 if (argv_find(argv
, argc
, "view", &idx
)
10166 || argv_find(argv
, argc
, "vrf", &idx
))
10167 vrf
= argv
[++idx
]->arg
;
10168 if (argv_find(argv
, argc
, "ipv4", &idx
)
10169 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10170 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10171 if (argv_find(argv
, argc
, "unicast", &idx
)
10172 || argv_find(argv
, argc
, "multicast", &idx
))
10173 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10176 bool uj
= use_json(argc
, argv
);
10178 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10180 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10181 return CMD_WARNING
;
10184 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10185 if (argv_find(argv
, argc
, "exact-match", &idx
))
10187 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10188 exact_match
, afi
, safi
, uj
);
10190 return bgp_show(vty
, bgp
, afi
, safi
,
10191 bgp_show_type_lcommunity_all
, NULL
, uj
);
10194 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10198 /* BGP route print out function without JSON */
10199 DEFUN (show_ip_bgp
,
10201 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10202 <dampening <parameters>\
10207 |community-list <(1-500)|WORD> [exact-match]\
10208 |A.B.C.D/M longer-prefixes\
10209 |X:X::X:X/M longer-prefixes\
10214 BGP_INSTANCE_HELP_STR
10216 BGP_SAFI_WITH_LABEL_HELP_STR
10217 "Display detailed information about dampening\n"
10218 "Display detail of configured dampening parameters\n"
10219 "Display routes matching the route-map\n"
10220 "A route-map to match on\n"
10221 "Display routes conforming to the prefix-list\n"
10222 "Prefix-list name\n"
10223 "Display routes conforming to the filter-list\n"
10224 "Regular expression access list name\n"
10225 "BGP RIB advertisement statistics\n"
10226 "Display routes matching the community-list\n"
10227 "community-list number\n"
10228 "community-list name\n"
10229 "Exact match of the communities\n"
10231 "Display route and more specific routes\n"
10233 "Display route and more specific routes\n")
10235 afi_t afi
= AFI_IP6
;
10236 safi_t safi
= SAFI_UNICAST
;
10237 int exact_match
= 0;
10238 struct bgp
*bgp
= NULL
;
10241 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10244 return CMD_WARNING
;
10246 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10247 if (argv_find(argv
, argc
, "parameters", &idx
))
10248 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10251 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10252 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10253 safi
, bgp_show_type_prefix_list
);
10255 if (argv_find(argv
, argc
, "filter-list", &idx
))
10256 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10257 safi
, bgp_show_type_filter_list
);
10259 if (argv_find(argv
, argc
, "statistics", &idx
))
10260 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10262 if (argv_find(argv
, argc
, "route-map", &idx
))
10263 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10264 safi
, bgp_show_type_route_map
);
10266 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10267 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10268 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10270 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10271 exact_match
, afi
, safi
);
10273 /* prefix-longer */
10274 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10275 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10276 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10278 bgp_show_type_prefix_longer
);
10280 return CMD_WARNING
;
10283 /* BGP route print out function with JSON */
10284 DEFUN (show_ip_bgp_json
,
10285 show_ip_bgp_json_cmd
,
10286 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10288 |dampening <flap-statistics|dampened-paths>\
10289 |community [AA:NN|local-AS|no-advertise|no-export\
10290 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10291 |accept-own|accept-own-nexthop|route-filter-v6\
10292 |route-filter-v4|route-filter-translated-v6\
10293 |route-filter-translated-v4] [exact-match]\
10298 BGP_INSTANCE_HELP_STR
10300 BGP_SAFI_WITH_LABEL_HELP_STR
10301 "Display only routes with non-natural netmasks\n"
10302 "Display detailed information about dampening\n"
10303 "Display flap statistics of routes\n"
10304 "Display paths suppressed due to dampening\n"
10305 "Display routes matching the communities\n"
10307 "Do not send outside local AS (well-known community)\n"
10308 "Do not advertise to any peer (well-known community)\n"
10309 "Do not export to next AS (well-known community)\n"
10310 "Graceful shutdown (well-known community)\n"
10311 "Do not export to any peer (well-known community)\n"
10312 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10313 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10314 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10315 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10316 "Should accept VPN route with local nexthop (well-known community)\n"
10317 "RT VPNv6 route filtering (well-known community)\n"
10318 "RT VPNv4 route filtering (well-known community)\n"
10319 "RT translated VPNv6 route filtering (well-known community)\n"
10320 "RT translated VPNv4 route filtering (well-known community)\n"
10321 "Exact match of the communities\n"
10324 afi_t afi
= AFI_IP6
;
10325 safi_t safi
= SAFI_UNICAST
;
10326 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10327 struct bgp
*bgp
= NULL
;
10329 int exact_match
= 0;
10330 bool uj
= use_json(argc
, argv
);
10335 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10338 return CMD_WARNING
;
10340 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10341 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10344 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10345 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10346 return bgp_show(vty
, bgp
, afi
, safi
,
10347 bgp_show_type_dampend_paths
, NULL
, uj
);
10348 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10349 return bgp_show(vty
, bgp
, afi
, safi
,
10350 bgp_show_type_flap_statistics
, NULL
,
10354 if (argv_find(argv
, argc
, "community", &idx
)) {
10355 char *maybecomm
= NULL
;
10356 char *community
= NULL
;
10358 if (idx
+ 1 < argc
) {
10359 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10360 maybecomm
= argv
[idx
+ 1]->arg
;
10362 maybecomm
= argv
[idx
+ 1]->text
;
10365 if (maybecomm
&& !strmatch(maybecomm
, "json")
10366 && !strmatch(maybecomm
, "exact-match"))
10367 community
= maybecomm
;
10369 if (argv_find(argv
, argc
, "exact-match", &idx
))
10373 return bgp_show_community(vty
, bgp
, community
,
10374 exact_match
, afi
, safi
, uj
);
10376 return (bgp_show(vty
, bgp
, afi
, safi
,
10377 bgp_show_type_community_all
, NULL
,
10381 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10384 DEFUN (show_ip_bgp_route
,
10385 show_ip_bgp_route_cmd
,
10386 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10387 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10391 BGP_INSTANCE_HELP_STR
10393 BGP_SAFI_WITH_LABEL_HELP_STR
10394 "Network in the BGP routing table to display\n"
10396 "Network in the BGP routing table to display\n"
10398 "Display only the bestpath\n"
10399 "Display only multipaths\n"
10402 int prefix_check
= 0;
10404 afi_t afi
= AFI_IP6
;
10405 safi_t safi
= SAFI_UNICAST
;
10406 char *prefix
= NULL
;
10407 struct bgp
*bgp
= NULL
;
10408 enum bgp_path_type path_type
;
10409 bool uj
= use_json(argc
, argv
);
10413 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10416 return CMD_WARNING
;
10420 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10421 return CMD_WARNING
;
10424 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10425 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10426 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10428 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10429 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10432 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10433 && afi
!= AFI_IP6
) {
10435 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10436 return CMD_WARNING
;
10438 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10439 && afi
!= AFI_IP
) {
10441 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10442 return CMD_WARNING
;
10445 prefix
= argv
[idx
]->arg
;
10447 /* [<bestpath|multipath>] */
10448 if (argv_find(argv
, argc
, "bestpath", &idx
))
10449 path_type
= BGP_PATH_SHOW_BESTPATH
;
10450 else if (argv_find(argv
, argc
, "multipath", &idx
))
10451 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10453 path_type
= BGP_PATH_SHOW_ALL
;
10455 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10459 DEFUN (show_ip_bgp_regexp
,
10460 show_ip_bgp_regexp_cmd
,
10461 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10465 BGP_INSTANCE_HELP_STR
10467 BGP_SAFI_WITH_LABEL_HELP_STR
10468 "Display routes matching the AS path regular expression\n"
10469 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10471 afi_t afi
= AFI_IP6
;
10472 safi_t safi
= SAFI_UNICAST
;
10473 struct bgp
*bgp
= NULL
;
10476 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10479 return CMD_WARNING
;
10481 // get index of regex
10482 argv_find(argv
, argc
, "regexp", &idx
);
10485 char *regstr
= argv_concat(argv
, argc
, idx
);
10486 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10487 bgp_show_type_regexp
);
10488 XFREE(MTYPE_TMP
, regstr
);
10492 DEFUN (show_ip_bgp_instance_all
,
10493 show_ip_bgp_instance_all_cmd
,
10494 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10498 BGP_INSTANCE_ALL_HELP_STR
10500 BGP_SAFI_WITH_LABEL_HELP_STR
10503 afi_t afi
= AFI_IP
;
10504 safi_t safi
= SAFI_UNICAST
;
10505 struct bgp
*bgp
= NULL
;
10507 bool uj
= use_json(argc
, argv
);
10512 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10515 return CMD_WARNING
;
10517 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10518 return CMD_SUCCESS
;
10521 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10522 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10527 if (!config_bgp_aspath_validate(regstr
)) {
10528 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10530 return CMD_WARNING_CONFIG_FAILED
;
10533 regex
= bgp_regcomp(regstr
);
10535 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10536 return CMD_WARNING
;
10539 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10540 bgp_regex_free(regex
);
10544 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10545 const char *prefix_list_str
, afi_t afi
,
10546 safi_t safi
, enum bgp_show_type type
)
10548 struct prefix_list
*plist
;
10550 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10551 if (plist
== NULL
) {
10552 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10554 return CMD_WARNING
;
10557 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10560 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10561 const char *filter
, afi_t afi
, safi_t safi
,
10562 enum bgp_show_type type
)
10564 struct as_list
*as_list
;
10566 as_list
= as_list_lookup(filter
);
10567 if (as_list
== NULL
) {
10568 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10570 return CMD_WARNING
;
10573 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10576 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10577 const char *rmap_str
, afi_t afi
, safi_t safi
,
10578 enum bgp_show_type type
)
10580 struct route_map
*rmap
;
10582 rmap
= route_map_lookup_by_name(rmap_str
);
10584 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10585 return CMD_WARNING
;
10588 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10591 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10592 const char *comstr
, int exact
, afi_t afi
,
10593 safi_t safi
, bool use_json
)
10595 struct community
*com
;
10598 com
= community_str2com(comstr
);
10600 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10601 return CMD_WARNING
;
10604 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10605 (exact
? bgp_show_type_community_exact
10606 : bgp_show_type_community
),
10608 community_free(&com
);
10613 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10614 const char *com
, int exact
, afi_t afi
,
10617 struct community_list
*list
;
10619 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10620 if (list
== NULL
) {
10621 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10622 return CMD_WARNING
;
10625 return bgp_show(vty
, bgp
, afi
, safi
,
10626 (exact
? bgp_show_type_community_list_exact
10627 : bgp_show_type_community_list
),
10631 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10632 const char *prefix
, afi_t afi
, safi_t safi
,
10633 enum bgp_show_type type
)
10640 ret
= str2prefix(prefix
, p
);
10642 vty_out(vty
, "%% Malformed Prefix\n");
10643 return CMD_WARNING
;
10646 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10652 BGP_STATS_MAXBITLEN
= 0,
10654 BGP_STATS_PREFIXES
,
10656 BGP_STATS_UNAGGREGATEABLE
,
10657 BGP_STATS_MAX_AGGREGATEABLE
,
10658 BGP_STATS_AGGREGATES
,
10660 BGP_STATS_ASPATH_COUNT
,
10661 BGP_STATS_ASPATH_MAXHOPS
,
10662 BGP_STATS_ASPATH_TOTHOPS
,
10663 BGP_STATS_ASPATH_MAXSIZE
,
10664 BGP_STATS_ASPATH_TOTSIZE
,
10665 BGP_STATS_ASN_HIGHEST
,
10669 static const char *const table_stats_strs
[] = {
10670 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10671 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10672 [BGP_STATS_RIB
] = "Total Advertisements",
10673 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10674 [BGP_STATS_MAX_AGGREGATEABLE
] =
10675 "Maximum aggregateable prefixes",
10676 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10677 [BGP_STATS_SPACE
] = "Address space advertised",
10678 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10679 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10680 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10681 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10682 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10683 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10684 [BGP_STATS_MAX
] = NULL
,
10687 struct bgp_table_stats
{
10688 struct bgp_table
*table
;
10689 unsigned long long counts
[BGP_STATS_MAX
];
10690 double total_space
;
10694 #define TALLY_SIGFIG 100000
10695 static unsigned long
10696 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10698 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10699 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10700 unsigned long ret
= newtot
/ count
;
10702 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10709 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10710 struct bgp_table_stats
*ts
, unsigned int space
)
10712 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10713 struct bgp_path_info
*pi
;
10718 if (!bgp_node_has_bgp_path_info_data(rn
))
10721 ts
->counts
[BGP_STATS_PREFIXES
]++;
10722 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10725 ts
->counts
[BGP_STATS_AVGPLEN
]
10726 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10727 ts
->counts
[BGP_STATS_AVGPLEN
],
10731 /* check if the prefix is included by any other announcements */
10732 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10733 prn
= bgp_node_parent_nolock(prn
);
10735 if (prn
== NULL
|| prn
== top
) {
10736 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10737 /* announced address space */
10739 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10740 } else if (bgp_node_has_bgp_path_info_data(prn
))
10741 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10744 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10745 ts
->counts
[BGP_STATS_RIB
]++;
10747 if (CHECK_FLAG(pi
->attr
->flag
,
10748 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
10749 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10751 /* as-path stats */
10752 if (pi
->attr
->aspath
) {
10753 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10754 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10755 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10757 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10759 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10760 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10762 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10763 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10765 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10766 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10768 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10769 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10770 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10772 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10773 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10774 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10777 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10778 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10783 static int bgp_table_stats_walker(struct thread
*t
)
10785 struct bgp_node
*rn
, *nrn
;
10786 struct bgp_node
*top
;
10787 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10788 unsigned int space
= 0;
10790 if (!(top
= bgp_table_top(ts
->table
)))
10793 switch (ts
->table
->afi
) {
10795 space
= IPV4_MAX_BITLEN
;
10798 space
= IPV6_MAX_BITLEN
;
10804 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10806 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10807 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10808 struct bgp_table
*table
;
10810 table
= bgp_node_get_bgp_table_info(rn
);
10814 top
= bgp_table_top(table
);
10815 for (nrn
= bgp_table_top(table
); nrn
;
10816 nrn
= bgp_route_next(nrn
))
10817 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10819 bgp_table_stats_rn(rn
, top
, ts
, space
);
10826 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10829 struct bgp_table_stats ts
;
10832 if (!bgp
->rib
[afi
][safi
]) {
10833 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10835 return CMD_WARNING
;
10838 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
10840 /* labeled-unicast routes live in the unicast table */
10841 if (safi
== SAFI_LABELED_UNICAST
)
10842 safi
= SAFI_UNICAST
;
10844 memset(&ts
, 0, sizeof(ts
));
10845 ts
.table
= bgp
->rib
[afi
][safi
];
10846 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10848 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10849 if (!table_stats_strs
[i
])
10854 case BGP_STATS_ASPATH_AVGHOPS
:
10855 case BGP_STATS_ASPATH_AVGSIZE
:
10856 case BGP_STATS_AVGPLEN
:
10857 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10858 vty_out (vty
, "%12.2f",
10859 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10862 case BGP_STATS_ASPATH_TOTHOPS
:
10863 case BGP_STATS_ASPATH_TOTSIZE
:
10864 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10865 vty_out(vty
, "%12.2f",
10867 ? (float)ts
.counts
[i
]
10869 [BGP_STATS_ASPATH_COUNT
]
10872 case BGP_STATS_TOTPLEN
:
10873 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10874 vty_out(vty
, "%12.2f",
10876 ? (float)ts
.counts
[i
]
10878 [BGP_STATS_PREFIXES
]
10881 case BGP_STATS_SPACE
:
10882 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10883 vty_out(vty
, "%12g\n", ts
.total_space
);
10885 if (afi
== AFI_IP6
) {
10886 vty_out(vty
, "%30s: ", "/32 equivalent ");
10887 vty_out(vty
, "%12g\n",
10888 ts
.total_space
* pow(2.0, -128 + 32));
10889 vty_out(vty
, "%30s: ", "/48 equivalent ");
10890 vty_out(vty
, "%12g\n",
10891 ts
.total_space
* pow(2.0, -128 + 48));
10893 vty_out(vty
, "%30s: ", "% announced ");
10894 vty_out(vty
, "%12.2f\n",
10895 ts
.total_space
* 100. * pow(2.0, -32));
10896 vty_out(vty
, "%30s: ", "/8 equivalent ");
10897 vty_out(vty
, "%12.2f\n",
10898 ts
.total_space
* pow(2.0, -32 + 8));
10899 vty_out(vty
, "%30s: ", "/24 equivalent ");
10900 vty_out(vty
, "%12.2f\n",
10901 ts
.total_space
* pow(2.0, -32 + 24));
10905 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10906 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10909 vty_out(vty
, "\n");
10911 return CMD_SUCCESS
;
10923 PCOUNT_PFCNT
, /* the figure we display to users */
10927 static const char *const pcount_strs
[] = {
10928 [PCOUNT_ADJ_IN
] = "Adj-in",
10929 [PCOUNT_DAMPED
] = "Damped",
10930 [PCOUNT_REMOVED
] = "Removed",
10931 [PCOUNT_HISTORY
] = "History",
10932 [PCOUNT_STALE
] = "Stale",
10933 [PCOUNT_VALID
] = "Valid",
10934 [PCOUNT_ALL
] = "All RIB",
10935 [PCOUNT_COUNTED
] = "PfxCt counted",
10936 [PCOUNT_PFCNT
] = "Useable",
10937 [PCOUNT_MAX
] = NULL
,
10940 struct peer_pcounts
{
10941 unsigned int count
[PCOUNT_MAX
];
10942 const struct peer
*peer
;
10943 const struct bgp_table
*table
;
10947 static void bgp_peer_count_proc(struct bgp_node
*rn
,
10948 struct peer_pcounts
*pc
)
10950 const struct bgp_adj_in
*ain
;
10951 const struct bgp_path_info
*pi
;
10952 const struct peer
*peer
= pc
->peer
;
10954 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10955 if (ain
->peer
== peer
)
10956 pc
->count
[PCOUNT_ADJ_IN
]++;
10958 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10960 if (pi
->peer
!= peer
)
10963 pc
->count
[PCOUNT_ALL
]++;
10965 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10966 pc
->count
[PCOUNT_DAMPED
]++;
10967 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10968 pc
->count
[PCOUNT_HISTORY
]++;
10969 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10970 pc
->count
[PCOUNT_REMOVED
]++;
10971 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10972 pc
->count
[PCOUNT_STALE
]++;
10973 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10974 pc
->count
[PCOUNT_VALID
]++;
10975 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10976 pc
->count
[PCOUNT_PFCNT
]++;
10978 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10979 pc
->count
[PCOUNT_COUNTED
]++;
10980 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10982 EC_LIB_DEVELOPMENT
,
10983 "Attempting to count but flags say it is unusable");
10985 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10987 EC_LIB_DEVELOPMENT
,
10988 "Not counted but flags say we should");
10993 static int bgp_peer_count_walker(struct thread
*t
)
10995 struct bgp_node
*rn
, *rm
;
10996 const struct bgp_table
*table
;
10997 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10999 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
11000 || pc
->safi
== SAFI_EVPN
) {
11001 /* Special handling for 2-level routing tables. */
11002 for (rn
= bgp_table_top(pc
->table
); rn
;
11003 rn
= bgp_route_next(rn
)) {
11004 table
= bgp_node_get_bgp_table_info(rn
);
11006 for (rm
= bgp_table_top(table
); rm
;
11007 rm
= bgp_route_next(rm
))
11008 bgp_peer_count_proc(rm
, pc
);
11011 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
11012 bgp_peer_count_proc(rn
, pc
);
11017 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11018 safi_t safi
, bool use_json
)
11020 struct peer_pcounts pcounts
= {.peer
= peer
};
11022 json_object
*json
= NULL
;
11023 json_object
*json_loop
= NULL
;
11026 json
= json_object_new_object();
11027 json_loop
= json_object_new_object();
11030 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
11031 || !peer
->bgp
->rib
[afi
][safi
]) {
11033 json_object_string_add(
11035 "No such neighbor or address family");
11036 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11037 json_object_free(json
);
11039 vty_out(vty
, "%% No such neighbor or address family\n");
11041 return CMD_WARNING
;
11044 memset(&pcounts
, 0, sizeof(pcounts
));
11045 pcounts
.peer
= peer
;
11046 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11047 pcounts
.safi
= safi
;
11049 /* in-place call via thread subsystem so as to record execution time
11050 * stats for the thread-walk (i.e. ensure this can't be blamed on
11051 * on just vty_read()).
11053 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11056 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11057 json_object_string_add(json
, "multiProtocol",
11058 get_afi_safi_str(afi
, safi
, true));
11059 json_object_int_add(json
, "pfxCounter",
11060 peer
->pcount
[afi
][safi
]);
11062 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11063 json_object_int_add(json_loop
, pcount_strs
[i
],
11066 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
11068 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11069 json_object_string_add(json
, "pfxctDriftFor",
11071 json_object_string_add(
11072 json
, "recommended",
11073 "Please report this bug, with the above command output");
11075 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11076 json
, JSON_C_TO_STRING_PRETTY
));
11077 json_object_free(json
);
11081 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
11082 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
11083 peer
->hostname
, peer
->host
,
11084 get_afi_safi_str(afi
, safi
, false));
11086 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11087 get_afi_safi_str(afi
, safi
, false));
11090 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
11091 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11093 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11094 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
11097 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11098 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
11100 "Please report this bug, with the above command output\n");
11104 return CMD_SUCCESS
;
11107 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11108 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11109 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11110 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11114 BGP_INSTANCE_HELP_STR
11117 "Detailed information on TCP and BGP neighbor connections\n"
11118 "Neighbor to display information about\n"
11119 "Neighbor to display information about\n"
11120 "Neighbor on BGP configured interface\n"
11121 "Display detailed prefix count information\n"
11124 afi_t afi
= AFI_IP6
;
11125 safi_t safi
= SAFI_UNICAST
;
11128 struct bgp
*bgp
= NULL
;
11129 bool uj
= use_json(argc
, argv
);
11134 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11137 return CMD_WARNING
;
11139 argv_find(argv
, argc
, "neighbors", &idx
);
11140 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11142 return CMD_WARNING
;
11144 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11147 #ifdef KEEP_OLD_VPN_COMMANDS
11148 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11149 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11150 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11155 "Display information about all VPNv4 NLRIs\n"
11156 "Detailed information on TCP and BGP neighbor connections\n"
11157 "Neighbor to display information about\n"
11158 "Neighbor to display information about\n"
11159 "Neighbor on BGP configured interface\n"
11160 "Display detailed prefix count information\n"
11165 bool uj
= use_json(argc
, argv
);
11167 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11169 return CMD_WARNING
;
11171 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11174 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11175 show_ip_bgp_vpn_all_route_prefix_cmd
,
11176 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11181 "Display information about all VPNv4 NLRIs\n"
11182 "Network in the BGP routing table to display\n"
11183 "Network in the BGP routing table to display\n"
11187 char *network
= NULL
;
11188 struct bgp
*bgp
= bgp_get_default();
11190 vty_out(vty
, "Can't find default instance\n");
11191 return CMD_WARNING
;
11194 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11195 network
= argv
[idx
]->arg
;
11196 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11197 network
= argv
[idx
]->arg
;
11199 vty_out(vty
, "Unable to figure out Network\n");
11200 return CMD_WARNING
;
11203 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11204 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11206 #endif /* KEEP_OLD_VPN_COMMANDS */
11208 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11209 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11210 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11215 "Network in the BGP routing table to display\n"
11216 "Network in the BGP routing table to display\n"
11217 "Network in the BGP routing table to display\n"
11218 "Network in the BGP routing table to display\n"
11222 char *network
= NULL
;
11223 int prefix_check
= 0;
11225 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11226 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11227 network
= argv
[idx
]->arg
;
11228 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11229 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11230 network
= argv
[idx
]->arg
;
11233 vty_out(vty
, "Unable to figure out Network\n");
11234 return CMD_WARNING
;
11236 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11237 prefix_check
, BGP_PATH_SHOW_ALL
,
11238 use_json(argc
, argv
));
11241 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11242 safi_t safi
, enum bgp_show_adj_route_type type
,
11243 const char *rmap_name
, bool use_json
,
11246 struct bgp_table
*table
;
11247 struct bgp_adj_in
*ain
;
11248 struct bgp_adj_out
*adj
;
11249 unsigned long output_count
;
11250 unsigned long filtered_count
;
11251 struct bgp_node
*rn
;
11257 struct update_subgroup
*subgrp
;
11258 json_object
*json_scode
= NULL
;
11259 json_object
*json_ocode
= NULL
;
11260 json_object
*json_ar
= NULL
;
11261 struct peer_af
*paf
;
11262 bool route_filtered
;
11265 json_scode
= json_object_new_object();
11266 json_ocode
= json_object_new_object();
11267 json_ar
= json_object_new_object();
11269 json_object_string_add(json_scode
, "suppressed", "s");
11270 json_object_string_add(json_scode
, "damped", "d");
11271 json_object_string_add(json_scode
, "history", "h");
11272 json_object_string_add(json_scode
, "valid", "*");
11273 json_object_string_add(json_scode
, "best", ">");
11274 json_object_string_add(json_scode
, "multipath", "=");
11275 json_object_string_add(json_scode
, "internal", "i");
11276 json_object_string_add(json_scode
, "ribFailure", "r");
11277 json_object_string_add(json_scode
, "stale", "S");
11278 json_object_string_add(json_scode
, "removed", "R");
11280 json_object_string_add(json_ocode
, "igp", "i");
11281 json_object_string_add(json_ocode
, "egp", "e");
11282 json_object_string_add(json_ocode
, "incomplete", "?");
11289 json_object_string_add(json
, "alert", "no BGP");
11290 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11291 json_object_free(json
);
11293 vty_out(vty
, "%% No bgp\n");
11297 /* labeled-unicast routes live in the unicast table */
11298 if (safi
== SAFI_LABELED_UNICAST
)
11299 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11301 table
= bgp
->rib
[afi
][safi
];
11303 output_count
= filtered_count
= 0;
11304 subgrp
= peer_subgroup(peer
, afi
, safi
);
11306 if (type
== bgp_show_adj_route_advertised
&& subgrp
11307 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11309 json_object_int_add(json
, "bgpTableVersion",
11311 json_object_string_add(json
, "bgpLocalRouterId",
11312 inet_ntoa(bgp
->router_id
));
11313 json_object_int_add(json
, "defaultLocPrf",
11314 bgp
->default_local_pref
);
11315 json_object_int_add(json
, "localAS", bgp
->as
);
11316 json_object_object_add(json
, "bgpStatusCodes",
11318 json_object_object_add(json
, "bgpOriginCodes",
11320 json_object_string_add(
11321 json
, "bgpOriginatingDefaultNetwork",
11322 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11324 vty_out(vty
, "BGP table version is %" PRIu64
11325 ", local router ID is %s, vrf id ",
11326 table
->version
, inet_ntoa(bgp
->router_id
));
11327 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11328 vty_out(vty
, "%s", VRFID_NONE_STR
);
11330 vty_out(vty
, "%u", bgp
->vrf_id
);
11331 vty_out(vty
, "\n");
11332 vty_out(vty
, "Default local pref %u, ",
11333 bgp
->default_local_pref
);
11334 vty_out(vty
, "local AS %u\n", bgp
->as
);
11335 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11336 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11337 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11339 vty_out(vty
, "Originating default network %s\n\n",
11340 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11345 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11346 if (type
== bgp_show_adj_route_received
11347 || type
== bgp_show_adj_route_filtered
) {
11348 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11349 if (ain
->peer
!= peer
)
11354 json_object_int_add(
11355 json
, "bgpTableVersion",
11357 json_object_string_add(
11359 "bgpLocalRouterId",
11362 json_object_int_add(json
,
11364 bgp
->default_local_pref
);
11365 json_object_int_add(json
,
11366 "localAS", bgp
->as
);
11367 json_object_object_add(
11368 json
, "bgpStatusCodes",
11370 json_object_object_add(
11371 json
, "bgpOriginCodes",
11375 "BGP table version is 0, local router ID is %s, vrf id ",
11378 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11384 vty_out(vty
, "\n");
11386 "Default local pref %u, ",
11387 bgp
->default_local_pref
);
11388 vty_out(vty
, "local AS %u\n",
11391 BGP_SHOW_SCODE_HEADER
);
11393 BGP_SHOW_NCODE_HEADER
);
11395 BGP_SHOW_OCODE_HEADER
);
11401 vty_out(vty
, BGP_SHOW_HEADER
);
11406 route_filtered
= false;
11408 /* Filter prefix using distribute list,
11409 * filter list or prefix list
11411 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11412 safi
)) == FILTER_DENY
)
11413 route_filtered
= true;
11415 /* Filter prefix using route-map */
11416 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11417 afi
, safi
, rmap_name
, NULL
, 0,
11420 if (type
== bgp_show_adj_route_filtered
&&
11421 !route_filtered
&& ret
!= RMAP_DENY
) {
11422 bgp_attr_undup(&attr
, ain
->attr
);
11426 if (type
== bgp_show_adj_route_received
&&
11427 (route_filtered
|| ret
== RMAP_DENY
))
11430 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11431 use_json
, json_ar
);
11432 bgp_attr_undup(&attr
, ain
->attr
);
11435 } else if (type
== bgp_show_adj_route_advertised
) {
11436 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11437 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11438 if (paf
->peer
!= peer
|| !adj
->attr
)
11443 json_object_int_add(
11447 json_object_string_add(
11449 "bgpLocalRouterId",
11452 json_object_int_add(
11453 json
, "defaultLocPrf",
11454 bgp
->default_local_pref
11456 json_object_int_add(
11459 json_object_object_add(
11463 json_object_object_add(
11469 "BGP table version is %" PRIu64
11470 ", local router ID is %s, vrf id ",
11483 vty_out(vty
, "\n");
11485 "Default local pref %u, ",
11486 bgp
->default_local_pref
11492 BGP_SHOW_SCODE_HEADER
);
11494 BGP_SHOW_NCODE_HEADER
);
11496 BGP_SHOW_OCODE_HEADER
);
11508 ret
= bgp_output_modifier(
11509 peer
, &rn
->p
, &attr
, afi
, safi
,
11512 if (ret
!= RMAP_DENY
) {
11513 route_vty_out_tmp(vty
, &rn
->p
,
11522 bgp_attr_undup(&attr
, adj
->attr
);
11528 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11529 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11530 json_object_int_add(json
, "filteredPrefixCounter",
11533 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11534 json
, JSON_C_TO_STRING_PRETTY
));
11535 json_object_free(json
);
11536 } else if (output_count
> 0) {
11537 if (filtered_count
> 0)
11539 "\nTotal number of prefixes %ld (%ld filtered)\n",
11540 output_count
, filtered_count
);
11542 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11547 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11548 safi_t safi
, enum bgp_show_adj_route_type type
,
11549 const char *rmap_name
, bool use_json
)
11551 json_object
*json
= NULL
;
11554 json
= json_object_new_object();
11556 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11558 json_object_string_add(
11560 "No such neighbor or address family");
11561 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11562 json_object_free(json
);
11564 vty_out(vty
, "%% No such neighbor or address family\n");
11566 return CMD_WARNING
;
11569 if ((type
== bgp_show_adj_route_received
11570 || type
== bgp_show_adj_route_filtered
)
11571 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11572 PEER_FLAG_SOFT_RECONFIG
)) {
11574 json_object_string_add(
11576 "Inbound soft reconfiguration not enabled");
11577 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11578 json_object_free(json
);
11581 "%% Inbound soft reconfiguration not enabled\n");
11583 return CMD_WARNING
;
11586 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11588 return CMD_SUCCESS
;
11591 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11592 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11593 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11594 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11598 BGP_INSTANCE_HELP_STR
11600 BGP_SAFI_WITH_LABEL_HELP_STR
11601 "Detailed information on TCP and BGP neighbor connections\n"
11602 "Neighbor to display information about\n"
11603 "Neighbor to display information about\n"
11604 "Neighbor on BGP configured interface\n"
11605 "Display the routes advertised to a BGP neighbor\n"
11606 "Display the received routes from neighbor\n"
11607 "Display the filtered routes received from neighbor\n"
11608 "Route-map to modify the attributes\n"
11609 "Name of the route map\n"
11612 afi_t afi
= AFI_IP6
;
11613 safi_t safi
= SAFI_UNICAST
;
11614 char *rmap_name
= NULL
;
11615 char *peerstr
= NULL
;
11616 struct bgp
*bgp
= NULL
;
11618 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11620 bool uj
= use_json(argc
, argv
);
11625 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11628 return CMD_WARNING
;
11630 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11631 argv_find(argv
, argc
, "neighbors", &idx
);
11632 peerstr
= argv
[++idx
]->arg
;
11634 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11636 return CMD_WARNING
;
11638 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11639 type
= bgp_show_adj_route_advertised
;
11640 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11641 type
= bgp_show_adj_route_received
;
11642 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11643 type
= bgp_show_adj_route_filtered
;
11645 if (argv_find(argv
, argc
, "route-map", &idx
))
11646 rmap_name
= argv
[++idx
]->arg
;
11648 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11651 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11652 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11653 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11659 "Address Family modifier\n"
11660 "Detailed information on TCP and BGP neighbor connections\n"
11661 "Neighbor to display information about\n"
11662 "Neighbor to display information about\n"
11663 "Neighbor on BGP configured interface\n"
11664 "Display information received from a BGP neighbor\n"
11665 "Display the prefixlist filter\n"
11668 afi_t afi
= AFI_IP6
;
11669 safi_t safi
= SAFI_UNICAST
;
11670 char *peerstr
= NULL
;
11673 union sockunion su
;
11679 /* show [ip] bgp */
11680 if (argv_find(argv
, argc
, "ip", &idx
))
11682 /* [<ipv4|ipv6> [unicast]] */
11683 if (argv_find(argv
, argc
, "ipv4", &idx
))
11685 if (argv_find(argv
, argc
, "ipv6", &idx
))
11687 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11688 argv_find(argv
, argc
, "neighbors", &idx
);
11689 peerstr
= argv
[++idx
]->arg
;
11691 bool uj
= use_json(argc
, argv
);
11693 ret
= str2sockunion(peerstr
, &su
);
11695 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11698 vty_out(vty
, "{}\n");
11701 "%% Malformed address or name: %s\n",
11703 return CMD_WARNING
;
11706 peer
= peer_lookup(NULL
, &su
);
11709 vty_out(vty
, "{}\n");
11711 vty_out(vty
, "No peer\n");
11712 return CMD_WARNING
;
11716 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11717 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11720 vty_out(vty
, "Address Family: %s\n",
11721 get_afi_safi_str(afi
, safi
, false));
11722 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11725 vty_out(vty
, "{}\n");
11727 vty_out(vty
, "No functional output\n");
11730 return CMD_SUCCESS
;
11733 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11734 afi_t afi
, safi_t safi
,
11735 enum bgp_show_type type
, bool use_json
)
11737 /* labeled-unicast routes live in the unicast table */
11738 if (safi
== SAFI_LABELED_UNICAST
)
11739 safi
= SAFI_UNICAST
;
11741 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11743 json_object
*json_no
= NULL
;
11744 json_no
= json_object_new_object();
11745 json_object_string_add(
11746 json_no
, "warning",
11747 "No such neighbor or address family");
11748 vty_out(vty
, "%s\n",
11749 json_object_to_json_string(json_no
));
11750 json_object_free(json_no
);
11752 vty_out(vty
, "%% No such neighbor or address family\n");
11753 return CMD_WARNING
;
11756 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11759 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11760 show_ip_bgp_flowspec_routes_detailed_cmd
,
11761 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11765 BGP_INSTANCE_HELP_STR
11768 "Detailed information on flowspec entries\n"
11771 afi_t afi
= AFI_IP
;
11772 safi_t safi
= SAFI_UNICAST
;
11773 struct bgp
*bgp
= NULL
;
11775 bool uj
= use_json(argc
, argv
);
11780 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11783 return CMD_WARNING
;
11785 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11788 DEFUN (show_ip_bgp_neighbor_routes
,
11789 show_ip_bgp_neighbor_routes_cmd
,
11790 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11791 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11795 BGP_INSTANCE_HELP_STR
11797 BGP_SAFI_WITH_LABEL_HELP_STR
11798 "Detailed information on TCP and BGP neighbor connections\n"
11799 "Neighbor to display information about\n"
11800 "Neighbor to display information about\n"
11801 "Neighbor on BGP configured interface\n"
11802 "Display flap statistics of the routes learned from neighbor\n"
11803 "Display the dampened routes received from neighbor\n"
11804 "Display routes learned from neighbor\n"
11807 char *peerstr
= NULL
;
11808 struct bgp
*bgp
= NULL
;
11809 afi_t afi
= AFI_IP6
;
11810 safi_t safi
= SAFI_UNICAST
;
11812 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11814 bool uj
= use_json(argc
, argv
);
11819 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11822 return CMD_WARNING
;
11824 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11825 argv_find(argv
, argc
, "neighbors", &idx
);
11826 peerstr
= argv
[++idx
]->arg
;
11828 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11830 return CMD_WARNING
;
11832 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11833 sh_type
= bgp_show_type_flap_neighbor
;
11834 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11835 sh_type
= bgp_show_type_damp_neighbor
;
11836 else if (argv_find(argv
, argc
, "routes", &idx
))
11837 sh_type
= bgp_show_type_neighbor
;
11839 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11842 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11844 struct bgp_distance
{
11845 /* Distance value for the IP source prefix. */
11848 /* Name of the access-list to be matched. */
11852 DEFUN (show_bgp_afi_vpn_rd_route
,
11853 show_bgp_afi_vpn_rd_route_cmd
,
11854 "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]",
11858 "Address Family modifier\n"
11859 "Display information for a route distinguisher\n"
11860 "Route Distinguisher\n"
11861 "Network in the BGP routing table to display\n"
11862 "Network in the BGP routing table to display\n"
11866 struct prefix_rd prd
;
11867 afi_t afi
= AFI_MAX
;
11870 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11871 vty_out(vty
, "%% Malformed Address Family\n");
11872 return CMD_WARNING
;
11875 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11877 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11878 return CMD_WARNING
;
11881 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11882 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11885 static struct bgp_distance
*bgp_distance_new(void)
11887 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11890 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11892 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11895 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11896 const char *ip_str
, const char *access_list_str
)
11903 struct bgp_node
*rn
;
11904 struct bgp_distance
*bdistance
;
11906 afi
= bgp_node_afi(vty
);
11907 safi
= bgp_node_safi(vty
);
11909 ret
= str2prefix(ip_str
, &p
);
11911 vty_out(vty
, "Malformed prefix\n");
11912 return CMD_WARNING_CONFIG_FAILED
;
11915 distance
= atoi(distance_str
);
11917 /* Get BGP distance node. */
11918 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11919 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11921 bgp_unlock_node(rn
);
11923 bdistance
= bgp_distance_new();
11924 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11927 /* Set distance value. */
11928 bdistance
->distance
= distance
;
11930 /* Reset access-list configuration. */
11931 if (bdistance
->access_list
) {
11932 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11933 bdistance
->access_list
= NULL
;
11935 if (access_list_str
)
11936 bdistance
->access_list
=
11937 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11939 return CMD_SUCCESS
;
11942 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11943 const char *ip_str
, const char *access_list_str
)
11950 struct bgp_node
*rn
;
11951 struct bgp_distance
*bdistance
;
11953 afi
= bgp_node_afi(vty
);
11954 safi
= bgp_node_safi(vty
);
11956 ret
= str2prefix(ip_str
, &p
);
11958 vty_out(vty
, "Malformed prefix\n");
11959 return CMD_WARNING_CONFIG_FAILED
;
11962 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11963 (struct prefix
*)&p
);
11965 vty_out(vty
, "Can't find specified prefix\n");
11966 return CMD_WARNING_CONFIG_FAILED
;
11969 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11970 distance
= atoi(distance_str
);
11972 if (bdistance
->distance
!= distance
) {
11973 vty_out(vty
, "Distance does not match configured\n");
11974 return CMD_WARNING_CONFIG_FAILED
;
11977 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11978 bgp_distance_free(bdistance
);
11980 bgp_node_set_bgp_path_info(rn
, NULL
);
11981 bgp_unlock_node(rn
);
11982 bgp_unlock_node(rn
);
11984 return CMD_SUCCESS
;
11987 /* Apply BGP information to distance method. */
11988 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11989 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11991 struct bgp_node
*rn
;
11994 struct bgp_distance
*bdistance
;
11995 struct access_list
*alist
;
11996 struct bgp_static
*bgp_static
;
12001 peer
= pinfo
->peer
;
12003 if (pinfo
->attr
->distance
)
12004 return pinfo
->attr
->distance
;
12006 /* Check source address. */
12007 sockunion2hostprefix(&peer
->su
, &q
);
12008 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
12010 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12011 bgp_unlock_node(rn
);
12013 if (bdistance
->access_list
) {
12014 alist
= access_list_lookup(afi
, bdistance
->access_list
);
12016 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
12017 return bdistance
->distance
;
12019 return bdistance
->distance
;
12022 /* Backdoor check. */
12023 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
12025 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12026 bgp_unlock_node(rn
);
12028 if (bgp_static
->backdoor
) {
12029 if (bgp
->distance_local
[afi
][safi
])
12030 return bgp
->distance_local
[afi
][safi
];
12032 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12036 if (peer
->sort
== BGP_PEER_EBGP
) {
12037 if (bgp
->distance_ebgp
[afi
][safi
])
12038 return bgp
->distance_ebgp
[afi
][safi
];
12039 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
12041 if (bgp
->distance_ibgp
[afi
][safi
])
12042 return bgp
->distance_ibgp
[afi
][safi
];
12043 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12047 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12048 * we should tell ZEBRA update the routes for a specific
12049 * AFI/SAFI to reflect changes in RIB.
12051 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
12053 safi_t update_safi
)
12058 FOREACH_AFI_SAFI (afi
, safi
) {
12059 if (!bgp_fibupd_safi(safi
))
12062 if (afi
!= update_afi
&& safi
!= update_safi
)
12065 if (BGP_DEBUG(zebra
, ZEBRA
))
12067 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12068 __func__
, afi
, safi
);
12069 bgp_zebra_announce_table(bgp
, afi
, safi
);
12073 DEFUN (bgp_distance
,
12075 "distance bgp (1-255) (1-255) (1-255)",
12076 "Define an administrative distance\n"
12078 "Distance for routes external to the AS\n"
12079 "Distance for routes internal to the AS\n"
12080 "Distance for local routes\n")
12082 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12083 int idx_number
= 2;
12084 int idx_number_2
= 3;
12085 int idx_number_3
= 4;
12086 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
12087 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
12088 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
12092 afi
= bgp_node_afi(vty
);
12093 safi
= bgp_node_safi(vty
);
12095 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
12096 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
12097 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
12098 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
12099 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
12100 bgp
->distance_local
[afi
][safi
] = distance_local
;
12101 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12103 return CMD_SUCCESS
;
12106 DEFUN (no_bgp_distance
,
12107 no_bgp_distance_cmd
,
12108 "no distance bgp [(1-255) (1-255) (1-255)]",
12110 "Define an administrative distance\n"
12112 "Distance for routes external to the AS\n"
12113 "Distance for routes internal to the AS\n"
12114 "Distance for local routes\n")
12116 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12120 afi
= bgp_node_afi(vty
);
12121 safi
= bgp_node_safi(vty
);
12123 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12124 || bgp
->distance_ibgp
[afi
][safi
] != 0
12125 || bgp
->distance_local
[afi
][safi
] != 0) {
12126 bgp
->distance_ebgp
[afi
][safi
] = 0;
12127 bgp
->distance_ibgp
[afi
][safi
] = 0;
12128 bgp
->distance_local
[afi
][safi
] = 0;
12129 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12131 return CMD_SUCCESS
;
12135 DEFUN (bgp_distance_source
,
12136 bgp_distance_source_cmd
,
12137 "distance (1-255) A.B.C.D/M",
12138 "Define an administrative distance\n"
12139 "Administrative distance\n"
12140 "IP source prefix\n")
12142 int idx_number
= 1;
12143 int idx_ipv4_prefixlen
= 2;
12144 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12145 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12146 return CMD_SUCCESS
;
12149 DEFUN (no_bgp_distance_source
,
12150 no_bgp_distance_source_cmd
,
12151 "no distance (1-255) A.B.C.D/M",
12153 "Define an administrative distance\n"
12154 "Administrative distance\n"
12155 "IP source prefix\n")
12157 int idx_number
= 2;
12158 int idx_ipv4_prefixlen
= 3;
12159 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12160 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12161 return CMD_SUCCESS
;
12164 DEFUN (bgp_distance_source_access_list
,
12165 bgp_distance_source_access_list_cmd
,
12166 "distance (1-255) A.B.C.D/M WORD",
12167 "Define an administrative distance\n"
12168 "Administrative distance\n"
12169 "IP source prefix\n"
12170 "Access list name\n")
12172 int idx_number
= 1;
12173 int idx_ipv4_prefixlen
= 2;
12175 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12176 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12177 return CMD_SUCCESS
;
12180 DEFUN (no_bgp_distance_source_access_list
,
12181 no_bgp_distance_source_access_list_cmd
,
12182 "no distance (1-255) A.B.C.D/M WORD",
12184 "Define an administrative distance\n"
12185 "Administrative distance\n"
12186 "IP source prefix\n"
12187 "Access list name\n")
12189 int idx_number
= 2;
12190 int idx_ipv4_prefixlen
= 3;
12192 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12193 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12194 return CMD_SUCCESS
;
12197 DEFUN (ipv6_bgp_distance_source
,
12198 ipv6_bgp_distance_source_cmd
,
12199 "distance (1-255) X:X::X:X/M",
12200 "Define an administrative distance\n"
12201 "Administrative distance\n"
12202 "IP source prefix\n")
12204 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12205 return CMD_SUCCESS
;
12208 DEFUN (no_ipv6_bgp_distance_source
,
12209 no_ipv6_bgp_distance_source_cmd
,
12210 "no distance (1-255) X:X::X:X/M",
12212 "Define an administrative distance\n"
12213 "Administrative distance\n"
12214 "IP source prefix\n")
12216 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12217 return CMD_SUCCESS
;
12220 DEFUN (ipv6_bgp_distance_source_access_list
,
12221 ipv6_bgp_distance_source_access_list_cmd
,
12222 "distance (1-255) X:X::X:X/M WORD",
12223 "Define an administrative distance\n"
12224 "Administrative distance\n"
12225 "IP source prefix\n"
12226 "Access list name\n")
12228 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12229 return CMD_SUCCESS
;
12232 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12233 no_ipv6_bgp_distance_source_access_list_cmd
,
12234 "no distance (1-255) X:X::X:X/M WORD",
12236 "Define an administrative distance\n"
12237 "Administrative distance\n"
12238 "IP source prefix\n"
12239 "Access list name\n")
12241 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12242 return CMD_SUCCESS
;
12245 DEFUN (bgp_damp_set
,
12247 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12248 "BGP Specific commands\n"
12249 "Enable route-flap dampening\n"
12250 "Half-life time for the penalty\n"
12251 "Value to start reusing a route\n"
12252 "Value to start suppressing a route\n"
12253 "Maximum duration to suppress a stable route\n")
12255 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12256 int idx_half_life
= 2;
12258 int idx_suppress
= 4;
12259 int idx_max_suppress
= 5;
12260 int half
= DEFAULT_HALF_LIFE
* 60;
12261 int reuse
= DEFAULT_REUSE
;
12262 int suppress
= DEFAULT_SUPPRESS
;
12263 int max
= 4 * half
;
12266 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12267 reuse
= atoi(argv
[idx_reuse
]->arg
);
12268 suppress
= atoi(argv
[idx_suppress
]->arg
);
12269 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12270 } else if (argc
== 3) {
12271 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12276 * These can't be 0 but our SA doesn't understand the
12277 * way our cli is constructed
12281 if (suppress
< reuse
) {
12283 "Suppress value cannot be less than reuse value \n");
12287 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12288 reuse
, suppress
, max
);
12291 DEFUN (bgp_damp_unset
,
12292 bgp_damp_unset_cmd
,
12293 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12295 "BGP Specific commands\n"
12296 "Enable route-flap dampening\n"
12297 "Half-life time for the penalty\n"
12298 "Value to start reusing a route\n"
12299 "Value to start suppressing a route\n"
12300 "Maximum duration to suppress a stable route\n")
12302 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12303 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12306 /* Display specified route of BGP table. */
12307 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12308 const char *ip_str
, afi_t afi
, safi_t safi
,
12309 struct prefix_rd
*prd
, int prefix_check
)
12312 struct prefix match
;
12313 struct bgp_node
*rn
;
12314 struct bgp_node
*rm
;
12315 struct bgp_path_info
*pi
;
12316 struct bgp_path_info
*pi_temp
;
12318 struct bgp_table
*table
;
12320 /* BGP structure lookup. */
12322 bgp
= bgp_lookup_by_name(view_name
);
12324 vty_out(vty
, "%% Can't find BGP instance %s\n",
12326 return CMD_WARNING
;
12329 bgp
= bgp_get_default();
12331 vty_out(vty
, "%% No BGP process is configured\n");
12332 return CMD_WARNING
;
12336 /* Check IP address argument. */
12337 ret
= str2prefix(ip_str
, &match
);
12339 vty_out(vty
, "%% address is malformed\n");
12340 return CMD_WARNING
;
12343 match
.family
= afi2family(afi
);
12345 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12346 || (safi
== SAFI_EVPN
)) {
12347 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12348 rn
= bgp_route_next(rn
)) {
12349 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12351 table
= bgp_node_get_bgp_table_info(rn
);
12354 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12358 || rm
->p
.prefixlen
== match
.prefixlen
) {
12359 pi
= bgp_node_get_bgp_path_info(rm
);
12361 if (pi
->extra
&& pi
->extra
->damp_info
) {
12362 pi_temp
= pi
->next
;
12363 bgp_damp_info_free(
12364 pi
->extra
->damp_info
,
12372 bgp_unlock_node(rm
);
12375 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12378 || rn
->p
.prefixlen
== match
.prefixlen
) {
12379 pi
= bgp_node_get_bgp_path_info(rn
);
12381 if (pi
->extra
&& pi
->extra
->damp_info
) {
12382 pi_temp
= pi
->next
;
12383 bgp_damp_info_free(
12384 pi
->extra
->damp_info
,
12392 bgp_unlock_node(rn
);
12396 return CMD_SUCCESS
;
12399 DEFUN (clear_ip_bgp_dampening
,
12400 clear_ip_bgp_dampening_cmd
,
12401 "clear ip bgp dampening",
12405 "Clear route flap dampening information\n")
12407 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
12408 return CMD_SUCCESS
;
12411 DEFUN (clear_ip_bgp_dampening_prefix
,
12412 clear_ip_bgp_dampening_prefix_cmd
,
12413 "clear ip bgp dampening A.B.C.D/M",
12417 "Clear route flap dampening information\n"
12420 int idx_ipv4_prefixlen
= 4;
12421 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12422 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12425 DEFUN (clear_ip_bgp_dampening_address
,
12426 clear_ip_bgp_dampening_address_cmd
,
12427 "clear ip bgp dampening A.B.C.D",
12431 "Clear route flap dampening information\n"
12432 "Network to clear damping information\n")
12435 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12436 SAFI_UNICAST
, NULL
, 0);
12439 DEFUN (clear_ip_bgp_dampening_address_mask
,
12440 clear_ip_bgp_dampening_address_mask_cmd
,
12441 "clear ip bgp dampening A.B.C.D A.B.C.D",
12445 "Clear route flap dampening information\n"
12446 "Network to clear damping information\n"
12450 int idx_ipv4_2
= 5;
12452 char prefix_str
[BUFSIZ
];
12454 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12457 vty_out(vty
, "%% Inconsistent address and mask\n");
12458 return CMD_WARNING
;
12461 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12465 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12467 struct vty
*vty
= arg
;
12468 struct peer
*peer
= bucket
->data
;
12469 char buf
[SU_ADDRSTRLEN
];
12471 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12472 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12475 DEFUN (show_bgp_peerhash
,
12476 show_bgp_peerhash_cmd
,
12477 "show bgp peerhash",
12480 "Display information about the BGP peerhash\n")
12482 struct list
*instances
= bm
->bgp
;
12483 struct listnode
*node
;
12486 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12487 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12488 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12492 return CMD_SUCCESS
;
12495 /* also used for encap safi */
12496 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12497 afi_t afi
, safi_t safi
)
12499 struct bgp_node
*prn
;
12500 struct bgp_node
*rn
;
12501 struct bgp_table
*table
;
12503 struct prefix_rd
*prd
;
12504 struct bgp_static
*bgp_static
;
12505 mpls_label_t label
;
12506 char buf
[SU_ADDRSTRLEN
];
12507 char rdbuf
[RD_ADDRSTRLEN
];
12509 /* Network configuration. */
12510 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12511 prn
= bgp_route_next(prn
)) {
12512 table
= bgp_node_get_bgp_table_info(prn
);
12516 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12517 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12518 if (bgp_static
== NULL
)
12522 prd
= (struct prefix_rd
*)&prn
->p
;
12524 /* "network" configuration display. */
12525 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12526 label
= decode_label(&bgp_static
->label
);
12528 vty_out(vty
, " network %s/%d rd %s",
12529 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12531 p
->prefixlen
, rdbuf
);
12532 if (safi
== SAFI_MPLS_VPN
)
12533 vty_out(vty
, " label %u", label
);
12535 if (bgp_static
->rmap
.name
)
12536 vty_out(vty
, " route-map %s",
12537 bgp_static
->rmap
.name
);
12539 if (bgp_static
->backdoor
)
12540 vty_out(vty
, " backdoor");
12542 vty_out(vty
, "\n");
12547 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12548 afi_t afi
, safi_t safi
)
12550 struct bgp_node
*prn
;
12551 struct bgp_node
*rn
;
12552 struct bgp_table
*table
;
12554 struct prefix_rd
*prd
;
12555 struct bgp_static
*bgp_static
;
12556 char buf
[PREFIX_STRLEN
* 2];
12557 char buf2
[SU_ADDRSTRLEN
];
12558 char rdbuf
[RD_ADDRSTRLEN
];
12560 /* Network configuration. */
12561 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12562 prn
= bgp_route_next(prn
)) {
12563 table
= bgp_node_get_bgp_table_info(prn
);
12567 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12568 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12569 if (bgp_static
== NULL
)
12572 char *macrouter
= NULL
;
12575 if (bgp_static
->router_mac
)
12576 macrouter
= prefix_mac2str(
12577 bgp_static
->router_mac
, NULL
, 0);
12578 if (bgp_static
->eth_s_id
)
12579 esi
= esi2str(bgp_static
->eth_s_id
);
12581 prd
= (struct prefix_rd
*)&prn
->p
;
12583 /* "network" configuration display. */
12584 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12585 if (p
->u
.prefix_evpn
.route_type
== 5) {
12586 char local_buf
[PREFIX_STRLEN
];
12587 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12588 struct prefix_evpn
*)p
)
12592 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12593 local_buf
, PREFIX_STRLEN
);
12594 sprintf(buf
, "%s/%u", local_buf
,
12595 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12597 prefix2str(p
, buf
, sizeof(buf
));
12600 if (bgp_static
->gatewayIp
.family
== AF_INET
12601 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12602 inet_ntop(bgp_static
->gatewayIp
.family
,
12603 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12606 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12608 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12609 decode_label(&bgp_static
->label
), esi
, buf2
,
12612 XFREE(MTYPE_TMP
, macrouter
);
12613 XFREE(MTYPE_TMP
, esi
);
12618 /* Configuration of static route announcement and aggregate
12620 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12623 struct bgp_node
*rn
;
12625 struct bgp_static
*bgp_static
;
12626 struct bgp_aggregate
*bgp_aggregate
;
12627 char buf
[SU_ADDRSTRLEN
];
12629 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12630 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12634 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12635 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12639 /* Network configuration. */
12640 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12641 rn
= bgp_route_next(rn
)) {
12642 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12643 if (bgp_static
== NULL
)
12648 vty_out(vty
, " network %s/%d",
12649 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12652 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12653 vty_out(vty
, " label-index %u",
12654 bgp_static
->label_index
);
12656 if (bgp_static
->rmap
.name
)
12657 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12659 if (bgp_static
->backdoor
)
12660 vty_out(vty
, " backdoor");
12662 vty_out(vty
, "\n");
12665 /* Aggregate-address configuration. */
12666 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12667 rn
= bgp_route_next(rn
)) {
12668 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12669 if (bgp_aggregate
== NULL
)
12674 vty_out(vty
, " aggregate-address %s/%d",
12675 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12678 if (bgp_aggregate
->as_set
)
12679 vty_out(vty
, " as-set");
12681 if (bgp_aggregate
->summary_only
)
12682 vty_out(vty
, " summary-only");
12684 if (bgp_aggregate
->rmap
.name
)
12685 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12687 vty_out(vty
, "\n");
12691 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12694 struct bgp_node
*rn
;
12695 struct bgp_distance
*bdistance
;
12697 /* Distance configuration. */
12698 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12699 && bgp
->distance_local
[afi
][safi
]
12700 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12701 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12702 || bgp
->distance_local
[afi
][safi
]
12703 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12704 vty_out(vty
, " distance bgp %d %d %d\n",
12705 bgp
->distance_ebgp
[afi
][safi
],
12706 bgp
->distance_ibgp
[afi
][safi
],
12707 bgp
->distance_local
[afi
][safi
]);
12710 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12711 rn
= bgp_route_next(rn
)) {
12712 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12713 if (bdistance
!= NULL
) {
12714 char buf
[PREFIX_STRLEN
];
12716 vty_out(vty
, " distance %d %s %s\n",
12717 bdistance
->distance
,
12718 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12719 bdistance
->access_list
? bdistance
->access_list
12725 /* Allocate routing table structure and install commands. */
12726 void bgp_route_init(void)
12731 /* Init BGP distance table. */
12732 FOREACH_AFI_SAFI (afi
, safi
)
12733 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12735 /* IPv4 BGP commands. */
12736 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12737 install_element(BGP_NODE
, &bgp_network_cmd
);
12738 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12740 install_element(BGP_NODE
, &aggregate_address_cmd
);
12741 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12742 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12743 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12745 /* IPv4 unicast configuration. */
12746 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12747 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12748 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12750 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12751 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12752 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12753 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12755 /* IPv4 multicast configuration. */
12756 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12757 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12758 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12759 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12760 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12761 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12762 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12764 /* IPv4 labeled-unicast configuration. */
12765 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12766 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12767 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12768 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12769 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12771 install_element(VIEW_NODE
,
12772 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12773 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12774 install_element(VIEW_NODE
,
12775 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12776 #ifdef KEEP_OLD_VPN_COMMANDS
12777 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12778 #endif /* KEEP_OLD_VPN_COMMANDS */
12779 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12780 install_element(VIEW_NODE
,
12781 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
12783 /* BGP dampening clear commands */
12784 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12785 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12787 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12788 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12791 install_element(ENABLE_NODE
,
12792 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12793 #ifdef KEEP_OLD_VPN_COMMANDS
12794 install_element(ENABLE_NODE
,
12795 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12796 #endif /* KEEP_OLD_VPN_COMMANDS */
12798 /* New config IPv6 BGP commands. */
12799 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12800 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12801 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12803 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12804 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12806 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12808 install_element(BGP_NODE
, &bgp_distance_cmd
);
12809 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12810 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12811 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12812 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12813 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12814 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12815 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12816 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12817 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12818 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12819 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12820 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12821 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12822 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12823 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12824 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12825 install_element(BGP_IPV4M_NODE
,
12826 &no_bgp_distance_source_access_list_cmd
);
12827 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12828 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12829 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12830 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12831 install_element(BGP_IPV6_NODE
,
12832 &ipv6_bgp_distance_source_access_list_cmd
);
12833 install_element(BGP_IPV6_NODE
,
12834 &no_ipv6_bgp_distance_source_access_list_cmd
);
12835 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12836 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12837 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12838 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12839 install_element(BGP_IPV6M_NODE
,
12840 &ipv6_bgp_distance_source_access_list_cmd
);
12841 install_element(BGP_IPV6M_NODE
,
12842 &no_ipv6_bgp_distance_source_access_list_cmd
);
12844 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12845 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12846 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12847 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12849 /* IPv4 Multicast Mode */
12850 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12851 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12853 /* Large Communities */
12854 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12855 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12857 /* show bgp ipv4 flowspec detailed */
12858 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12860 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12863 void bgp_route_finish(void)
12868 FOREACH_AFI_SAFI (afi
, safi
) {
12869 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12870 bgp_distance_table
[afi
][safi
] = NULL
;