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_IBGP
)
4363 if (peer
->sort
== BGP_PEER_EBGP
4364 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4365 || FILTER_LIST_OUT_NAME(filter
)
4366 || DISTRIBUTE_OUT_NAME(filter
)))
4371 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4373 if (peer
->sort
== BGP_PEER_IBGP
)
4376 if (peer
->sort
== BGP_PEER_EBGP
4377 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4378 || FILTER_LIST_IN_NAME(filter
)
4379 || DISTRIBUTE_IN_NAME(filter
)))
4384 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4387 struct bgp_node
*rn
;
4388 struct bgp_path_info
*pi
;
4389 struct bgp_path_info
*next
;
4391 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4392 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4395 /* Unimport EVPN routes from VRFs */
4396 if (safi
== SAFI_EVPN
)
4397 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4401 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4402 && pi
->type
== ZEBRA_ROUTE_BGP
4403 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4404 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4405 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4407 if (bgp_fibupd_safi(safi
))
4408 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4410 bgp_path_info_reap(rn
, pi
);
4415 /* Delete all kernel routes. */
4416 void bgp_cleanup_routes(struct bgp
*bgp
)
4419 struct bgp_node
*rn
;
4420 struct bgp_table
*table
;
4422 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4423 if (afi
== AFI_L2VPN
)
4425 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4428 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4430 if (afi
!= AFI_L2VPN
) {
4432 safi
= SAFI_MPLS_VPN
;
4433 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4434 rn
= bgp_route_next(rn
)) {
4435 table
= bgp_node_get_bgp_table_info(rn
);
4436 if (table
!= NULL
) {
4437 bgp_cleanup_table(bgp
, table
, safi
);
4438 bgp_table_finish(&table
);
4439 bgp_node_set_bgp_table_info(rn
, NULL
);
4440 bgp_unlock_node(rn
);
4444 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4445 rn
= bgp_route_next(rn
)) {
4446 table
= bgp_node_get_bgp_table_info(rn
);
4447 if (table
!= NULL
) {
4448 bgp_cleanup_table(bgp
, table
, safi
);
4449 bgp_table_finish(&table
);
4450 bgp_node_set_bgp_table_info(rn
, NULL
);
4451 bgp_unlock_node(rn
);
4456 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4457 rn
= bgp_route_next(rn
)) {
4458 table
= bgp_node_get_bgp_table_info(rn
);
4459 if (table
!= NULL
) {
4460 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4461 bgp_table_finish(&table
);
4462 bgp_node_set_bgp_table_info(rn
, NULL
);
4463 bgp_unlock_node(rn
);
4468 void bgp_reset(void)
4471 bgp_zclient_reset();
4472 access_list_reset();
4473 prefix_list_reset();
4476 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4478 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4479 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4480 PEER_CAP_ADDPATH_AF_TX_RCV
));
4483 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4485 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4486 struct bgp_nlri
*packet
)
4495 int addpath_encoded
;
4496 uint32_t addpath_id
;
4499 lim
= pnt
+ packet
->length
;
4501 safi
= packet
->safi
;
4503 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4505 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4506 syntactic validity. If the field is syntactically incorrect,
4507 then the Error Subcode is set to Invalid Network Field. */
4508 for (; pnt
< lim
; pnt
+= psize
) {
4509 /* Clear prefix structure. */
4510 memset(&p
, 0, sizeof(struct prefix
));
4512 if (addpath_encoded
) {
4514 /* When packet overflow occurs return immediately. */
4515 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4516 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4518 addpath_id
= ntohl(*((uint32_t *)pnt
));
4519 pnt
+= BGP_ADDPATH_ID_LEN
;
4522 /* Fetch prefix length. */
4523 p
.prefixlen
= *pnt
++;
4524 /* afi/safi validity already verified by caller,
4525 * bgp_update_receive */
4526 p
.family
= afi2family(afi
);
4528 /* Prefix length check. */
4529 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4532 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4533 peer
->host
, p
.prefixlen
, packet
->afi
);
4534 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4537 /* Packet size overflow check. */
4538 psize
= PSIZE(p
.prefixlen
);
4540 /* When packet overflow occur return immediately. */
4541 if (pnt
+ psize
> lim
) {
4544 "%s [Error] Update packet error (prefix length %d overflows packet)",
4545 peer
->host
, p
.prefixlen
);
4546 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4549 /* Defensive coding, double-check the psize fits in a struct
4551 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4554 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4555 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4556 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4559 /* Fetch prefix from NLRI packet. */
4560 memcpy(p
.u
.val
, pnt
, psize
);
4562 /* Check address. */
4563 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4564 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4565 /* From RFC4271 Section 6.3:
4567 * If a prefix in the NLRI field is semantically
4569 * (e.g., an unexpected multicast IP address),
4571 * be logged locally, and the prefix SHOULD be
4576 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4577 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4582 /* Check address. */
4583 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4584 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4589 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4591 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4596 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4601 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4603 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4610 /* Normal process. */
4612 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4613 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4614 NULL
, NULL
, 0, 0, NULL
);
4616 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4617 safi
, ZEBRA_ROUTE_BGP
,
4618 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4621 /* Do not send BGP notification twice when maximum-prefix count
4623 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4624 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4626 /* Address family configuration mismatch. */
4628 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4631 /* Packet length consistency check. */
4635 "%s [Error] Update packet error (prefix length mismatch with total length)",
4637 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4640 return BGP_NLRI_PARSE_OK
;
4643 static struct bgp_static
*bgp_static_new(void)
4645 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4648 static void bgp_static_free(struct bgp_static
*bgp_static
)
4650 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4651 route_map_counter_decrement(bgp_static
->rmap
.map
);
4653 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4654 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4657 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4658 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4660 struct bgp_node
*rn
;
4661 struct bgp_path_info
*pi
;
4662 struct bgp_path_info
*new;
4663 struct bgp_path_info rmap_path
;
4665 struct attr
*attr_new
;
4666 route_map_result_t ret
;
4668 int vnc_implicit_withdraw
= 0;
4675 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4677 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4679 attr
.nexthop
= bgp_static
->igpnexthop
;
4680 attr
.med
= bgp_static
->igpmetric
;
4681 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4683 if (bgp_static
->atomic
)
4684 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4686 /* Store label index, if required. */
4687 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4688 attr
.label_index
= bgp_static
->label_index
;
4689 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4692 /* Apply route-map. */
4693 if (bgp_static
->rmap
.name
) {
4694 struct attr attr_tmp
= attr
;
4696 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4697 rmap_path
.peer
= bgp
->peer_self
;
4698 rmap_path
.attr
= &attr_tmp
;
4700 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4702 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4705 bgp
->peer_self
->rmap_type
= 0;
4707 if (ret
== RMAP_DENYMATCH
) {
4708 /* Free uninterned attribute. */
4709 bgp_attr_flush(&attr_tmp
);
4711 /* Unintern original. */
4712 aspath_unintern(&attr
.aspath
);
4713 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4717 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4718 bgp_attr_add_gshut_community(&attr_tmp
);
4720 attr_new
= bgp_attr_intern(&attr_tmp
);
4723 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4724 bgp_attr_add_gshut_community(&attr
);
4726 attr_new
= bgp_attr_intern(&attr
);
4729 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4730 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4731 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4735 if (attrhash_cmp(pi
->attr
, attr_new
)
4736 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4737 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4738 bgp_unlock_node(rn
);
4739 bgp_attr_unintern(&attr_new
);
4740 aspath_unintern(&attr
.aspath
);
4743 /* The attribute is changed. */
4744 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4746 /* Rewrite BGP route information. */
4747 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4748 bgp_path_info_restore(rn
, pi
);
4750 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4752 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4753 && (safi
== SAFI_UNICAST
)) {
4754 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4756 * Implicit withdraw case.
4757 * We have to do this before pi is
4760 ++vnc_implicit_withdraw
;
4761 vnc_import_bgp_del_route(bgp
, p
, pi
);
4762 vnc_import_bgp_exterior_del_route(
4767 bgp_attr_unintern(&pi
->attr
);
4768 pi
->attr
= attr_new
;
4769 pi
->uptime
= bgp_clock();
4771 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4772 && (safi
== SAFI_UNICAST
)) {
4773 if (vnc_implicit_withdraw
) {
4774 vnc_import_bgp_add_route(bgp
, p
, pi
);
4775 vnc_import_bgp_exterior_add_route(
4781 /* Nexthop reachability check. */
4782 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4783 && (safi
== SAFI_UNICAST
4784 || safi
== SAFI_LABELED_UNICAST
)) {
4786 struct bgp
*bgp_nexthop
= bgp
;
4788 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4789 bgp_nexthop
= pi
->extra
->bgp_orig
;
4791 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4793 bgp_path_info_set_flag(rn
, pi
,
4796 if (BGP_DEBUG(nht
, NHT
)) {
4797 char buf1
[INET6_ADDRSTRLEN
];
4798 inet_ntop(p
->family
,
4802 "%s(%s): Route not in table, not advertising",
4803 __FUNCTION__
, buf1
);
4805 bgp_path_info_unset_flag(
4806 rn
, pi
, BGP_PATH_VALID
);
4809 /* Delete the NHT structure if any, if we're
4811 * enabling/disabling import check. We
4812 * deregister the route
4813 * from NHT to avoid overloading NHT and the
4814 * process interaction
4816 bgp_unlink_nexthop(pi
);
4817 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4819 /* Process change. */
4820 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4821 bgp_process(bgp
, rn
, afi
, safi
);
4823 if (SAFI_UNICAST
== safi
4824 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4826 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4827 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4831 bgp_unlock_node(rn
);
4832 aspath_unintern(&attr
.aspath
);
4837 /* Make new BGP info. */
4838 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4840 /* Nexthop reachability check. */
4841 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4842 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4843 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4844 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4846 if (BGP_DEBUG(nht
, NHT
)) {
4847 char buf1
[INET6_ADDRSTRLEN
];
4848 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4851 "%s(%s): Route not in table, not advertising",
4852 __FUNCTION__
, buf1
);
4854 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4857 /* Delete the NHT structure if any, if we're toggling between
4858 * enabling/disabling import check. We deregister the route
4859 * from NHT to avoid overloading NHT and the process interaction
4861 bgp_unlink_nexthop(new);
4863 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4866 /* Aggregate address increment. */
4867 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4869 /* Register new BGP information. */
4870 bgp_path_info_add(rn
, new);
4872 /* route_node_get lock */
4873 bgp_unlock_node(rn
);
4875 /* Process change. */
4876 bgp_process(bgp
, rn
, afi
, safi
);
4878 if (SAFI_UNICAST
== safi
4879 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4880 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4881 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4884 /* Unintern original. */
4885 aspath_unintern(&attr
.aspath
);
4888 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4891 struct bgp_node
*rn
;
4892 struct bgp_path_info
*pi
;
4894 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4896 /* Check selected route and self inserted route. */
4897 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4898 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4899 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4902 /* Withdraw static BGP route from routing table. */
4904 if (SAFI_UNICAST
== safi
4905 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4906 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4907 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4909 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4910 bgp_unlink_nexthop(pi
);
4911 bgp_path_info_delete(rn
, pi
);
4912 bgp_process(bgp
, rn
, afi
, safi
);
4915 /* Unlock bgp_node_lookup. */
4916 bgp_unlock_node(rn
);
4920 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4922 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4923 afi_t afi
, safi_t safi
,
4924 struct prefix_rd
*prd
)
4926 struct bgp_node
*rn
;
4927 struct bgp_path_info
*pi
;
4929 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4931 /* Check selected route and self inserted route. */
4932 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4933 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4934 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4937 /* Withdraw static BGP route from routing table. */
4940 rfapiProcessWithdraw(
4941 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4942 1); /* Kill, since it is an administrative change */
4944 if (SAFI_MPLS_VPN
== safi
4945 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4946 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4948 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4949 bgp_path_info_delete(rn
, pi
);
4950 bgp_process(bgp
, rn
, afi
, safi
);
4953 /* Unlock bgp_node_lookup. */
4954 bgp_unlock_node(rn
);
4957 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4958 struct bgp_static
*bgp_static
, afi_t afi
,
4961 struct bgp_node
*rn
;
4962 struct bgp_path_info
*new;
4963 struct attr
*attr_new
;
4964 struct attr attr
= {0};
4965 struct bgp_path_info
*pi
;
4967 mpls_label_t label
= 0;
4969 uint32_t num_labels
= 0;
4974 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4976 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4979 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4981 attr
.nexthop
= bgp_static
->igpnexthop
;
4982 attr
.med
= bgp_static
->igpmetric
;
4983 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4985 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4986 || (safi
== SAFI_ENCAP
)) {
4987 if (afi
== AFI_IP
) {
4988 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4989 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4992 if (afi
== AFI_L2VPN
) {
4993 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4995 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4996 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4997 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4998 sizeof(struct in6_addr
));
4999 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
5000 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5001 struct bgp_encap_type_vxlan bet
;
5002 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5003 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5004 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5006 if (bgp_static
->router_mac
) {
5007 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5010 /* Apply route-map. */
5011 if (bgp_static
->rmap
.name
) {
5012 struct attr attr_tmp
= attr
;
5013 struct bgp_path_info rmap_path
;
5014 route_map_result_t ret
;
5016 rmap_path
.peer
= bgp
->peer_self
;
5017 rmap_path
.attr
= &attr_tmp
;
5019 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5021 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5024 bgp
->peer_self
->rmap_type
= 0;
5026 if (ret
== RMAP_DENYMATCH
) {
5027 /* Free uninterned attribute. */
5028 bgp_attr_flush(&attr_tmp
);
5030 /* Unintern original. */
5031 aspath_unintern(&attr
.aspath
);
5032 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5037 attr_new
= bgp_attr_intern(&attr_tmp
);
5039 attr_new
= bgp_attr_intern(&attr
);
5042 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5043 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5044 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5048 memset(&add
, 0, sizeof(union gw_addr
));
5049 if (attrhash_cmp(pi
->attr
, attr_new
)
5050 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
5051 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5052 bgp_unlock_node(rn
);
5053 bgp_attr_unintern(&attr_new
);
5054 aspath_unintern(&attr
.aspath
);
5057 /* The attribute is changed. */
5058 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5060 /* Rewrite BGP route information. */
5061 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5062 bgp_path_info_restore(rn
, pi
);
5064 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5065 bgp_attr_unintern(&pi
->attr
);
5066 pi
->attr
= attr_new
;
5067 pi
->uptime
= bgp_clock();
5070 label
= decode_label(&pi
->extra
->label
[0]);
5073 /* Process change. */
5074 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5075 bgp_process(bgp
, rn
, afi
, safi
);
5077 if (SAFI_MPLS_VPN
== safi
5078 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5079 vpn_leak_to_vrf_update(bgp
, pi
);
5082 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5083 pi
->attr
, afi
, safi
, pi
->type
,
5084 pi
->sub_type
, &label
);
5086 bgp_unlock_node(rn
);
5087 aspath_unintern(&attr
.aspath
);
5093 /* Make new BGP info. */
5094 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5096 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5097 new->extra
= bgp_path_info_extra_new();
5099 new->extra
->label
[0] = bgp_static
->label
;
5100 new->extra
->num_labels
= num_labels
;
5103 label
= decode_label(&bgp_static
->label
);
5106 /* Aggregate address increment. */
5107 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5109 /* Register new BGP information. */
5110 bgp_path_info_add(rn
, new);
5111 /* route_node_get lock */
5112 bgp_unlock_node(rn
);
5114 /* Process change. */
5115 bgp_process(bgp
, rn
, afi
, safi
);
5117 if (SAFI_MPLS_VPN
== safi
5118 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5119 vpn_leak_to_vrf_update(bgp
, new);
5122 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5123 safi
, new->type
, new->sub_type
, &label
);
5126 /* Unintern original. */
5127 aspath_unintern(&attr
.aspath
);
5130 /* Configure static BGP network. When user don't run zebra, static
5131 route should be installed as valid. */
5132 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5133 const char *ip_str
, afi_t afi
, safi_t safi
,
5134 const char *rmap
, int backdoor
, uint32_t label_index
)
5136 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5139 struct bgp_static
*bgp_static
;
5140 struct bgp_node
*rn
;
5141 uint8_t need_update
= 0;
5143 /* Convert IP prefix string to struct prefix. */
5144 ret
= str2prefix(ip_str
, &p
);
5146 vty_out(vty
, "%% Malformed prefix\n");
5147 return CMD_WARNING_CONFIG_FAILED
;
5149 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5150 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5151 return CMD_WARNING_CONFIG_FAILED
;
5158 /* Set BGP static route configuration. */
5159 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5162 vty_out(vty
, "%% Can't find static route specified\n");
5163 return CMD_WARNING_CONFIG_FAILED
;
5166 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5168 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5169 && (label_index
!= bgp_static
->label_index
)) {
5171 "%% label-index doesn't match static route\n");
5172 return CMD_WARNING_CONFIG_FAILED
;
5175 if ((rmap
&& bgp_static
->rmap
.name
)
5176 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5178 "%% route-map name doesn't match static route\n");
5179 return CMD_WARNING_CONFIG_FAILED
;
5182 /* Update BGP RIB. */
5183 if (!bgp_static
->backdoor
)
5184 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5186 /* Clear configuration. */
5187 bgp_static_free(bgp_static
);
5188 bgp_node_set_bgp_static_info(rn
, NULL
);
5189 bgp_unlock_node(rn
);
5190 bgp_unlock_node(rn
);
5193 /* Set BGP static route configuration. */
5194 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5196 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5198 /* Configuration change. */
5199 /* Label index cannot be changed. */
5200 if (bgp_static
->label_index
!= label_index
) {
5201 vty_out(vty
, "%% cannot change label-index\n");
5202 return CMD_WARNING_CONFIG_FAILED
;
5205 /* Check previous routes are installed into BGP. */
5206 if (bgp_static
->valid
5207 && bgp_static
->backdoor
!= backdoor
)
5210 bgp_static
->backdoor
= backdoor
;
5213 XFREE(MTYPE_ROUTE_MAP_NAME
,
5214 bgp_static
->rmap
.name
);
5215 route_map_counter_decrement(
5216 bgp_static
->rmap
.map
);
5217 bgp_static
->rmap
.name
=
5218 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5219 bgp_static
->rmap
.map
=
5220 route_map_lookup_by_name(rmap
);
5221 route_map_counter_increment(
5222 bgp_static
->rmap
.map
);
5224 XFREE(MTYPE_ROUTE_MAP_NAME
,
5225 bgp_static
->rmap
.name
);
5226 route_map_counter_decrement(
5227 bgp_static
->rmap
.map
);
5228 bgp_static
->rmap
.name
= NULL
;
5229 bgp_static
->rmap
.map
= NULL
;
5230 bgp_static
->valid
= 0;
5232 bgp_unlock_node(rn
);
5234 /* New configuration. */
5235 bgp_static
= bgp_static_new();
5236 bgp_static
->backdoor
= backdoor
;
5237 bgp_static
->valid
= 0;
5238 bgp_static
->igpmetric
= 0;
5239 bgp_static
->igpnexthop
.s_addr
= 0;
5240 bgp_static
->label_index
= label_index
;
5243 XFREE(MTYPE_ROUTE_MAP_NAME
,
5244 bgp_static
->rmap
.name
);
5245 route_map_counter_decrement(
5246 bgp_static
->rmap
.map
);
5247 bgp_static
->rmap
.name
=
5248 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5249 bgp_static
->rmap
.map
=
5250 route_map_lookup_by_name(rmap
);
5251 route_map_counter_increment(
5252 bgp_static
->rmap
.map
);
5254 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5257 bgp_static
->valid
= 1;
5259 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5261 if (!bgp_static
->backdoor
)
5262 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5268 void bgp_static_add(struct bgp
*bgp
)
5272 struct bgp_node
*rn
;
5273 struct bgp_node
*rm
;
5274 struct bgp_table
*table
;
5275 struct bgp_static
*bgp_static
;
5277 FOREACH_AFI_SAFI (afi
, safi
)
5278 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5279 rn
= bgp_route_next(rn
)) {
5280 if (!bgp_node_has_bgp_path_info_data(rn
))
5283 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5284 || (safi
== SAFI_EVPN
)) {
5285 table
= bgp_node_get_bgp_table_info(rn
);
5287 for (rm
= bgp_table_top(table
); rm
;
5288 rm
= bgp_route_next(rm
)) {
5290 bgp_node_get_bgp_static_info(
5292 bgp_static_update_safi(bgp
, &rm
->p
,
5299 bgp_node_get_bgp_static_info(rn
), afi
,
5305 /* Called from bgp_delete(). Delete all static routes from the BGP
5307 void bgp_static_delete(struct bgp
*bgp
)
5311 struct bgp_node
*rn
;
5312 struct bgp_node
*rm
;
5313 struct bgp_table
*table
;
5314 struct bgp_static
*bgp_static
;
5316 FOREACH_AFI_SAFI (afi
, safi
)
5317 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5318 rn
= bgp_route_next(rn
)) {
5319 if (!bgp_node_has_bgp_path_info_data(rn
))
5322 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5323 || (safi
== SAFI_EVPN
)) {
5324 table
= bgp_node_get_bgp_table_info(rn
);
5326 for (rm
= bgp_table_top(table
); rm
;
5327 rm
= bgp_route_next(rm
)) {
5329 bgp_node_get_bgp_static_info(
5334 bgp_static_withdraw_safi(
5335 bgp
, &rm
->p
, AFI_IP
, safi
,
5336 (struct prefix_rd
*)&rn
->p
);
5337 bgp_static_free(bgp_static
);
5338 bgp_node_set_bgp_static_info(rn
, NULL
);
5339 bgp_unlock_node(rn
);
5342 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5343 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5344 bgp_static_free(bgp_static
);
5345 bgp_node_set_bgp_static_info(rn
, NULL
);
5346 bgp_unlock_node(rn
);
5351 void bgp_static_redo_import_check(struct bgp
*bgp
)
5355 struct bgp_node
*rn
;
5356 struct bgp_node
*rm
;
5357 struct bgp_table
*table
;
5358 struct bgp_static
*bgp_static
;
5360 /* Use this flag to force reprocessing of the route */
5361 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5362 FOREACH_AFI_SAFI (afi
, safi
) {
5363 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5364 rn
= bgp_route_next(rn
)) {
5365 if (!bgp_node_has_bgp_path_info_data(rn
))
5368 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5369 || (safi
== SAFI_EVPN
)) {
5370 table
= bgp_node_get_bgp_table_info(rn
);
5372 for (rm
= bgp_table_top(table
); rm
;
5373 rm
= bgp_route_next(rm
)) {
5375 bgp_node_get_bgp_static_info(
5377 bgp_static_update_safi(bgp
, &rm
->p
,
5382 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5383 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5388 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5391 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5394 struct bgp_table
*table
;
5395 struct bgp_node
*rn
;
5396 struct bgp_path_info
*pi
;
5398 /* Do not install the aggregate route if BGP is in the
5399 * process of termination.
5401 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5402 (bgp
->peer_self
== NULL
))
5405 table
= bgp
->rib
[afi
][safi
];
5406 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5407 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5408 if (pi
->peer
== bgp
->peer_self
5409 && ((pi
->type
== ZEBRA_ROUTE_BGP
5410 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5411 || (pi
->type
!= ZEBRA_ROUTE_BGP
5413 == BGP_ROUTE_REDISTRIBUTE
))) {
5414 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5416 bgp_unlink_nexthop(pi
);
5417 bgp_path_info_delete(rn
, pi
);
5418 bgp_process(bgp
, rn
, afi
, safi
);
5425 * Purge all networks and redistributed routes from routing table.
5426 * Invoked upon the instance going down.
5428 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5433 FOREACH_AFI_SAFI (afi
, safi
)
5434 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5439 * Currently this is used to set static routes for VPN and ENCAP.
5440 * I think it can probably be factored with bgp_static_set.
5442 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5443 const char *ip_str
, const char *rd_str
,
5444 const char *label_str
, const char *rmap_str
,
5445 int evpn_type
, const char *esi
, const char *gwip
,
5446 const char *ethtag
, const char *routermac
)
5448 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5451 struct prefix_rd prd
;
5452 struct bgp_node
*prn
;
5453 struct bgp_node
*rn
;
5454 struct bgp_table
*table
;
5455 struct bgp_static
*bgp_static
;
5456 mpls_label_t label
= MPLS_INVALID_LABEL
;
5457 struct prefix gw_ip
;
5459 /* validate ip prefix */
5460 ret
= str2prefix(ip_str
, &p
);
5462 vty_out(vty
, "%% Malformed prefix\n");
5463 return CMD_WARNING_CONFIG_FAILED
;
5466 if ((afi
== AFI_L2VPN
)
5467 && (bgp_build_evpn_prefix(evpn_type
,
5468 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5469 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5470 return CMD_WARNING_CONFIG_FAILED
;
5473 ret
= str2prefix_rd(rd_str
, &prd
);
5475 vty_out(vty
, "%% Malformed rd\n");
5476 return CMD_WARNING_CONFIG_FAILED
;
5480 unsigned long label_val
;
5481 label_val
= strtoul(label_str
, NULL
, 10);
5482 encode_label(label_val
, &label
);
5485 if (safi
== SAFI_EVPN
) {
5486 if (esi
&& str2esi(esi
, NULL
) == 0) {
5487 vty_out(vty
, "%% Malformed ESI\n");
5488 return CMD_WARNING_CONFIG_FAILED
;
5490 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5491 vty_out(vty
, "%% Malformed Router MAC\n");
5492 return CMD_WARNING_CONFIG_FAILED
;
5495 memset(&gw_ip
, 0, sizeof(struct prefix
));
5496 ret
= str2prefix(gwip
, &gw_ip
);
5498 vty_out(vty
, "%% Malformed GatewayIp\n");
5499 return CMD_WARNING_CONFIG_FAILED
;
5501 if ((gw_ip
.family
== AF_INET
5502 && is_evpn_prefix_ipaddr_v6(
5503 (struct prefix_evpn
*)&p
))
5504 || (gw_ip
.family
== AF_INET6
5505 && is_evpn_prefix_ipaddr_v4(
5506 (struct prefix_evpn
*)&p
))) {
5508 "%% GatewayIp family differs with IP prefix\n");
5509 return CMD_WARNING_CONFIG_FAILED
;
5513 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5514 if (!bgp_node_has_bgp_path_info_data(prn
))
5515 bgp_node_set_bgp_table_info(prn
,
5516 bgp_table_init(bgp
, afi
, safi
));
5517 table
= bgp_node_get_bgp_table_info(prn
);
5519 rn
= bgp_node_get(table
, &p
);
5521 if (bgp_node_has_bgp_path_info_data(rn
)) {
5522 vty_out(vty
, "%% Same network configuration exists\n");
5523 bgp_unlock_node(rn
);
5525 /* New configuration. */
5526 bgp_static
= bgp_static_new();
5527 bgp_static
->backdoor
= 0;
5528 bgp_static
->valid
= 0;
5529 bgp_static
->igpmetric
= 0;
5530 bgp_static
->igpnexthop
.s_addr
= 0;
5531 bgp_static
->label
= label
;
5532 bgp_static
->prd
= prd
;
5535 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5536 route_map_counter_decrement(bgp_static
->rmap
.map
);
5537 bgp_static
->rmap
.name
=
5538 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5539 bgp_static
->rmap
.map
=
5540 route_map_lookup_by_name(rmap_str
);
5541 route_map_counter_increment(bgp_static
->rmap
.map
);
5544 if (safi
== SAFI_EVPN
) {
5546 bgp_static
->eth_s_id
=
5548 sizeof(struct eth_segment_id
));
5549 str2esi(esi
, bgp_static
->eth_s_id
);
5552 bgp_static
->router_mac
=
5553 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5554 (void)prefix_str2mac(routermac
,
5555 bgp_static
->router_mac
);
5558 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5560 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5562 bgp_static
->valid
= 1;
5563 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5569 /* Configure static BGP network. */
5570 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5571 const char *ip_str
, const char *rd_str
,
5572 const char *label_str
, int evpn_type
, const char *esi
,
5573 const char *gwip
, const char *ethtag
)
5575 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5578 struct prefix_rd prd
;
5579 struct bgp_node
*prn
;
5580 struct bgp_node
*rn
;
5581 struct bgp_table
*table
;
5582 struct bgp_static
*bgp_static
;
5583 mpls_label_t label
= MPLS_INVALID_LABEL
;
5585 /* Convert IP prefix string to struct prefix. */
5586 ret
= str2prefix(ip_str
, &p
);
5588 vty_out(vty
, "%% Malformed prefix\n");
5589 return CMD_WARNING_CONFIG_FAILED
;
5592 if ((afi
== AFI_L2VPN
)
5593 && (bgp_build_evpn_prefix(evpn_type
,
5594 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5595 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5596 return CMD_WARNING_CONFIG_FAILED
;
5598 ret
= str2prefix_rd(rd_str
, &prd
);
5600 vty_out(vty
, "%% Malformed rd\n");
5601 return CMD_WARNING_CONFIG_FAILED
;
5605 unsigned long label_val
;
5606 label_val
= strtoul(label_str
, NULL
, 10);
5607 encode_label(label_val
, &label
);
5610 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5611 if (!bgp_node_has_bgp_path_info_data(prn
))
5612 bgp_node_set_bgp_table_info(prn
,
5613 bgp_table_init(bgp
, afi
, safi
));
5615 bgp_unlock_node(prn
);
5616 table
= bgp_node_get_bgp_table_info(prn
);
5618 rn
= bgp_node_lookup(table
, &p
);
5621 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5623 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5624 bgp_static_free(bgp_static
);
5625 bgp_node_set_bgp_static_info(rn
, NULL
);
5626 bgp_unlock_node(rn
);
5627 bgp_unlock_node(rn
);
5629 vty_out(vty
, "%% Can't find the route\n");
5634 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5635 const char *rmap_name
)
5637 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5638 struct bgp_rmap
*rmap
;
5640 rmap
= &bgp
->table_map
[afi
][safi
];
5642 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5643 route_map_counter_decrement(rmap
->map
);
5644 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5645 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5646 route_map_counter_increment(rmap
->map
);
5648 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5649 route_map_counter_decrement(rmap
->map
);
5654 if (bgp_fibupd_safi(safi
))
5655 bgp_zebra_announce_table(bgp
, afi
, safi
);
5660 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5661 const char *rmap_name
)
5663 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5664 struct bgp_rmap
*rmap
;
5666 rmap
= &bgp
->table_map
[afi
][safi
];
5667 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5668 route_map_counter_decrement(rmap
->map
);
5672 if (bgp_fibupd_safi(safi
))
5673 bgp_zebra_announce_table(bgp
, afi
, safi
);
5678 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5681 if (bgp
->table_map
[afi
][safi
].name
) {
5682 vty_out(vty
, " table-map %s\n",
5683 bgp
->table_map
[afi
][safi
].name
);
5687 DEFUN (bgp_table_map
,
5690 "BGP table to RIB route download filter\n"
5691 "Name of the route map\n")
5694 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5695 argv
[idx_word
]->arg
);
5697 DEFUN (no_bgp_table_map
,
5698 no_bgp_table_map_cmd
,
5699 "no table-map WORD",
5701 "BGP table to RIB route download filter\n"
5702 "Name of the route map\n")
5705 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5706 argv
[idx_word
]->arg
);
5712 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5713 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5714 backdoor$backdoor}]",
5716 "Specify a network to announce via BGP\n"
5721 "Route-map to modify the attributes\n"
5722 "Name of the route map\n"
5723 "Label index to associate with the prefix\n"
5724 "Label index value\n"
5725 "Specify a BGP backdoor route\n")
5727 char addr_prefix_str
[BUFSIZ
];
5732 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5735 vty_out(vty
, "%% Inconsistent address and mask\n");
5736 return CMD_WARNING_CONFIG_FAILED
;
5740 return bgp_static_set(
5741 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5742 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5743 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5746 DEFPY(ipv6_bgp_network
,
5747 ipv6_bgp_network_cmd
,
5748 "[no] network X:X::X:X/M$prefix \
5749 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5751 "Specify a network to announce via BGP\n"
5753 "Route-map to modify the attributes\n"
5754 "Name of the route map\n"
5755 "Label index to associate with the prefix\n"
5756 "Label index value\n")
5758 return bgp_static_set(
5759 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5760 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5763 static struct bgp_aggregate
*bgp_aggregate_new(void)
5765 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5768 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5770 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
5771 route_map_counter_decrement(aggregate
->rmap
.map
);
5772 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5775 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5776 struct aspath
*aspath
,
5777 struct community
*comm
,
5778 struct ecommunity
*ecomm
,
5779 struct lcommunity
*lcomm
)
5781 static struct aspath
*ae
= NULL
;
5784 ae
= aspath_empty();
5789 if (origin
!= pi
->attr
->origin
)
5792 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5795 if (!community_cmp(pi
->attr
->community
, comm
))
5798 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5801 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5804 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5810 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5811 struct prefix
*p
, uint8_t origin
,
5812 struct aspath
*aspath
,
5813 struct community
*community
,
5814 struct ecommunity
*ecommunity
,
5815 struct lcommunity
*lcommunity
,
5816 uint8_t atomic_aggregate
,
5817 struct bgp_aggregate
*aggregate
)
5819 struct bgp_node
*rn
;
5820 struct bgp_table
*table
;
5821 struct bgp_path_info
*pi
, *orig
, *new;
5824 table
= bgp
->rib
[afi
][safi
];
5826 rn
= bgp_node_get(table
, p
);
5828 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5829 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5830 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5833 if (aggregate
->count
> 0) {
5835 * If the aggregate information has not changed
5836 * no need to re-install it again.
5838 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5839 ecommunity
, lcommunity
)) {
5840 bgp_unlock_node(rn
);
5843 aspath_free(aspath
);
5845 community_free(&community
);
5847 ecommunity_free(&ecommunity
);
5849 lcommunity_free(&lcommunity
);
5855 * Mark the old as unusable
5858 bgp_path_info_delete(rn
, pi
);
5860 attr
= bgp_attr_aggregate_intern(
5861 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
5862 aggregate
, atomic_aggregate
, p
);
5865 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
5869 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5870 bgp
->peer_self
, attr
, rn
);
5872 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5874 bgp_path_info_add(rn
, new);
5875 bgp_process(bgp
, rn
, afi
, safi
);
5877 for (pi
= orig
; pi
; pi
= pi
->next
)
5878 if (pi
->peer
== bgp
->peer_self
5879 && pi
->type
== ZEBRA_ROUTE_BGP
5880 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5883 /* Withdraw static BGP route from routing table. */
5885 bgp_path_info_delete(rn
, pi
);
5886 bgp_process(bgp
, rn
, afi
, safi
);
5890 bgp_unlock_node(rn
);
5893 /* Update an aggregate as routes are added/removed from the BGP table */
5894 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5895 afi_t afi
, safi_t safi
,
5896 struct bgp_aggregate
*aggregate
)
5898 struct bgp_table
*table
;
5899 struct bgp_node
*top
;
5900 struct bgp_node
*rn
;
5902 struct aspath
*aspath
= NULL
;
5903 struct community
*community
= NULL
;
5904 struct ecommunity
*ecommunity
= NULL
;
5905 struct lcommunity
*lcommunity
= NULL
;
5906 struct bgp_path_info
*pi
;
5907 unsigned long match
= 0;
5908 uint8_t atomic_aggregate
= 0;
5910 /* If the bgp instance is being deleted or self peer is deleted
5911 * then do not create aggregate route
5913 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5914 (bgp
->peer_self
== NULL
))
5917 /* ORIGIN attribute: If at least one route among routes that are
5918 aggregated has ORIGIN with the value INCOMPLETE, then the
5919 aggregated route must have the ORIGIN attribute with the value
5920 INCOMPLETE. Otherwise, if at least one route among routes that
5921 are aggregated has ORIGIN with the value EGP, then the aggregated
5922 route must have the origin attribute with the value EGP. In all
5923 other case the value of the ORIGIN attribute of the aggregated
5924 route is INTERNAL. */
5925 origin
= BGP_ORIGIN_IGP
;
5927 table
= bgp
->rib
[afi
][safi
];
5929 top
= bgp_node_get(table
, p
);
5930 for (rn
= bgp_node_get(table
, p
); rn
;
5931 rn
= bgp_route_next_until(rn
, top
)) {
5932 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5937 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5938 if (BGP_PATH_HOLDDOWN(pi
))
5942 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5943 atomic_aggregate
= 1;
5945 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5949 * summary-only aggregate route suppress
5950 * aggregated route announcements.
5952 if (aggregate
->summary_only
) {
5953 (bgp_path_info_extra_get(pi
))->suppress
++;
5954 bgp_path_info_set_flag(rn
, pi
,
5955 BGP_PATH_ATTR_CHANGED
);
5962 * If at least one route among routes that are
5963 * aggregated has ORIGIN with the value INCOMPLETE,
5964 * then the aggregated route MUST have the ORIGIN
5965 * attribute with the value INCOMPLETE. Otherwise, if
5966 * at least one route among routes that are aggregated
5967 * has ORIGIN with the value EGP, then the aggregated
5968 * route MUST have the ORIGIN attribute with the value
5971 switch (pi
->attr
->origin
) {
5972 case BGP_ORIGIN_INCOMPLETE
:
5973 aggregate
->incomplete_origin_count
++;
5975 case BGP_ORIGIN_EGP
:
5976 aggregate
->egp_origin_count
++;
5984 if (!aggregate
->as_set
)
5988 * as-set aggregate route generate origin, as path,
5989 * and community aggregation.
5991 /* Compute aggregate route's as-path.
5993 bgp_compute_aggregate_aspath_hash(aggregate
,
5996 /* Compute aggregate route's community.
5998 if (pi
->attr
->community
)
5999 bgp_compute_aggregate_community_hash(
6001 pi
->attr
->community
);
6003 /* Compute aggregate route's extended community.
6005 if (pi
->attr
->ecommunity
)
6006 bgp_compute_aggregate_ecommunity_hash(
6008 pi
->attr
->ecommunity
);
6010 /* Compute aggregate route's large community.
6012 if (pi
->attr
->lcommunity
)
6013 bgp_compute_aggregate_lcommunity_hash(
6015 pi
->attr
->lcommunity
);
6018 bgp_process(bgp
, rn
, afi
, safi
);
6020 if (aggregate
->as_set
) {
6021 bgp_compute_aggregate_aspath_val(aggregate
);
6022 bgp_compute_aggregate_community_val(aggregate
);
6023 bgp_compute_aggregate_ecommunity_val(aggregate
);
6024 bgp_compute_aggregate_lcommunity_val(aggregate
);
6028 bgp_unlock_node(top
);
6031 if (aggregate
->incomplete_origin_count
> 0)
6032 origin
= BGP_ORIGIN_INCOMPLETE
;
6033 else if (aggregate
->egp_origin_count
> 0)
6034 origin
= BGP_ORIGIN_EGP
;
6036 if (aggregate
->as_set
) {
6037 if (aggregate
->aspath
)
6038 /* Retrieve aggregate route's as-path.
6040 aspath
= aspath_dup(aggregate
->aspath
);
6042 if (aggregate
->community
)
6043 /* Retrieve aggregate route's community.
6045 community
= community_dup(aggregate
->community
);
6047 if (aggregate
->ecommunity
)
6048 /* Retrieve aggregate route's ecommunity.
6050 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6052 if (aggregate
->lcommunity
)
6053 /* Retrieve aggregate route's lcommunity.
6055 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6058 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6059 ecommunity
, lcommunity
, atomic_aggregate
,
6063 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6064 safi_t safi
, struct bgp_aggregate
*aggregate
)
6066 struct bgp_table
*table
;
6067 struct bgp_node
*top
;
6068 struct bgp_node
*rn
;
6069 struct bgp_path_info
*pi
;
6070 unsigned long match
;
6072 table
= bgp
->rib
[afi
][safi
];
6074 /* If routes exists below this node, generate aggregate routes. */
6075 top
= bgp_node_get(table
, p
);
6076 for (rn
= bgp_node_get(table
, p
); rn
;
6077 rn
= bgp_route_next_until(rn
, top
)) {
6078 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6082 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6083 if (BGP_PATH_HOLDDOWN(pi
))
6086 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6089 if (aggregate
->summary_only
&& pi
->extra
) {
6090 pi
->extra
->suppress
--;
6092 if (pi
->extra
->suppress
== 0) {
6093 bgp_path_info_set_flag(
6094 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6100 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6101 aggregate
->incomplete_origin_count
--;
6102 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6103 aggregate
->egp_origin_count
--;
6105 if (aggregate
->as_set
) {
6106 /* Remove as-path from aggregate.
6108 bgp_remove_aspath_from_aggregate_hash(
6112 if (pi
->attr
->community
)
6113 /* Remove community from aggregate.
6115 bgp_remove_comm_from_aggregate_hash(
6117 pi
->attr
->community
);
6119 if (pi
->attr
->ecommunity
)
6120 /* Remove ecommunity from aggregate.
6122 bgp_remove_ecomm_from_aggregate_hash(
6124 pi
->attr
->ecommunity
);
6126 if (pi
->attr
->lcommunity
)
6127 /* Remove lcommunity from aggregate.
6129 bgp_remove_lcomm_from_aggregate_hash(
6131 pi
->attr
->lcommunity
);
6136 /* If this node was suppressed, process the change. */
6138 bgp_process(bgp
, rn
, afi
, safi
);
6140 if (aggregate
->as_set
) {
6141 aspath_free(aggregate
->aspath
);
6142 aggregate
->aspath
= NULL
;
6143 if (aggregate
->community
)
6144 community_free(&aggregate
->community
);
6145 if (aggregate
->ecommunity
)
6146 ecommunity_free(&aggregate
->ecommunity
);
6147 if (aggregate
->lcommunity
)
6148 lcommunity_free(&aggregate
->lcommunity
);
6151 bgp_unlock_node(top
);
6154 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6155 struct bgp_path_info
*pinew
, afi_t afi
,
6157 struct bgp_aggregate
*aggregate
)
6160 struct aspath
*aspath
= NULL
;
6161 uint8_t atomic_aggregate
= 0;
6162 struct community
*community
= NULL
;
6163 struct ecommunity
*ecommunity
= NULL
;
6164 struct lcommunity
*lcommunity
= NULL
;
6166 /* ORIGIN attribute: If at least one route among routes that are
6167 * aggregated has ORIGIN with the value INCOMPLETE, then the
6168 * aggregated route must have the ORIGIN attribute with the value
6169 * INCOMPLETE. Otherwise, if at least one route among routes that
6170 * are aggregated has ORIGIN with the value EGP, then the aggregated
6171 * route must have the origin attribute with the value EGP. In all
6172 * other case the value of the ORIGIN attribute of the aggregated
6173 * route is INTERNAL.
6175 origin
= BGP_ORIGIN_IGP
;
6179 if (aggregate
->summary_only
)
6180 (bgp_path_info_extra_get(pinew
))->suppress
++;
6182 switch (pinew
->attr
->origin
) {
6183 case BGP_ORIGIN_INCOMPLETE
:
6184 aggregate
->incomplete_origin_count
++;
6186 case BGP_ORIGIN_EGP
:
6187 aggregate
->egp_origin_count
++;
6195 if (aggregate
->incomplete_origin_count
> 0)
6196 origin
= BGP_ORIGIN_INCOMPLETE
;
6197 else if (aggregate
->egp_origin_count
> 0)
6198 origin
= BGP_ORIGIN_EGP
;
6200 if (aggregate
->as_set
) {
6201 /* Compute aggregate route's as-path.
6203 bgp_compute_aggregate_aspath(aggregate
,
6204 pinew
->attr
->aspath
);
6206 /* Compute aggregate route's community.
6208 if (pinew
->attr
->community
)
6209 bgp_compute_aggregate_community(
6211 pinew
->attr
->community
);
6213 /* Compute aggregate route's extended community.
6215 if (pinew
->attr
->ecommunity
)
6216 bgp_compute_aggregate_ecommunity(
6218 pinew
->attr
->ecommunity
);
6220 /* Compute aggregate route's large community.
6222 if (pinew
->attr
->lcommunity
)
6223 bgp_compute_aggregate_lcommunity(
6225 pinew
->attr
->lcommunity
);
6227 /* Retrieve aggregate route's as-path.
6229 if (aggregate
->aspath
)
6230 aspath
= aspath_dup(aggregate
->aspath
);
6232 /* Retrieve aggregate route's community.
6234 if (aggregate
->community
)
6235 community
= community_dup(aggregate
->community
);
6237 /* Retrieve aggregate route's ecommunity.
6239 if (aggregate
->ecommunity
)
6240 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6242 /* Retrieve aggregate route's lcommunity.
6244 if (aggregate
->lcommunity
)
6245 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6248 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6249 aspath
, community
, ecommunity
,
6250 lcommunity
, atomic_aggregate
, aggregate
);
6253 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6255 struct bgp_path_info
*pi
,
6256 struct bgp_aggregate
*aggregate
,
6257 struct prefix
*aggr_p
)
6260 struct aspath
*aspath
= NULL
;
6261 uint8_t atomic_aggregate
= 0;
6262 struct community
*community
= NULL
;
6263 struct ecommunity
*ecommunity
= NULL
;
6264 struct lcommunity
*lcommunity
= NULL
;
6265 unsigned long match
= 0;
6267 if (BGP_PATH_HOLDDOWN(pi
))
6270 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6273 if (aggregate
->summary_only
6275 && pi
->extra
->suppress
> 0) {
6276 pi
->extra
->suppress
--;
6278 if (pi
->extra
->suppress
== 0) {
6279 bgp_path_info_set_flag(pi
->net
, pi
,
6280 BGP_PATH_ATTR_CHANGED
);
6285 if (aggregate
->count
> 0)
6288 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6289 aggregate
->incomplete_origin_count
--;
6290 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6291 aggregate
->egp_origin_count
--;
6293 if (aggregate
->as_set
) {
6294 /* Remove as-path from aggregate.
6296 bgp_remove_aspath_from_aggregate(aggregate
,
6299 if (pi
->attr
->community
)
6300 /* Remove community from aggregate.
6302 bgp_remove_community_from_aggregate(
6304 pi
->attr
->community
);
6306 if (pi
->attr
->ecommunity
)
6307 /* Remove ecommunity from aggregate.
6309 bgp_remove_ecommunity_from_aggregate(
6311 pi
->attr
->ecommunity
);
6313 if (pi
->attr
->lcommunity
)
6314 /* Remove lcommunity from aggregate.
6316 bgp_remove_lcommunity_from_aggregate(
6318 pi
->attr
->lcommunity
);
6321 /* If this node was suppressed, process the change. */
6323 bgp_process(bgp
, pi
->net
, afi
, safi
);
6325 origin
= BGP_ORIGIN_IGP
;
6326 if (aggregate
->incomplete_origin_count
> 0)
6327 origin
= BGP_ORIGIN_INCOMPLETE
;
6328 else if (aggregate
->egp_origin_count
> 0)
6329 origin
= BGP_ORIGIN_EGP
;
6331 if (aggregate
->as_set
) {
6332 /* Retrieve aggregate route's as-path.
6334 if (aggregate
->aspath
)
6335 aspath
= aspath_dup(aggregate
->aspath
);
6337 /* Retrieve aggregate route's community.
6339 if (aggregate
->community
)
6340 community
= community_dup(aggregate
->community
);
6342 /* Retrieve aggregate route's ecommunity.
6344 if (aggregate
->ecommunity
)
6345 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6347 /* Retrieve aggregate route's lcommunity.
6349 if (aggregate
->lcommunity
)
6350 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6353 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6354 aspath
, community
, ecommunity
,
6355 lcommunity
, atomic_aggregate
, aggregate
);
6358 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6359 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6361 struct bgp_node
*child
;
6362 struct bgp_node
*rn
;
6363 struct bgp_aggregate
*aggregate
;
6364 struct bgp_table
*table
;
6366 table
= bgp
->aggregate
[afi
][safi
];
6368 /* No aggregates configured. */
6369 if (bgp_table_top_nolock(table
) == NULL
)
6372 if (p
->prefixlen
== 0)
6375 if (BGP_PATH_HOLDDOWN(pi
))
6378 child
= bgp_node_get(table
, p
);
6380 /* Aggregate address configuration check. */
6381 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6382 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6383 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6384 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6388 bgp_unlock_node(child
);
6391 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6392 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6394 struct bgp_node
*child
;
6395 struct bgp_node
*rn
;
6396 struct bgp_aggregate
*aggregate
;
6397 struct bgp_table
*table
;
6399 table
= bgp
->aggregate
[afi
][safi
];
6401 /* No aggregates configured. */
6402 if (bgp_table_top_nolock(table
) == NULL
)
6405 if (p
->prefixlen
== 0)
6408 child
= bgp_node_get(table
, p
);
6410 /* Aggregate address configuration check. */
6411 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6412 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6413 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6414 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6415 del
, aggregate
, &rn
->p
);
6418 bgp_unlock_node(child
);
6421 /* Aggregate route attribute. */
6422 #define AGGREGATE_SUMMARY_ONLY 1
6423 #define AGGREGATE_AS_SET 1
6424 #define AGGREGATE_AS_UNSET 0
6426 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6427 afi_t afi
, safi_t safi
)
6429 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6432 struct bgp_node
*rn
;
6433 struct bgp_aggregate
*aggregate
;
6435 /* Convert string to prefix structure. */
6436 ret
= str2prefix(prefix_str
, &p
);
6438 vty_out(vty
, "Malformed prefix\n");
6439 return CMD_WARNING_CONFIG_FAILED
;
6443 /* Old configuration check. */
6444 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6447 "%% There is no aggregate-address configuration.\n");
6448 return CMD_WARNING_CONFIG_FAILED
;
6451 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6452 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6453 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6454 NULL
, NULL
, 0, aggregate
);
6456 /* Unlock aggregate address configuration. */
6457 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6459 if (aggregate
->community
)
6460 community_free(&aggregate
->community
);
6462 if (aggregate
->community_hash
) {
6463 /* Delete all communities in the hash.
6465 hash_clean(aggregate
->community_hash
,
6466 bgp_aggr_community_remove
);
6467 /* Free up the community_hash.
6469 hash_free(aggregate
->community_hash
);
6472 if (aggregate
->ecommunity
)
6473 ecommunity_free(&aggregate
->ecommunity
);
6475 if (aggregate
->ecommunity_hash
) {
6476 /* Delete all ecommunities in the hash.
6478 hash_clean(aggregate
->ecommunity_hash
,
6479 bgp_aggr_ecommunity_remove
);
6480 /* Free up the ecommunity_hash.
6482 hash_free(aggregate
->ecommunity_hash
);
6485 if (aggregate
->lcommunity
)
6486 lcommunity_free(&aggregate
->lcommunity
);
6488 if (aggregate
->lcommunity_hash
) {
6489 /* Delete all lcommunities in the hash.
6491 hash_clean(aggregate
->lcommunity_hash
,
6492 bgp_aggr_lcommunity_remove
);
6493 /* Free up the lcommunity_hash.
6495 hash_free(aggregate
->lcommunity_hash
);
6498 if (aggregate
->aspath
)
6499 aspath_free(aggregate
->aspath
);
6501 if (aggregate
->aspath_hash
) {
6502 /* Delete all as-paths in the hash.
6504 hash_clean(aggregate
->aspath_hash
,
6505 bgp_aggr_aspath_remove
);
6506 /* Free up the aspath_hash.
6508 hash_free(aggregate
->aspath_hash
);
6511 bgp_aggregate_free(aggregate
);
6512 bgp_unlock_node(rn
);
6513 bgp_unlock_node(rn
);
6518 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6519 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6522 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6525 struct bgp_node
*rn
;
6526 struct bgp_aggregate
*aggregate
;
6527 uint8_t as_set_new
= as_set
;
6529 /* Convert string to prefix structure. */
6530 ret
= str2prefix(prefix_str
, &p
);
6532 vty_out(vty
, "Malformed prefix\n");
6533 return CMD_WARNING_CONFIG_FAILED
;
6537 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6538 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6539 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6541 return CMD_WARNING_CONFIG_FAILED
;
6544 /* Old configuration check. */
6545 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6546 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6549 vty_out(vty
, "There is already same aggregate network.\n");
6550 /* try to remove the old entry */
6551 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6553 vty_out(vty
, "Error deleting aggregate.\n");
6554 bgp_unlock_node(rn
);
6555 return CMD_WARNING_CONFIG_FAILED
;
6559 /* Make aggregate address structure. */
6560 aggregate
= bgp_aggregate_new();
6561 aggregate
->summary_only
= summary_only
;
6563 /* Network operators MUST NOT locally generate any new
6564 * announcements containing AS_SET or AS_CONFED_SET. If they have
6565 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6566 * SHOULD withdraw those routes and re-announce routes for the
6567 * aggregate or component prefixes (i.e., the more-specific routes
6568 * subsumed by the previously aggregated route) without AS_SET
6569 * or AS_CONFED_SET in the updates.
6571 if (bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
) {
6572 if (as_set
== AGGREGATE_AS_SET
) {
6573 as_set_new
= AGGREGATE_AS_UNSET
;
6575 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
6578 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6582 aggregate
->as_set
= as_set_new
;
6583 aggregate
->safi
= safi
;
6586 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6587 route_map_counter_decrement(aggregate
->rmap
.map
);
6588 aggregate
->rmap
.name
=
6589 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6590 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6591 route_map_counter_increment(aggregate
->rmap
.map
);
6593 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6595 /* Aggregate address insert into BGP routing table. */
6596 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6601 DEFUN (aggregate_address
,
6602 aggregate_address_cmd
,
6603 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6604 "Configure BGP aggregate entries\n"
6605 "Aggregate prefix\n"
6606 "Generate AS set path information\n"
6607 "Filter more specific routes from updates\n"
6608 "Filter more specific routes from updates\n"
6609 "Generate AS set path information\n"
6610 "Apply route map to aggregate network\n"
6611 "Name of route map\n")
6614 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6615 char *prefix
= argv
[idx
]->arg
;
6617 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6618 : AGGREGATE_AS_UNSET
;
6620 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6621 ? AGGREGATE_SUMMARY_ONLY
6625 argv_find(argv
, argc
, "WORD", &idx
);
6627 rmap
= argv
[idx
]->arg
;
6629 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6630 rmap
, summary_only
, as_set
);
6633 DEFUN (aggregate_address_mask
,
6634 aggregate_address_mask_cmd
,
6635 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6636 "Configure BGP aggregate entries\n"
6637 "Aggregate address\n"
6639 "Generate AS set path information\n"
6640 "Filter more specific routes from updates\n"
6641 "Filter more specific routes from updates\n"
6642 "Generate AS set path information\n"
6643 "Apply route map to aggregate network\n"
6644 "Name of route map\n")
6647 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6648 char *prefix
= argv
[idx
]->arg
;
6649 char *mask
= argv
[idx
+ 1]->arg
;
6652 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6653 : AGGREGATE_AS_UNSET
;
6655 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6656 ? AGGREGATE_SUMMARY_ONLY
6659 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6661 rmap
= argv
[idx
]->arg
;
6663 char prefix_str
[BUFSIZ
];
6664 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6667 vty_out(vty
, "%% Inconsistent address and mask\n");
6668 return CMD_WARNING_CONFIG_FAILED
;
6671 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6672 rmap
, summary_only
, as_set
);
6675 DEFUN (no_aggregate_address
,
6676 no_aggregate_address_cmd
,
6677 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6679 "Configure BGP aggregate entries\n"
6680 "Aggregate prefix\n"
6681 "Generate AS set path information\n"
6682 "Filter more specific routes from updates\n"
6683 "Filter more specific routes from updates\n"
6684 "Generate AS set path information\n"
6685 "Apply route map to aggregate network\n"
6686 "Name of route map\n")
6689 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6690 char *prefix
= argv
[idx
]->arg
;
6691 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6694 DEFUN (no_aggregate_address_mask
,
6695 no_aggregate_address_mask_cmd
,
6696 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6698 "Configure BGP aggregate entries\n"
6699 "Aggregate address\n"
6701 "Generate AS set path information\n"
6702 "Filter more specific routes from updates\n"
6703 "Filter more specific routes from updates\n"
6704 "Generate AS set path information\n"
6705 "Apply route map to aggregate network\n"
6706 "Name of route map\n")
6709 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6710 char *prefix
= argv
[idx
]->arg
;
6711 char *mask
= argv
[idx
+ 1]->arg
;
6713 char prefix_str
[BUFSIZ
];
6714 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6717 vty_out(vty
, "%% Inconsistent address and mask\n");
6718 return CMD_WARNING_CONFIG_FAILED
;
6721 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6724 DEFUN (ipv6_aggregate_address
,
6725 ipv6_aggregate_address_cmd
,
6726 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6727 "Configure BGP aggregate entries\n"
6728 "Aggregate prefix\n"
6729 "Generate AS set path information\n"
6730 "Filter more specific routes from updates\n"
6731 "Filter more specific routes from updates\n"
6732 "Generate AS set path information\n"
6733 "Apply route map to aggregate network\n"
6734 "Name of route map\n")
6737 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6738 char *prefix
= argv
[idx
]->arg
;
6741 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6742 : AGGREGATE_AS_UNSET
;
6745 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6746 ? AGGREGATE_SUMMARY_ONLY
6749 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6751 rmap
= argv
[idx
]->arg
;
6753 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6757 DEFUN (no_ipv6_aggregate_address
,
6758 no_ipv6_aggregate_address_cmd
,
6759 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6761 "Configure BGP aggregate entries\n"
6762 "Aggregate prefix\n"
6763 "Generate AS set path information\n"
6764 "Filter more specific routes from updates\n"
6765 "Filter more specific routes from updates\n"
6766 "Generate AS set path information\n"
6767 "Apply route map to aggregate network\n"
6768 "Name of route map\n")
6771 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6772 char *prefix
= argv
[idx
]->arg
;
6773 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6776 /* Redistribute route treatment. */
6777 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6778 const union g_addr
*nexthop
, ifindex_t ifindex
,
6779 enum nexthop_types_t nhtype
, uint32_t metric
,
6780 uint8_t type
, unsigned short instance
,
6783 struct bgp_path_info
*new;
6784 struct bgp_path_info
*bpi
;
6785 struct bgp_path_info rmap_path
;
6786 struct bgp_node
*bn
;
6788 struct attr
*new_attr
;
6790 route_map_result_t ret
;
6791 struct bgp_redist
*red
;
6793 /* Make default attribute. */
6794 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6796 * This must not be NULL to satisfy Coverity SA
6798 assert(attr
.aspath
);
6801 case NEXTHOP_TYPE_IFINDEX
:
6803 case NEXTHOP_TYPE_IPV4
:
6804 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6805 attr
.nexthop
= nexthop
->ipv4
;
6807 case NEXTHOP_TYPE_IPV6
:
6808 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6809 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6810 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6812 case NEXTHOP_TYPE_BLACKHOLE
:
6813 switch (p
->family
) {
6815 attr
.nexthop
.s_addr
= INADDR_ANY
;
6818 memset(&attr
.mp_nexthop_global
, 0,
6819 sizeof(attr
.mp_nexthop_global
));
6820 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6825 attr
.nh_ifindex
= ifindex
;
6828 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6831 afi
= family2afi(p
->family
);
6833 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6835 struct attr attr_new
;
6837 /* Copy attribute for modification. */
6840 if (red
->redist_metric_flag
)
6841 attr_new
.med
= red
->redist_metric
;
6843 /* Apply route-map. */
6844 if (red
->rmap
.name
) {
6845 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6846 rmap_path
.peer
= bgp
->peer_self
;
6847 rmap_path
.attr
= &attr_new
;
6849 SET_FLAG(bgp
->peer_self
->rmap_type
,
6850 PEER_RMAP_TYPE_REDISTRIBUTE
);
6852 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6855 bgp
->peer_self
->rmap_type
= 0;
6857 if (ret
== RMAP_DENYMATCH
) {
6858 /* Free uninterned attribute. */
6859 bgp_attr_flush(&attr_new
);
6861 /* Unintern original. */
6862 aspath_unintern(&attr
.aspath
);
6863 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6868 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6869 bgp_attr_add_gshut_community(&attr_new
);
6871 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6872 SAFI_UNICAST
, p
, NULL
);
6874 new_attr
= bgp_attr_intern(&attr_new
);
6876 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6878 if (bpi
->peer
== bgp
->peer_self
6879 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6883 /* Ensure the (source route) type is updated. */
6885 if (attrhash_cmp(bpi
->attr
, new_attr
)
6886 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6887 bgp_attr_unintern(&new_attr
);
6888 aspath_unintern(&attr
.aspath
);
6889 bgp_unlock_node(bn
);
6892 /* The attribute is changed. */
6893 bgp_path_info_set_flag(bn
, bpi
,
6894 BGP_PATH_ATTR_CHANGED
);
6896 /* Rewrite BGP route information. */
6897 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6898 bgp_path_info_restore(bn
, bpi
);
6900 bgp_aggregate_decrement(
6901 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6902 bgp_attr_unintern(&bpi
->attr
);
6903 bpi
->attr
= new_attr
;
6904 bpi
->uptime
= bgp_clock();
6906 /* Process change. */
6907 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6909 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6910 bgp_unlock_node(bn
);
6911 aspath_unintern(&attr
.aspath
);
6913 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6915 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6917 vpn_leak_from_vrf_update(
6918 bgp_get_default(), bgp
, bpi
);
6924 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6925 bgp
->peer_self
, new_attr
, bn
);
6926 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6928 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6929 bgp_path_info_add(bn
, new);
6930 bgp_unlock_node(bn
);
6931 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6933 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6934 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6936 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6940 /* Unintern original. */
6941 aspath_unintern(&attr
.aspath
);
6944 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6945 unsigned short instance
)
6948 struct bgp_node
*rn
;
6949 struct bgp_path_info
*pi
;
6950 struct bgp_redist
*red
;
6952 afi
= family2afi(p
->family
);
6954 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6956 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6957 SAFI_UNICAST
, p
, NULL
);
6959 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6960 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6964 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6965 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6967 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6970 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6971 bgp_path_info_delete(rn
, pi
);
6972 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6974 bgp_unlock_node(rn
);
6978 /* Withdraw specified route type's route. */
6979 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6980 unsigned short instance
)
6982 struct bgp_node
*rn
;
6983 struct bgp_path_info
*pi
;
6984 struct bgp_table
*table
;
6986 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6988 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6989 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6990 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6991 && pi
->instance
== instance
)
6995 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6996 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6998 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7001 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
7003 bgp_path_info_delete(rn
, pi
);
7004 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7009 /* Static function to display route. */
7010 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
7017 if (p
->family
== AF_INET
) {
7021 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7024 json_object_string_add(json
, "prefix",
7025 inet_ntop(p
->family
,
7028 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7029 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7030 json_object_string_add(json
, "network", buf2
);
7032 } else if (p
->family
== AF_ETHERNET
) {
7033 prefix2str(p
, buf
, PREFIX_STRLEN
);
7034 len
= vty_out(vty
, "%s", buf
);
7035 } else if (p
->family
== AF_EVPN
) {
7039 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7042 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7043 } else if (p
->family
== AF_FLOWSPEC
) {
7044 route_vty_out_flowspec(vty
, p
, NULL
,
7046 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7047 NLRI_STRING_FORMAT_MIN
, json
);
7052 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7055 json_object_string_add(json
, "prefix",
7056 inet_ntop(p
->family
,
7059 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7060 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7061 json_object_string_add(json
, "network", buf2
);
7068 vty_out(vty
, "\n%*s", 20, " ");
7070 vty_out(vty
, "%*s", len
, " ");
7074 enum bgp_display_type
{
7078 /* Print the short form route status for a bgp_path_info */
7079 static void route_vty_short_status_out(struct vty
*vty
,
7080 struct bgp_path_info
*path
,
7081 json_object
*json_path
)
7085 /* Route status display. */
7086 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7087 json_object_boolean_true_add(json_path
, "removed");
7089 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7090 json_object_boolean_true_add(json_path
, "stale");
7092 if (path
->extra
&& path
->extra
->suppress
)
7093 json_object_boolean_true_add(json_path
, "suppressed");
7095 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7096 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7097 json_object_boolean_true_add(json_path
, "valid");
7100 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7101 json_object_boolean_true_add(json_path
, "history");
7103 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7104 json_object_boolean_true_add(json_path
, "damped");
7106 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7107 json_object_boolean_true_add(json_path
, "bestpath");
7109 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7110 json_object_boolean_true_add(json_path
, "multipath");
7112 /* Internal route. */
7113 if ((path
->peer
->as
)
7114 && (path
->peer
->as
== path
->peer
->local_as
))
7115 json_object_string_add(json_path
, "pathFrom",
7118 json_object_string_add(json_path
, "pathFrom",
7124 /* Route status display. */
7125 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7127 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7129 else if (path
->extra
&& path
->extra
->suppress
)
7131 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7132 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7138 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7140 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7142 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7144 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7149 /* Internal route. */
7150 if (path
->peer
&& (path
->peer
->as
)
7151 && (path
->peer
->as
== path
->peer
->local_as
))
7157 static char *bgp_nexthop_hostname(struct peer
*peer
, struct attr
*attr
)
7159 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)
7160 && !(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))
7161 return peer
->hostname
;
7165 /* called from terminal list command */
7166 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7167 struct bgp_path_info
*path
, int display
, safi_t safi
,
7168 json_object
*json_paths
)
7170 struct attr
*attr
= path
->attr
;
7171 json_object
*json_path
= NULL
;
7172 json_object
*json_nexthops
= NULL
;
7173 json_object
*json_nexthop_global
= NULL
;
7174 json_object
*json_nexthop_ll
= NULL
;
7175 json_object
*json_ext_community
= NULL
;
7176 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7178 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7179 bool nexthop_othervrf
= false;
7180 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7181 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7182 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
7185 json_path
= json_object_new_object();
7187 /* short status lead text */
7188 route_vty_short_status_out(vty
, path
, json_path
);
7191 /* print prefix and mask */
7193 route_vty_out_route(p
, vty
, json_path
);
7195 vty_out(vty
, "%*s", 17, " ");
7197 route_vty_out_route(p
, vty
, json_path
);
7201 * If vrf id of nexthop is different from that of prefix,
7202 * set up printable string to append
7204 if (path
->extra
&& path
->extra
->bgp_orig
) {
7205 const char *self
= "";
7210 nexthop_othervrf
= true;
7211 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7213 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7214 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7215 "@%s%s", VRFID_NONE_STR
, self
);
7217 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7218 path
->extra
->bgp_orig
->vrf_id
, self
);
7220 if (path
->extra
->bgp_orig
->inst_type
7221 != BGP_INSTANCE_TYPE_DEFAULT
)
7223 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7225 const char *self
= "";
7230 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7234 * For ENCAP and EVPN routes, nexthop address family is not
7235 * neccessarily the same as the prefix address family.
7236 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7237 * EVPN routes are also exchanged with a MP nexthop. Currently,
7239 * is only IPv4, the value will be present in either
7241 * attr->mp_nexthop_global_in
7243 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7246 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7250 sprintf(nexthop
, "%s",
7251 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7255 sprintf(nexthop
, "%s",
7256 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7260 sprintf(nexthop
, "?");
7265 json_nexthop_global
= json_object_new_object();
7267 json_object_string_add(json_nexthop_global
, "ip",
7270 if (nexthop_hostname
)
7271 json_object_string_add(json_nexthop_global
,
7275 json_object_string_add(json_nexthop_global
, "afi",
7276 (af
== AF_INET
) ? "ipv4"
7278 json_object_boolean_true_add(json_nexthop_global
,
7281 vty_out(vty
, "%s%s",
7282 nexthop_hostname
? nexthop_hostname
: nexthop
,
7284 } else if (safi
== SAFI_EVPN
) {
7286 json_nexthop_global
= json_object_new_object();
7288 json_object_string_add(json_nexthop_global
, "ip",
7289 inet_ntoa(attr
->nexthop
));
7291 if (nexthop_hostname
)
7292 json_object_string_add(json_nexthop_global
,
7296 json_object_string_add(json_nexthop_global
, "afi",
7298 json_object_boolean_true_add(json_nexthop_global
,
7301 vty_out(vty
, "%-16s%s",
7302 nexthop_hostname
? nexthop_hostname
7303 : inet_ntoa(attr
->nexthop
),
7305 } else if (safi
== SAFI_FLOWSPEC
) {
7306 if (attr
->nexthop
.s_addr
!= 0) {
7308 json_nexthop_global
= json_object_new_object();
7310 json_object_string_add(json_nexthop_global
,
7312 json_object_string_add(
7313 json_nexthop_global
, "ip",
7314 inet_ntoa(attr
->nexthop
));
7316 if (nexthop_hostname
)
7317 json_object_string_add(
7318 json_nexthop_global
, "hostname",
7321 json_object_boolean_true_add(
7322 json_nexthop_global
,
7325 vty_out(vty
, "%-16s",
7328 : inet_ntoa(attr
->nexthop
));
7331 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7333 json_nexthop_global
= json_object_new_object();
7335 json_object_string_add(json_nexthop_global
, "ip",
7336 inet_ntoa(attr
->nexthop
));
7338 if (nexthop_hostname
)
7339 json_object_string_add(json_nexthop_global
,
7343 json_object_string_add(json_nexthop_global
, "afi",
7345 json_object_boolean_true_add(json_nexthop_global
,
7350 snprintf(buf
, sizeof(buf
), "%s%s",
7351 nexthop_hostname
? nexthop_hostname
7352 : inet_ntoa(attr
->nexthop
),
7354 vty_out(vty
, "%-16s", buf
);
7359 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7364 json_nexthop_global
= json_object_new_object();
7365 json_object_string_add(
7366 json_nexthop_global
, "ip",
7367 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7370 if (nexthop_hostname
)
7371 json_object_string_add(json_nexthop_global
,
7375 json_object_string_add(json_nexthop_global
, "afi",
7377 json_object_string_add(json_nexthop_global
, "scope",
7380 /* We display both LL & GL if both have been
7382 if ((attr
->mp_nexthop_len
7383 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7384 || (path
->peer
->conf_if
)) {
7385 json_nexthop_ll
= json_object_new_object();
7386 json_object_string_add(
7387 json_nexthop_ll
, "ip",
7389 &attr
->mp_nexthop_local
, buf
,
7392 if (nexthop_hostname
)
7393 json_object_string_add(
7394 json_nexthop_ll
, "hostname",
7397 json_object_string_add(json_nexthop_ll
, "afi",
7399 json_object_string_add(json_nexthop_ll
, "scope",
7402 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7403 &attr
->mp_nexthop_local
)
7405 && !attr
->mp_nexthop_prefer_global
)
7406 json_object_boolean_true_add(
7407 json_nexthop_ll
, "used");
7409 json_object_boolean_true_add(
7410 json_nexthop_global
, "used");
7412 json_object_boolean_true_add(
7413 json_nexthop_global
, "used");
7415 /* Display LL if LL/Global both in table unless
7416 * prefer-global is set */
7417 if (((attr
->mp_nexthop_len
7418 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7419 && !attr
->mp_nexthop_prefer_global
)
7420 || (path
->peer
->conf_if
)) {
7421 if (path
->peer
->conf_if
) {
7422 len
= vty_out(vty
, "%s",
7423 path
->peer
->conf_if
);
7424 len
= 16 - len
; /* len of IPv6
7430 vty_out(vty
, "\n%*s", 36, " ");
7432 vty_out(vty
, "%*s", len
, " ");
7440 &attr
->mp_nexthop_local
,
7446 vty_out(vty
, "\n%*s", 36, " ");
7448 vty_out(vty
, "%*s", len
, " ");
7457 &attr
->mp_nexthop_global
,
7463 vty_out(vty
, "\n%*s", 36, " ");
7465 vty_out(vty
, "%*s", len
, " ");
7471 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7475 * Adding "metric" field to match with corresponding
7476 * CLI. "med" will be deprecated in future.
7478 json_object_int_add(json_path
, "med", attr
->med
);
7479 json_object_int_add(json_path
, "metric", attr
->med
);
7481 vty_out(vty
, "%10u", attr
->med
);
7482 else if (!json_paths
)
7486 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7490 * Adding "locPrf" field to match with corresponding
7491 * CLI. "localPref" will be deprecated in future.
7493 json_object_int_add(json_path
, "localpref",
7495 json_object_int_add(json_path
, "locPrf",
7498 vty_out(vty
, "%7u", attr
->local_pref
);
7499 else if (!json_paths
)
7503 json_object_int_add(json_path
, "weight", attr
->weight
);
7505 vty_out(vty
, "%7u ", attr
->weight
);
7509 json_object_string_add(
7510 json_path
, "peerId",
7511 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7519 * Adding "path" field to match with corresponding
7520 * CLI. "aspath" will be deprecated in future.
7522 json_object_string_add(json_path
, "aspath",
7524 json_object_string_add(json_path
, "path",
7527 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7532 json_object_string_add(json_path
, "origin",
7533 bgp_origin_long_str
[attr
->origin
]);
7535 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7538 if (safi
== SAFI_EVPN
&&
7539 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7540 json_ext_community
= json_object_new_object();
7541 json_object_string_add(json_ext_community
,
7543 attr
->ecommunity
->str
);
7544 json_object_object_add(json_path
,
7545 "extendedCommunity",
7546 json_ext_community
);
7550 json_object_boolean_true_add(json_path
,
7551 "announceNexthopSelf");
7552 if (nexthop_othervrf
) {
7553 json_object_string_add(json_path
, "nhVrfName",
7556 json_object_int_add(json_path
, "nhVrfId",
7557 ((nexthop_vrfid
== VRF_UNKNOWN
)
7559 : (int)nexthop_vrfid
));
7564 if (json_nexthop_global
|| json_nexthop_ll
) {
7565 json_nexthops
= json_object_new_array();
7567 if (json_nexthop_global
)
7568 json_object_array_add(json_nexthops
,
7569 json_nexthop_global
);
7571 if (json_nexthop_ll
)
7572 json_object_array_add(json_nexthops
,
7575 json_object_object_add(json_path
, "nexthops",
7579 json_object_array_add(json_paths
, json_path
);
7583 if (safi
== SAFI_EVPN
&&
7584 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7585 vty_out(vty
, "%*s", 20, " ");
7586 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7590 /* prints an additional line, indented, with VNC info, if
7592 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7593 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7598 /* called from terminal list command */
7599 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7600 safi_t safi
, bool use_json
, json_object
*json_ar
)
7602 json_object
*json_status
= NULL
;
7603 json_object
*json_net
= NULL
;
7606 /* Route status display. */
7608 json_status
= json_object_new_object();
7609 json_net
= json_object_new_object();
7616 /* print prefix and mask */
7618 if (safi
== SAFI_EVPN
)
7619 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7620 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7621 json_object_string_add(
7622 json_net
, "addrPrefix",
7623 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7625 json_object_int_add(json_net
, "prefixLen",
7627 prefix2str(p
, buff
, PREFIX_STRLEN
);
7628 json_object_string_add(json_net
, "network", buff
);
7631 route_vty_out_route(p
, vty
, NULL
);
7633 /* Print attribute */
7636 if (p
->family
== AF_INET
7637 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7638 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7639 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7640 json_object_string_add(
7641 json_net
, "nextHop",
7643 attr
->mp_nexthop_global_in
));
7645 json_object_string_add(
7646 json_net
, "nextHop",
7647 inet_ntoa(attr
->nexthop
));
7648 } else if (p
->family
== AF_INET6
7649 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7652 json_object_string_add(
7653 json_net
, "nextHopGlobal",
7655 &attr
->mp_nexthop_global
, buf
,
7657 } else if (p
->family
== AF_EVPN
&&
7658 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7659 json_object_string_add(json_net
,
7660 "nextHop", inet_ntoa(
7661 attr
->mp_nexthop_global_in
));
7664 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7665 json_object_int_add(json_net
, "metric",
7668 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7671 * Adding "locPrf" field to match with
7672 * corresponding CLI. "localPref" will be
7673 * deprecated in future.
7675 json_object_int_add(json_net
, "localPref",
7677 json_object_int_add(json_net
, "locPrf",
7681 json_object_int_add(json_net
, "weight", attr
->weight
);
7687 * Adding "path" field to match with
7688 * corresponding CLI. "localPref" will be
7689 * deprecated in future.
7691 json_object_string_add(json_net
, "asPath",
7693 json_object_string_add(json_net
, "path",
7698 json_object_string_add(json_net
, "bgpOriginCode",
7699 bgp_origin_str
[attr
->origin
]);
7701 if (p
->family
== AF_INET
7702 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7703 || safi
== SAFI_EVPN
7704 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7705 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7706 || safi
== SAFI_EVPN
)
7707 vty_out(vty
, "%-16s",
7709 attr
->mp_nexthop_global_in
));
7711 vty_out(vty
, "%-16s",
7712 inet_ntoa(attr
->nexthop
));
7713 } else if (p
->family
== AF_INET6
7714 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7721 &attr
->mp_nexthop_global
, buf
,
7725 vty_out(vty
, "\n%*s", 36, " ");
7727 vty_out(vty
, "%*s", len
, " ");
7730 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7731 vty_out(vty
, "%10u", attr
->med
);
7735 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7736 vty_out(vty
, "%7u", attr
->local_pref
);
7740 vty_out(vty
, "%7u ", attr
->weight
);
7744 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7747 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7751 json_object_boolean_true_add(json_status
, "*");
7752 json_object_boolean_true_add(json_status
, ">");
7753 json_object_object_add(json_net
, "appliedStatusSymbols",
7756 prefix2str(p
, buff
, PREFIX_STRLEN
);
7757 json_object_object_add(json_ar
, buff
, json_net
);
7762 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7763 struct bgp_path_info
*path
, int display
, safi_t safi
,
7766 json_object
*json_out
= NULL
;
7768 mpls_label_t label
= MPLS_INVALID_LABEL
;
7774 json_out
= json_object_new_object();
7776 /* short status lead text */
7777 route_vty_short_status_out(vty
, path
, json_out
);
7779 /* print prefix and mask */
7782 route_vty_out_route(p
, vty
, NULL
);
7784 vty_out(vty
, "%*s", 17, " ");
7787 /* Print attribute */
7789 if (((p
->family
== AF_INET
)
7790 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7791 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7792 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7793 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7794 || safi
== SAFI_EVPN
) {
7796 json_object_string_add(
7797 json_out
, "mpNexthopGlobalIn",
7798 inet_ntoa(attr
->mp_nexthop_global_in
));
7800 vty_out(vty
, "%-16s",
7801 inet_ntoa(attr
->mp_nexthop_global_in
));
7804 json_object_string_add(
7805 json_out
, "nexthop",
7806 inet_ntoa(attr
->nexthop
));
7808 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
7810 } else if (((p
->family
== AF_INET6
)
7811 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7812 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7813 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7816 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7818 json_object_string_add(
7819 json_out
, "mpNexthopGlobalIn",
7821 &attr
->mp_nexthop_global
,
7822 buf_a
, sizeof(buf_a
)));
7826 &attr
->mp_nexthop_global
,
7827 buf_a
, sizeof(buf_a
)));
7828 } else if (attr
->mp_nexthop_len
7829 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7830 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
7831 &attr
->mp_nexthop_global
,
7832 &attr
->mp_nexthop_local
);
7834 json_object_string_add(json_out
,
7835 "mpNexthopGlobalLocal",
7838 vty_out(vty
, "%s", buf_a
);
7842 label
= decode_label(&path
->extra
->label
[0]);
7844 if (bgp_is_valid_label(&label
)) {
7846 json_object_int_add(json_out
, "notag", label
);
7847 json_object_array_add(json
, json_out
);
7849 vty_out(vty
, "notag/%d", label
);
7855 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7856 struct bgp_path_info
*path
, int display
,
7857 json_object
*json_paths
)
7860 char buf
[BUFSIZ
] = {0};
7861 json_object
*json_path
= NULL
;
7862 json_object
*json_nexthop
= NULL
;
7863 json_object
*json_overlay
= NULL
;
7869 json_path
= json_object_new_object();
7870 json_overlay
= json_object_new_object();
7871 json_nexthop
= json_object_new_object();
7874 /* short status lead text */
7875 route_vty_short_status_out(vty
, path
, json_path
);
7877 /* print prefix and mask */
7879 route_vty_out_route(p
, vty
, json_path
);
7881 vty_out(vty
, "%*s", 17, " ");
7883 /* Print attribute */
7886 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7890 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
7892 vty_out(vty
, "%-16s", buf
);
7894 json_object_string_add(json_nexthop
, "ip", buf
);
7896 json_object_string_add(json_nexthop
, "afi", "ipv4");
7898 json_object_object_add(json_path
, "nexthop",
7903 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
7904 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
7906 vty_out(vty
, "%s(%s)", buf
, buf1
);
7908 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
7910 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
7913 json_object_string_add(json_nexthop
, "afi", "ipv6");
7915 json_object_object_add(json_path
, "nexthop",
7923 json_object_string_add(json_nexthop
, "Error",
7924 "Unsupported address-family");
7928 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7931 vty_out(vty
, "%s", str
);
7933 json_object_string_add(json_overlay
, "esi", str
);
7935 XFREE(MTYPE_TMP
, str
);
7937 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7938 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
7940 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7941 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7946 vty_out(vty
, "/%s", buf
);
7948 json_object_string_add(json_overlay
, "gw", buf
);
7950 if (attr
->ecommunity
) {
7952 struct ecommunity_val
*routermac
= ecommunity_lookup(
7953 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7954 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7957 mac
= ecom_mac2str((char *)routermac
->val
);
7960 vty_out(vty
, "/%s", (char *)mac
);
7962 json_object_string_add(json_overlay
, "rmac",
7965 XFREE(MTYPE_TMP
, mac
);
7972 json_object_object_add(json_path
, "overlay", json_overlay
);
7974 json_object_array_add(json_paths
, json_path
);
7978 /* dampening route */
7979 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7980 struct bgp_path_info
*path
, int display
, afi_t afi
,
7981 safi_t safi
, bool use_json
, json_object
*json
)
7985 char timebuf
[BGP_UPTIME_LEN
];
7987 /* short status lead text */
7988 route_vty_short_status_out(vty
, path
, json
);
7990 /* print prefix and mask */
7993 route_vty_out_route(p
, vty
, NULL
);
7995 vty_out(vty
, "%*s", 17, " ");
7998 len
= vty_out(vty
, "%s", path
->peer
->host
);
8002 vty_out(vty
, "\n%*s", 34, " ");
8005 json_object_int_add(json
, "peerHost", len
);
8007 vty_out(vty
, "%*s", len
, " ");
8011 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8012 safi
, use_json
, json
);
8015 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8016 BGP_UPTIME_LEN
, afi
, safi
,
8019 /* Print attribute */
8025 json_object_string_add(json
, "asPath",
8028 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8033 json_object_string_add(json
, "origin",
8034 bgp_origin_str
[attr
->origin
]);
8036 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8043 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8044 struct bgp_path_info
*path
, int display
, afi_t afi
,
8045 safi_t safi
, bool use_json
, json_object
*json
)
8048 struct bgp_damp_info
*bdi
;
8049 char timebuf
[BGP_UPTIME_LEN
];
8055 bdi
= path
->extra
->damp_info
;
8057 /* short status lead text */
8058 route_vty_short_status_out(vty
, path
, json
);
8060 /* print prefix and mask */
8063 route_vty_out_route(p
, vty
, NULL
);
8065 vty_out(vty
, "%*s", 17, " ");
8068 len
= vty_out(vty
, "%s", path
->peer
->host
);
8072 vty_out(vty
, "\n%*s", 33, " ");
8075 json_object_int_add(json
, "peerHost", len
);
8077 vty_out(vty
, "%*s", len
, " ");
8080 len
= vty_out(vty
, "%d", bdi
->flap
);
8087 json_object_int_add(json
, "bdiFlap", len
);
8089 vty_out(vty
, "%*s", len
, " ");
8093 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8096 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8097 BGP_UPTIME_LEN
, 0, NULL
));
8099 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8100 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8102 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8103 BGP_UPTIME_LEN
, afi
, safi
,
8107 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8108 BGP_UPTIME_LEN
, afi
,
8109 safi
, use_json
, json
));
8112 vty_out(vty
, "%*s ", 8, " ");
8115 /* Print attribute */
8121 json_object_string_add(json
, "asPath",
8124 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8129 json_object_string_add(json
, "origin",
8130 bgp_origin_str
[attr
->origin
]);
8132 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8138 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8139 int *first
, const char *header
,
8140 json_object
*json_adv_to
)
8142 char buf1
[INET6_ADDRSTRLEN
];
8143 json_object
*json_peer
= NULL
;
8146 /* 'advertised-to' is a dictionary of peers we have advertised
8148 * prefix too. The key is the peer's IP or swpX, the value is
8150 * hostname if we know it and "" if not.
8152 json_peer
= json_object_new_object();
8155 json_object_string_add(json_peer
, "hostname",
8159 json_object_object_add(json_adv_to
, peer
->conf_if
,
8162 json_object_object_add(
8164 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8168 vty_out(vty
, "%s", header
);
8173 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8175 vty_out(vty
, " %s(%s)", peer
->hostname
,
8178 vty_out(vty
, " %s(%s)", peer
->hostname
,
8179 sockunion2str(&peer
->su
, buf1
,
8183 vty_out(vty
, " %s", peer
->conf_if
);
8186 sockunion2str(&peer
->su
, buf1
,
8192 static void route_vty_out_tx_ids(struct vty
*vty
,
8193 struct bgp_addpath_info_data
*d
)
8197 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8198 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8199 d
->addpath_tx_id
[i
],
8200 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8204 static const char *bgp_path_selection_reason2str(
8205 enum bgp_path_selection_reason reason
)
8208 case bgp_path_selection_none
:
8209 return "Nothing to Select";
8211 case bgp_path_selection_first
:
8212 return "First path received";
8214 case bgp_path_selection_evpn_sticky_mac
:
8215 return "EVPN Sticky Mac";
8217 case bgp_path_selection_evpn_seq
:
8218 return "EVPN sequence number";
8220 case bgp_path_selection_evpn_lower_ip
:
8221 return "EVPN lower IP";
8223 case bgp_path_selection_weight
:
8226 case bgp_path_selection_local_pref
:
8227 return "Local Pref";
8229 case bgp_path_selection_local_route
:
8230 return "Local Route";
8232 case bgp_path_selection_confed_as_path
:
8233 return "Confederation based AS Path";
8235 case bgp_path_selection_as_path
:
8238 case bgp_path_selection_origin
:
8241 case bgp_path_selection_med
:
8244 case bgp_path_selection_peer
:
8247 case bgp_path_selection_confed
:
8248 return "Confed Peer Type";
8250 case bgp_path_selection_igp_metric
:
8251 return "IGP Metric";
8253 case bgp_path_selection_older
:
8254 return "Older Path";
8256 case bgp_path_selection_router_id
:
8259 case bgp_path_selection_cluster_length
:
8260 return "Cluser length";
8262 case bgp_path_selection_stale
:
8263 return "Path Staleness";
8265 case bgp_path_selection_local_configured
:
8266 return "Locally configured route";
8268 case bgp_path_selection_neighbor_ip
:
8269 return "Neighbor IP";
8271 case bgp_path_selection_default
:
8272 return "Nothing left to compare";
8275 return "Invalid (internal error)";
8278 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8279 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8280 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8282 char buf
[INET6_ADDRSTRLEN
];
8284 char buf2
[EVPN_ROUTE_STRLEN
];
8285 struct attr
*attr
= path
->attr
;
8286 int sockunion_vty_out(struct vty
*, union sockunion
*);
8288 json_object
*json_bestpath
= NULL
;
8289 json_object
*json_cluster_list
= NULL
;
8290 json_object
*json_cluster_list_list
= NULL
;
8291 json_object
*json_ext_community
= NULL
;
8292 json_object
*json_last_update
= NULL
;
8293 json_object
*json_pmsi
= NULL
;
8294 json_object
*json_nexthop_global
= NULL
;
8295 json_object
*json_nexthop_ll
= NULL
;
8296 json_object
*json_nexthops
= NULL
;
8297 json_object
*json_path
= NULL
;
8298 json_object
*json_peer
= NULL
;
8299 json_object
*json_string
= NULL
;
8300 json_object
*json_adv_to
= NULL
;
8302 struct listnode
*node
, *nnode
;
8304 int addpath_capable
;
8306 unsigned int first_as
;
8308 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8310 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
8313 json_path
= json_object_new_object();
8314 json_peer
= json_object_new_object();
8315 json_nexthop_global
= json_object_new_object();
8323 if (path
->extra
&& path
->extra
->num_labels
) {
8324 bgp_evpn_label2str(path
->extra
->label
,
8325 path
->extra
->num_labels
, tag_buf
,
8328 if (safi
== SAFI_EVPN
) {
8330 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8331 buf2
, sizeof(buf2
));
8332 vty_out(vty
, " Route %s", buf2
);
8333 if (tag_buf
[0] != '\0')
8334 vty_out(vty
, " VNI %s", tag_buf
);
8338 json_object_string_add(json_path
, "VNI",
8343 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8344 struct bgp_path_info
*parent_ri
;
8345 struct bgp_node
*rn
, *prn
;
8347 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8348 rn
= parent_ri
->net
;
8349 if (rn
&& rn
->prn
) {
8351 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8352 buf1
, sizeof(buf1
));
8353 if (is_pi_family_evpn(parent_ri
)) {
8354 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8355 buf2
, sizeof(buf2
));
8356 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8358 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8363 /* Line1 display AS-path, Aggregator */
8366 if (!attr
->aspath
->json
)
8367 aspath_str_update(attr
->aspath
, true);
8368 json_object_lock(attr
->aspath
->json
);
8369 json_object_object_add(json_path
, "aspath",
8370 attr
->aspath
->json
);
8372 if (attr
->aspath
->segments
)
8373 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8375 vty_out(vty
, " Local");
8379 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8381 json_object_boolean_true_add(json_path
, "removed");
8383 vty_out(vty
, ", (removed)");
8386 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8388 json_object_boolean_true_add(json_path
, "stale");
8390 vty_out(vty
, ", (stale)");
8393 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8395 json_object_int_add(json_path
, "aggregatorAs",
8396 attr
->aggregator_as
);
8397 json_object_string_add(
8398 json_path
, "aggregatorId",
8399 inet_ntoa(attr
->aggregator_addr
));
8401 vty_out(vty
, ", (aggregated by %u %s)",
8402 attr
->aggregator_as
,
8403 inet_ntoa(attr
->aggregator_addr
));
8407 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8408 PEER_FLAG_REFLECTOR_CLIENT
)) {
8410 json_object_boolean_true_add(json_path
,
8411 "rxedFromRrClient");
8413 vty_out(vty
, ", (Received from a RR-client)");
8416 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8417 PEER_FLAG_RSERVER_CLIENT
)) {
8419 json_object_boolean_true_add(json_path
,
8420 "rxedFromRsClient");
8422 vty_out(vty
, ", (Received from a RS-client)");
8425 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8427 json_object_boolean_true_add(json_path
,
8428 "dampeningHistoryEntry");
8430 vty_out(vty
, ", (history entry)");
8431 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8433 json_object_boolean_true_add(json_path
,
8434 "dampeningSuppressed");
8436 vty_out(vty
, ", (suppressed due to dampening)");
8442 /* Line2 display Next-hop, Neighbor, Router-id */
8443 /* Display the nexthop */
8444 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8445 || bn
->p
.family
== AF_EVPN
)
8446 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8447 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8448 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8449 || safi
== SAFI_EVPN
) {
8451 json_object_string_add(
8452 json_nexthop_global
, "ip",
8453 inet_ntoa(attr
->mp_nexthop_global_in
));
8455 if (nexthop_hostname
)
8456 json_object_string_add(
8457 json_nexthop_global
, "hostname",
8464 attr
->mp_nexthop_global_in
));
8467 json_object_string_add(
8468 json_nexthop_global
, "ip",
8469 inet_ntoa(attr
->nexthop
));
8471 if (nexthop_hostname
)
8472 json_object_string_add(
8473 json_nexthop_global
, "hostname",
8479 : inet_ntoa(attr
->nexthop
));
8483 json_object_string_add(json_nexthop_global
, "afi",
8487 json_object_string_add(
8488 json_nexthop_global
, "ip",
8489 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8490 buf
, INET6_ADDRSTRLEN
));
8492 if (nexthop_hostname
)
8493 json_object_string_add(json_nexthop_global
,
8497 json_object_string_add(json_nexthop_global
, "afi",
8499 json_object_string_add(json_nexthop_global
, "scope",
8505 : inet_ntop(AF_INET6
,
8506 &attr
->mp_nexthop_global
,
8507 buf
, INET6_ADDRSTRLEN
));
8511 /* Display the IGP cost or 'inaccessible' */
8512 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8514 json_object_boolean_false_add(json_nexthop_global
,
8517 vty_out(vty
, " (inaccessible)");
8519 if (path
->extra
&& path
->extra
->igpmetric
) {
8521 json_object_int_add(json_nexthop_global
,
8523 path
->extra
->igpmetric
);
8525 vty_out(vty
, " (metric %u)",
8526 path
->extra
->igpmetric
);
8529 /* IGP cost is 0, display this only for json */
8532 json_object_int_add(json_nexthop_global
,
8537 json_object_boolean_true_add(json_nexthop_global
,
8541 /* Display peer "from" output */
8542 /* This path was originated locally */
8543 if (path
->peer
== bgp
->peer_self
) {
8545 if (safi
== SAFI_EVPN
8546 || (bn
->p
.family
== AF_INET
8547 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8549 json_object_string_add(json_peer
, "peerId",
8552 vty_out(vty
, " from 0.0.0.0 ");
8555 json_object_string_add(json_peer
, "peerId",
8558 vty_out(vty
, " from :: ");
8562 json_object_string_add(json_peer
, "routerId",
8563 inet_ntoa(bgp
->router_id
));
8565 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8568 /* We RXed this path from one of our peers */
8572 json_object_string_add(json_peer
, "peerId",
8573 sockunion2str(&path
->peer
->su
,
8576 json_object_string_add(json_peer
, "routerId",
8578 &path
->peer
->remote_id
,
8579 buf1
, sizeof(buf1
)));
8581 if (path
->peer
->hostname
)
8582 json_object_string_add(json_peer
, "hostname",
8583 path
->peer
->hostname
);
8585 if (path
->peer
->domainname
)
8586 json_object_string_add(json_peer
, "domainname",
8587 path
->peer
->domainname
);
8589 if (path
->peer
->conf_if
)
8590 json_object_string_add(json_peer
, "interface",
8591 path
->peer
->conf_if
);
8593 if (path
->peer
->conf_if
) {
8594 if (path
->peer
->hostname
8595 && bgp_flag_check(path
->peer
->bgp
,
8596 BGP_FLAG_SHOW_HOSTNAME
))
8597 vty_out(vty
, " from %s(%s)",
8598 path
->peer
->hostname
,
8599 path
->peer
->conf_if
);
8601 vty_out(vty
, " from %s",
8602 path
->peer
->conf_if
);
8604 if (path
->peer
->hostname
8605 && bgp_flag_check(path
->peer
->bgp
,
8606 BGP_FLAG_SHOW_HOSTNAME
))
8607 vty_out(vty
, " from %s(%s)",
8608 path
->peer
->hostname
,
8611 vty_out(vty
, " from %s",
8612 sockunion2str(&path
->peer
->su
,
8617 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8618 vty_out(vty
, " (%s)",
8619 inet_ntoa(attr
->originator_id
));
8621 vty_out(vty
, " (%s)",
8623 &path
->peer
->remote_id
, buf1
,
8629 * Note when vrfid of nexthop is different from that of prefix
8631 if (path
->extra
&& path
->extra
->bgp_orig
) {
8632 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8637 if (path
->extra
->bgp_orig
->inst_type
8638 == BGP_INSTANCE_TYPE_DEFAULT
)
8639 vn
= VRF_DEFAULT_NAME
;
8641 vn
= path
->extra
->bgp_orig
->name
;
8643 json_object_string_add(json_path
, "nhVrfName", vn
);
8645 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8646 json_object_int_add(json_path
, "nhVrfId", -1);
8648 json_object_int_add(json_path
, "nhVrfId",
8649 (int)nexthop_vrfid
);
8652 if (nexthop_vrfid
== VRF_UNKNOWN
)
8653 vty_out(vty
, " vrf ?");
8655 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8661 json_object_boolean_true_add(json_path
,
8662 "announceNexthopSelf");
8664 vty_out(vty
, " announce-nh-self");
8671 /* display the link-local nexthop */
8672 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8674 json_nexthop_ll
= json_object_new_object();
8675 json_object_string_add(
8676 json_nexthop_ll
, "ip",
8677 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8678 buf
, INET6_ADDRSTRLEN
));
8680 if (nexthop_hostname
)
8681 json_object_string_add(json_nexthop_ll
,
8685 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8686 json_object_string_add(json_nexthop_ll
, "scope",
8689 json_object_boolean_true_add(json_nexthop_ll
,
8692 if (!attr
->mp_nexthop_prefer_global
)
8693 json_object_boolean_true_add(json_nexthop_ll
,
8696 json_object_boolean_true_add(
8697 json_nexthop_global
, "used");
8699 vty_out(vty
, " (%s) %s\n",
8700 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8701 buf
, INET6_ADDRSTRLEN
),
8702 attr
->mp_nexthop_prefer_global
8707 /* If we do not have a link-local nexthop then we must flag the
8711 json_object_boolean_true_add(json_nexthop_global
,
8715 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8716 * Int/Ext/Local, Atomic, best */
8718 json_object_string_add(json_path
, "origin",
8719 bgp_origin_long_str
[attr
->origin
]);
8721 vty_out(vty
, " Origin %s",
8722 bgp_origin_long_str
[attr
->origin
]);
8724 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8727 * Adding "metric" field to match with
8728 * corresponding CLI. "med" will be
8729 * deprecated in future.
8731 json_object_int_add(json_path
, "med", attr
->med
);
8732 json_object_int_add(json_path
, "metric", attr
->med
);
8734 vty_out(vty
, ", metric %u", attr
->med
);
8737 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8739 json_object_int_add(json_path
, "localpref",
8742 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8745 if (attr
->weight
!= 0) {
8747 json_object_int_add(json_path
, "weight", attr
->weight
);
8749 vty_out(vty
, ", weight %u", attr
->weight
);
8752 if (attr
->tag
!= 0) {
8754 json_object_int_add(json_path
, "tag", attr
->tag
);
8756 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
8759 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8761 json_object_boolean_false_add(json_path
, "valid");
8763 vty_out(vty
, ", invalid");
8764 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8766 json_object_boolean_true_add(json_path
, "valid");
8768 vty_out(vty
, ", valid");
8771 if (path
->peer
!= bgp
->peer_self
) {
8772 if (path
->peer
->as
== path
->peer
->local_as
) {
8773 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
8775 json_object_string_add(
8779 vty_out(vty
, ", confed-internal");
8782 json_object_string_add(
8783 json_peer
, "type", "internal");
8785 vty_out(vty
, ", internal");
8788 if (bgp_confederation_peers_check(bgp
,
8791 json_object_string_add(
8795 vty_out(vty
, ", confed-external");
8798 json_object_string_add(
8799 json_peer
, "type", "external");
8801 vty_out(vty
, ", external");
8804 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8806 json_object_boolean_true_add(json_path
, "aggregated");
8807 json_object_boolean_true_add(json_path
, "local");
8809 vty_out(vty
, ", aggregated, local");
8811 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8813 json_object_boolean_true_add(json_path
, "sourced");
8815 vty_out(vty
, ", sourced");
8818 json_object_boolean_true_add(json_path
, "sourced");
8819 json_object_boolean_true_add(json_path
, "local");
8821 vty_out(vty
, ", sourced, local");
8825 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8827 json_object_boolean_true_add(json_path
,
8830 vty_out(vty
, ", atomic-aggregate");
8833 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8834 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8835 && bgp_path_info_mpath_count(path
))) {
8837 json_object_boolean_true_add(json_path
, "multipath");
8839 vty_out(vty
, ", multipath");
8842 // Mark the bestpath(s)
8843 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8844 first_as
= aspath_get_first_as(attr
->aspath
);
8848 json_bestpath
= json_object_new_object();
8849 json_object_int_add(json_bestpath
, "bestpathFromAs",
8853 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
8855 vty_out(vty
, ", bestpath-from-AS Local");
8859 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8862 json_bestpath
= json_object_new_object();
8863 json_object_boolean_true_add(json_bestpath
, "overall");
8864 json_object_string_add(
8865 json_bestpath
, "selectionReason",
8866 bgp_path_selection_reason2str(bn
->reason
));
8868 vty_out(vty
, ", best");
8869 vty_out(vty
, " (%s)",
8870 bgp_path_selection_reason2str(bn
->reason
));
8875 json_object_object_add(json_path
, "bestpath", json_bestpath
);
8880 /* Line 4 display Community */
8881 if (attr
->community
) {
8883 if (!attr
->community
->json
)
8884 community_str(attr
->community
, true);
8885 json_object_lock(attr
->community
->json
);
8886 json_object_object_add(json_path
, "community",
8887 attr
->community
->json
);
8889 vty_out(vty
, " Community: %s\n",
8890 attr
->community
->str
);
8894 /* Line 5 display Extended-community */
8895 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8897 json_ext_community
= json_object_new_object();
8898 json_object_string_add(json_ext_community
, "string",
8899 attr
->ecommunity
->str
);
8900 json_object_object_add(json_path
, "extendedCommunity",
8901 json_ext_community
);
8903 vty_out(vty
, " Extended Community: %s\n",
8904 attr
->ecommunity
->str
);
8908 /* Line 6 display Large community */
8909 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8911 if (!attr
->lcommunity
->json
)
8912 lcommunity_str(attr
->lcommunity
, true);
8913 json_object_lock(attr
->lcommunity
->json
);
8914 json_object_object_add(json_path
, "largeCommunity",
8915 attr
->lcommunity
->json
);
8917 vty_out(vty
, " Large Community: %s\n",
8918 attr
->lcommunity
->str
);
8922 /* Line 7 display Originator, Cluster-id */
8923 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8924 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8925 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8927 json_object_string_add(
8928 json_path
, "originatorId",
8929 inet_ntoa(attr
->originator_id
));
8931 vty_out(vty
, " Originator: %s",
8932 inet_ntoa(attr
->originator_id
));
8935 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8939 json_cluster_list
= json_object_new_object();
8940 json_cluster_list_list
=
8941 json_object_new_array();
8943 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8945 json_string
= json_object_new_string(
8946 inet_ntoa(attr
->cluster
8948 json_object_array_add(
8949 json_cluster_list_list
,
8954 * struct cluster_list does not have
8955 * "str" variable like aspath and community
8956 * do. Add this someday if someone asks
8958 * json_object_string_add(json_cluster_list,
8959 * "string", attr->cluster->str);
8961 json_object_object_add(json_cluster_list
,
8963 json_cluster_list_list
);
8964 json_object_object_add(json_path
, "clusterList",
8967 vty_out(vty
, ", Cluster list: ");
8969 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8972 inet_ntoa(attr
->cluster
8982 if (path
->extra
&& path
->extra
->damp_info
)
8983 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
8986 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8987 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
8988 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8991 json_object_int_add(json_path
, "remoteLabel", label
);
8993 vty_out(vty
, " Remote label: %d\n", label
);
8997 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8999 json_object_int_add(json_path
, "labelIndex",
9002 vty_out(vty
, " Label Index: %d\n",
9006 /* Line 8 display Addpath IDs */
9007 if (path
->addpath_rx_id
9008 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9010 json_object_int_add(json_path
, "addpathRxId",
9011 path
->addpath_rx_id
);
9013 /* Keep backwards compatibility with the old API
9014 * by putting TX All's ID in the old field
9016 json_object_int_add(
9017 json_path
, "addpathTxId",
9019 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9021 /* ... but create a specific field for each
9024 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9025 json_object_int_add(
9027 bgp_addpath_names(i
)->id_json_name
,
9028 path
->tx_addpath
.addpath_tx_id
[i
]);
9031 vty_out(vty
, " AddPath ID: RX %u, ",
9032 path
->addpath_rx_id
);
9034 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9038 /* If we used addpath to TX a non-bestpath we need to display
9039 * "Advertised to" on a path-by-path basis
9041 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9044 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9046 bgp_addpath_encode_tx(peer
, afi
, safi
);
9047 has_adj
= bgp_adj_out_lookup(
9049 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9050 &path
->tx_addpath
));
9052 if ((addpath_capable
&& has_adj
)
9053 || (!addpath_capable
&& has_adj
9054 && CHECK_FLAG(path
->flags
,
9055 BGP_PATH_SELECTED
))) {
9056 if (json_path
&& !json_adv_to
)
9057 json_adv_to
= json_object_new_object();
9059 route_vty_out_advertised_to(
9061 " Advertised to:", json_adv_to
);
9067 json_object_object_add(
9068 json_path
, "advertisedTo", json_adv_to
);
9077 /* Line 9 display Uptime */
9078 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9080 json_last_update
= json_object_new_object();
9081 json_object_int_add(json_last_update
, "epoch", tbuf
);
9082 json_object_string_add(json_last_update
, "string",
9084 json_object_object_add(json_path
, "lastUpdate",
9087 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9089 /* Line 10 display PMSI tunnel attribute, if present */
9090 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9092 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9093 PMSI_TNLTYPE_STR_DEFAULT
);
9096 json_pmsi
= json_object_new_object();
9097 json_object_string_add(json_pmsi
, "tunnelType", str
);
9098 json_object_int_add(json_pmsi
, "label",
9099 label2vni(&attr
->label
));
9100 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9102 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9103 str
, label2vni(&attr
->label
));
9106 /* We've constructed the json object for this path, add it to the json
9110 if (json_nexthop_global
|| json_nexthop_ll
) {
9111 json_nexthops
= json_object_new_array();
9113 if (json_nexthop_global
)
9114 json_object_array_add(json_nexthops
,
9115 json_nexthop_global
);
9117 if (json_nexthop_ll
)
9118 json_object_array_add(json_nexthops
,
9121 json_object_object_add(json_path
, "nexthops",
9125 json_object_object_add(json_path
, "peer", json_peer
);
9126 json_object_array_add(json_paths
, json_path
);
9130 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9131 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9132 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9134 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9135 const char *prefix_list_str
, afi_t afi
,
9136 safi_t safi
, enum bgp_show_type type
);
9137 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9138 const char *filter
, afi_t afi
, safi_t safi
,
9139 enum bgp_show_type type
);
9140 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9141 const char *rmap_str
, afi_t afi
, safi_t safi
,
9142 enum bgp_show_type type
);
9143 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9144 const char *com
, int exact
, afi_t afi
,
9146 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9147 const char *prefix
, afi_t afi
, safi_t safi
,
9148 enum bgp_show_type type
);
9149 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9150 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
9151 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9152 const char *comstr
, int exact
, afi_t afi
,
9153 safi_t safi
, bool use_json
);
9156 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9157 struct bgp_table
*table
, enum bgp_show_type type
,
9158 void *output_arg
, bool use_json
, char *rd
,
9159 int is_last
, unsigned long *output_cum
,
9160 unsigned long *total_cum
,
9161 unsigned long *json_header_depth
)
9163 struct bgp_path_info
*pi
;
9164 struct bgp_node
*rn
;
9167 unsigned long output_count
= 0;
9168 unsigned long total_count
= 0;
9171 json_object
*json_paths
= NULL
;
9174 if (output_cum
&& *output_cum
!= 0)
9177 if (use_json
&& !*json_header_depth
) {
9179 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9180 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9181 " \"localAS\": %u,\n \"routes\": { ",
9182 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9183 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9186 table
->version
, inet_ntoa(bgp
->router_id
),
9187 bgp
->default_local_pref
, bgp
->as
);
9188 *json_header_depth
= 2;
9190 vty_out(vty
, " \"routeDistinguishers\" : {");
9191 ++*json_header_depth
;
9195 if (use_json
&& rd
) {
9196 vty_out(vty
, " \"%s\" : { ", rd
);
9199 /* Start processing of routes. */
9200 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9201 pi
= bgp_node_get_bgp_path_info(rn
);
9207 json_paths
= json_object_new_array();
9211 for (; pi
; pi
= pi
->next
) {
9213 if (type
== bgp_show_type_flap_statistics
9214 || type
== bgp_show_type_flap_neighbor
9215 || type
== bgp_show_type_dampend_paths
9216 || type
== bgp_show_type_damp_neighbor
) {
9217 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9220 if (type
== bgp_show_type_regexp
) {
9221 regex_t
*regex
= output_arg
;
9223 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9227 if (type
== bgp_show_type_prefix_list
) {
9228 struct prefix_list
*plist
= output_arg
;
9230 if (prefix_list_apply(plist
, &rn
->p
)
9234 if (type
== bgp_show_type_filter_list
) {
9235 struct as_list
*as_list
= output_arg
;
9237 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9238 != AS_FILTER_PERMIT
)
9241 if (type
== bgp_show_type_route_map
) {
9242 struct route_map
*rmap
= output_arg
;
9243 struct bgp_path_info path
;
9244 struct attr dummy_attr
;
9245 route_map_result_t ret
;
9247 dummy_attr
= *pi
->attr
;
9249 path
.peer
= pi
->peer
;
9250 path
.attr
= &dummy_attr
;
9252 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9254 if (ret
== RMAP_DENYMATCH
)
9257 if (type
== bgp_show_type_neighbor
9258 || type
== bgp_show_type_flap_neighbor
9259 || type
== bgp_show_type_damp_neighbor
) {
9260 union sockunion
*su
= output_arg
;
9262 if (pi
->peer
== NULL
9263 || pi
->peer
->su_remote
== NULL
9264 || !sockunion_same(pi
->peer
->su_remote
, su
))
9267 if (type
== bgp_show_type_cidr_only
) {
9268 uint32_t destination
;
9270 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9271 if (IN_CLASSC(destination
)
9272 && rn
->p
.prefixlen
== 24)
9274 if (IN_CLASSB(destination
)
9275 && rn
->p
.prefixlen
== 16)
9277 if (IN_CLASSA(destination
)
9278 && rn
->p
.prefixlen
== 8)
9281 if (type
== bgp_show_type_prefix_longer
) {
9283 if (!prefix_match(p
, &rn
->p
))
9286 if (type
== bgp_show_type_community_all
) {
9287 if (!pi
->attr
->community
)
9290 if (type
== bgp_show_type_community
) {
9291 struct community
*com
= output_arg
;
9293 if (!pi
->attr
->community
9294 || !community_match(pi
->attr
->community
,
9298 if (type
== bgp_show_type_community_exact
) {
9299 struct community
*com
= output_arg
;
9301 if (!pi
->attr
->community
9302 || !community_cmp(pi
->attr
->community
, com
))
9305 if (type
== bgp_show_type_community_list
) {
9306 struct community_list
*list
= output_arg
;
9308 if (!community_list_match(pi
->attr
->community
,
9312 if (type
== bgp_show_type_community_list_exact
) {
9313 struct community_list
*list
= output_arg
;
9315 if (!community_list_exact_match(
9316 pi
->attr
->community
, list
))
9319 if (type
== bgp_show_type_lcommunity
) {
9320 struct lcommunity
*lcom
= output_arg
;
9322 if (!pi
->attr
->lcommunity
9323 || !lcommunity_match(pi
->attr
->lcommunity
,
9328 if (type
== bgp_show_type_lcommunity_exact
) {
9329 struct lcommunity
*lcom
= output_arg
;
9331 if (!pi
->attr
->lcommunity
9332 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9336 if (type
== bgp_show_type_lcommunity_list
) {
9337 struct community_list
*list
= output_arg
;
9339 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9344 == bgp_show_type_lcommunity_list_exact
) {
9345 struct community_list
*list
= output_arg
;
9347 if (!lcommunity_list_exact_match(
9348 pi
->attr
->lcommunity
, list
))
9351 if (type
== bgp_show_type_lcommunity_all
) {
9352 if (!pi
->attr
->lcommunity
)
9355 if (type
== bgp_show_type_dampend_paths
9356 || type
== bgp_show_type_damp_neighbor
) {
9357 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9358 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9362 if (!use_json
&& header
) {
9363 vty_out(vty
, "BGP table version is %" PRIu64
9364 ", local router ID is %s, vrf id ",
9366 inet_ntoa(bgp
->router_id
));
9367 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9368 vty_out(vty
, "%s", VRFID_NONE_STR
);
9370 vty_out(vty
, "%u", bgp
->vrf_id
);
9372 vty_out(vty
, "Default local pref %u, ",
9373 bgp
->default_local_pref
);
9374 vty_out(vty
, "local AS %u\n", bgp
->as
);
9375 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9376 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9377 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9378 if (type
== bgp_show_type_dampend_paths
9379 || type
== bgp_show_type_damp_neighbor
)
9380 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9381 else if (type
== bgp_show_type_flap_statistics
9382 || type
== bgp_show_type_flap_neighbor
)
9383 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9385 vty_out(vty
, BGP_SHOW_HEADER
);
9388 if (rd
!= NULL
&& !display
&& !output_count
) {
9391 "Route Distinguisher: %s\n",
9394 if (type
== bgp_show_type_dampend_paths
9395 || type
== bgp_show_type_damp_neighbor
)
9396 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9397 safi
, use_json
, json_paths
);
9398 else if (type
== bgp_show_type_flap_statistics
9399 || type
== bgp_show_type_flap_neighbor
)
9400 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9401 safi
, use_json
, json_paths
);
9403 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9415 if (p
->family
== AF_FLOWSPEC
) {
9416 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9418 bgp_fs_nlri_get_string((unsigned char *)
9419 p
->u
.prefix_flowspec
.ptr
,
9420 p
->u
.prefix_flowspec
9423 NLRI_STRING_FORMAT_MIN
,
9426 vty_out(vty
, "\"%s/%d\": ",
9428 p
->u
.prefix_flowspec
.prefixlen
);
9430 vty_out(vty
, ",\"%s/%d\": ",
9432 p
->u
.prefix_flowspec
.prefixlen
);
9434 prefix2str(p
, buf2
, sizeof(buf2
));
9436 vty_out(vty
, "\"%s\": ", buf2
);
9438 vty_out(vty
, ",\"%s\": ", buf2
);
9441 json_object_to_json_string(json_paths
));
9442 json_object_free(json_paths
);
9446 json_object_free(json_paths
);
9450 output_count
+= *output_cum
;
9451 *output_cum
= output_count
;
9454 total_count
+= *total_cum
;
9455 *total_cum
= total_count
;
9459 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9463 for (i
= 0; i
< *json_header_depth
; ++i
)
9464 vty_out(vty
, " } ");
9469 /* No route is displayed */
9470 if (output_count
== 0) {
9471 if (type
== bgp_show_type_normal
)
9473 "No BGP prefixes displayed, %ld exist\n",
9477 "\nDisplayed %ld routes and %ld total paths\n",
9478 output_count
, total_count
);
9485 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9486 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9487 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9489 struct bgp_node
*rn
, *next
;
9490 unsigned long output_cum
= 0;
9491 unsigned long total_cum
= 0;
9492 unsigned long json_header_depth
= 0;
9493 struct bgp_table
*itable
;
9496 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9498 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9499 next
= bgp_route_next(rn
);
9500 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9503 itable
= bgp_node_get_bgp_table_info(rn
);
9504 if (itable
!= NULL
) {
9505 struct prefix_rd prd
;
9506 char rd
[RD_ADDRSTRLEN
];
9508 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9509 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9510 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9511 use_json
, rd
, next
== NULL
, &output_cum
,
9512 &total_cum
, &json_header_depth
);
9518 if (output_cum
== 0)
9519 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9523 "\nDisplayed %ld routes and %ld total paths\n",
9524 output_cum
, total_cum
);
9528 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9529 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9531 struct bgp_table
*table
;
9532 unsigned long json_header_depth
= 0;
9535 bgp
= bgp_get_default();
9540 vty_out(vty
, "No BGP process is configured\n");
9542 vty_out(vty
, "{}\n");
9546 table
= bgp
->rib
[afi
][safi
];
9547 /* use MPLS and ENCAP specific shows until they are merged */
9548 if (safi
== SAFI_MPLS_VPN
) {
9549 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9550 output_arg
, use_json
);
9553 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9554 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9555 output_arg
, use_json
,
9558 /* labeled-unicast routes live in the unicast table */
9559 else if (safi
== SAFI_LABELED_UNICAST
)
9560 safi
= SAFI_UNICAST
;
9562 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9563 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9566 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9567 safi_t safi
, bool use_json
)
9569 struct listnode
*node
, *nnode
;
9572 bool route_output
= false;
9575 vty_out(vty
, "{\n");
9577 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9578 route_output
= true;
9581 vty_out(vty
, ",\n");
9585 vty_out(vty
, "\"%s\":",
9586 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9590 vty_out(vty
, "\nInstance %s:\n",
9591 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9595 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9600 vty_out(vty
, "}\n");
9601 else if (!route_output
)
9602 vty_out(vty
, "%% BGP instance not found\n");
9605 /* Header of detailed BGP route information */
9606 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9607 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9608 afi_t afi
, safi_t safi
, json_object
*json
)
9610 struct bgp_path_info
*pi
;
9613 struct listnode
*node
, *nnode
;
9614 char buf1
[RD_ADDRSTRLEN
];
9615 char buf2
[INET6_ADDRSTRLEN
];
9616 char buf3
[EVPN_ROUTE_STRLEN
];
9617 char prefix_str
[BUFSIZ
];
9622 int route_filter_translated_v4
= 0;
9623 int route_filter_v4
= 0;
9624 int route_filter_translated_v6
= 0;
9625 int route_filter_v6
= 0;
9628 int accept_own_nexthop
= 0;
9631 int no_advertise
= 0;
9635 int has_valid_label
= 0;
9636 mpls_label_t label
= 0;
9637 json_object
*json_adv_to
= NULL
;
9640 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9642 if (has_valid_label
)
9643 label
= label_pton(&rn
->local_label
);
9645 if (safi
== SAFI_EVPN
) {
9648 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9649 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9650 : "", prd
? ":" : "",
9651 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9652 buf3
, sizeof(buf3
)));
9654 json_object_string_add(json
, "rd",
9655 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9657 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9661 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9662 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9663 ? prefix_rd2str(prd
, buf1
,
9666 safi
== SAFI_MPLS_VPN
? ":" : "",
9667 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9672 json_object_string_add(json
, "prefix",
9673 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9676 if (has_valid_label
) {
9678 json_object_int_add(json
, "localLabel", label
);
9680 vty_out(vty
, "Local label: %d\n", label
);
9684 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9685 vty_out(vty
, "not allocated\n");
9687 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9689 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9691 if (pi
->extra
&& pi
->extra
->suppress
)
9694 if (pi
->attr
->community
== NULL
)
9697 no_advertise
+= community_include(
9698 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9699 no_export
+= community_include(pi
->attr
->community
,
9700 COMMUNITY_NO_EXPORT
);
9701 local_as
+= community_include(pi
->attr
->community
,
9702 COMMUNITY_LOCAL_AS
);
9703 accept_own
+= community_include(pi
->attr
->community
,
9704 COMMUNITY_ACCEPT_OWN
);
9705 route_filter_translated_v4
+= community_include(
9706 pi
->attr
->community
,
9707 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9708 route_filter_translated_v6
+= community_include(
9709 pi
->attr
->community
,
9710 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9711 route_filter_v4
+= community_include(
9712 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9713 route_filter_v6
+= community_include(
9714 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9715 llgr_stale
+= community_include(pi
->attr
->community
,
9716 COMMUNITY_LLGR_STALE
);
9717 no_llgr
+= community_include(pi
->attr
->community
,
9719 accept_own_nexthop
+=
9720 community_include(pi
->attr
->community
,
9721 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9722 blackhole
+= community_include(pi
->attr
->community
,
9723 COMMUNITY_BLACKHOLE
);
9724 no_peer
+= community_include(pi
->attr
->community
,
9730 vty_out(vty
, "Paths: (%d available", count
);
9732 vty_out(vty
, ", best #%d", best
);
9733 if (safi
== SAFI_UNICAST
) {
9734 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9735 vty_out(vty
, ", table %s",
9738 vty_out(vty
, ", vrf %s",
9742 vty_out(vty
, ", no best path");
9746 ", accept own local route exported and imported in different VRF");
9747 else if (route_filter_translated_v4
)
9749 ", mark translated RTs for VPNv4 route filtering");
9750 else if (route_filter_v4
)
9752 ", attach RT as-is for VPNv4 route filtering");
9753 else if (route_filter_translated_v6
)
9755 ", mark translated RTs for VPNv6 route filtering");
9756 else if (route_filter_v6
)
9758 ", attach RT as-is for VPNv6 route filtering");
9759 else if (llgr_stale
)
9761 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9764 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9765 else if (accept_own_nexthop
)
9767 ", accept local nexthop");
9769 vty_out(vty
, ", inform peer to blackhole prefix");
9771 vty_out(vty
, ", not advertised to EBGP peer");
9772 else if (no_advertise
)
9773 vty_out(vty
, ", not advertised to any peer");
9775 vty_out(vty
, ", not advertised outside local AS");
9778 ", inform EBGP peer not to advertise to their EBGP peers");
9782 ", Advertisements suppressed by an aggregate.");
9783 vty_out(vty
, ")\n");
9786 /* If we are not using addpath then we can display Advertised to and
9788 * show what peers we advertised the bestpath to. If we are using
9790 * though then we must display Advertised to on a path-by-path basis. */
9791 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9792 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9793 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9794 if (json
&& !json_adv_to
)
9795 json_adv_to
= json_object_new_object();
9797 route_vty_out_advertised_to(
9799 " Advertised to non peer-group peers:\n ",
9806 json_object_object_add(json
, "advertisedTo",
9811 vty_out(vty
, " Not advertised to any peer");
9817 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
9818 struct bgp_node
*bgp_node
, struct vty
*vty
,
9819 struct bgp
*bgp
, afi_t afi
,
9820 safi_t safi
, json_object
*json
,
9821 enum bgp_path_type pathtype
, int *display
)
9823 struct bgp_path_info
*pi
;
9825 char rdbuf
[RD_ADDRSTRLEN
];
9826 json_object
*json_header
= NULL
;
9827 json_object
*json_paths
= NULL
;
9829 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
9832 if (json
&& !json_paths
) {
9833 /* Instantiate json_paths only if path is valid */
9834 json_paths
= json_object_new_array();
9836 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
9837 json_header
= json_object_new_object();
9843 route_vty_out_detail_header(
9844 vty
, bgp
, bgp_node
, pfx_rd
,
9845 AFI_IP
, safi
, json_header
);
9850 if (pathtype
== BGP_PATH_SHOW_ALL
9851 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9852 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
9853 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9854 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
9855 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
9856 route_vty_out_detail(vty
, bgp
, bgp_node
,
9861 if (json
&& json_paths
) {
9862 json_object_object_add(json_header
, "paths", json_paths
);
9865 json_object_object_add(json
, rdbuf
, json_header
);
9869 /* Display specified route of BGP table. */
9870 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9871 struct bgp_table
*rib
, const char *ip_str
,
9872 afi_t afi
, safi_t safi
,
9873 struct prefix_rd
*prd
, int prefix_check
,
9874 enum bgp_path_type pathtype
, bool use_json
)
9878 struct prefix match
;
9879 struct bgp_node
*rn
;
9880 struct bgp_node
*rm
;
9881 struct bgp_table
*table
;
9882 json_object
*json
= NULL
;
9883 json_object
*json_paths
= NULL
;
9885 /* Check IP address argument. */
9886 ret
= str2prefix(ip_str
, &match
);
9888 vty_out(vty
, "address is malformed\n");
9892 match
.family
= afi2family(afi
);
9895 json
= json_object_new_object();
9897 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
9898 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9899 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9901 table
= bgp_node_get_bgp_table_info(rn
);
9905 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9909 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9910 bgp_unlock_node(rm
);
9914 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9915 vty
, bgp
, afi
, safi
, json
,
9916 pathtype
, &display
);
9918 bgp_unlock_node(rm
);
9920 } else if (safi
== SAFI_EVPN
) {
9921 struct bgp_node
*longest_pfx
;
9922 bool is_exact_pfxlen_match
= FALSE
;
9924 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9925 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9927 table
= bgp_node_get_bgp_table_info(rn
);
9932 is_exact_pfxlen_match
= FALSE
;
9934 * Search through all the prefixes for a match. The
9935 * pfx's are enumerated in ascending order of pfxlens.
9936 * So, the last pfx match is the longest match. Set
9937 * is_exact_pfxlen_match when we get exact pfxlen match
9939 for (rm
= bgp_table_top(table
); rm
;
9940 rm
= bgp_route_next(rm
)) {
9942 * Get prefixlen of the ip-prefix within type5
9945 if (evpn_type5_prefix_match(&rm
->p
,
9946 &match
) && rm
->info
) {
9949 bgp_evpn_get_type5_prefixlen(&rm
->p
);
9950 if (type5_pfxlen
== match
.prefixlen
) {
9951 is_exact_pfxlen_match
= TRUE
;
9952 bgp_unlock_node(rm
);
9961 if (prefix_check
&& !is_exact_pfxlen_match
)
9967 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9968 vty
, bgp
, afi
, safi
, json
,
9969 pathtype
, &display
);
9971 bgp_unlock_node(rm
);
9973 } else if (safi
== SAFI_FLOWSPEC
) {
9975 json_paths
= json_object_new_array();
9977 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9978 &match
, prefix_check
,
9982 if (use_json
&& display
)
9983 json_object_object_add(json
, "paths", json_paths
);
9985 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9987 || rn
->p
.prefixlen
== match
.prefixlen
) {
9988 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
9990 pathtype
, &display
);
9993 bgp_unlock_node(rn
);
9998 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9999 json
, JSON_C_TO_STRING_PRETTY
|
10000 JSON_C_TO_STRING_NOSLASHESCAPE
));
10001 json_object_free(json
);
10004 vty_out(vty
, "%% Network not in table\n");
10005 return CMD_WARNING
;
10009 return CMD_SUCCESS
;
10012 /* Display specified route of Main RIB */
10013 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10014 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10015 int prefix_check
, enum bgp_path_type pathtype
,
10019 bgp
= bgp_get_default();
10022 vty_out(vty
, "No BGP process is configured\n");
10024 vty_out(vty
, "{}\n");
10025 return CMD_WARNING
;
10029 /* labeled-unicast routes live in the unicast table */
10030 if (safi
== SAFI_LABELED_UNICAST
)
10031 safi
= SAFI_UNICAST
;
10033 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10034 afi
, safi
, prd
, prefix_check
, pathtype
,
10038 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10039 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10040 safi_t safi
, bool uj
)
10042 struct lcommunity
*lcom
;
10048 b
= buffer_new(1024);
10049 for (i
= 0; i
< argc
; i
++) {
10051 buffer_putc(b
, ' ');
10053 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10055 buffer_putstr(b
, argv
[i
]->arg
);
10059 buffer_putc(b
, '\0');
10061 str
= buffer_getstr(b
);
10064 lcom
= lcommunity_str2com(str
);
10065 XFREE(MTYPE_TMP
, str
);
10067 vty_out(vty
, "%% Large-community malformed\n");
10068 return CMD_WARNING
;
10071 return bgp_show(vty
, bgp
, afi
, safi
,
10072 (exact
? bgp_show_type_lcommunity_exact
10073 : bgp_show_type_lcommunity
),
10077 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10078 const char *lcom
, bool exact
, afi_t afi
,
10079 safi_t safi
, bool uj
)
10081 struct community_list
*list
;
10083 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10084 LARGE_COMMUNITY_LIST_MASTER
);
10085 if (list
== NULL
) {
10086 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10088 return CMD_WARNING
;
10091 return bgp_show(vty
, bgp
, afi
, safi
,
10092 (exact
? bgp_show_type_lcommunity_list_exact
10093 : bgp_show_type_lcommunity_list
),
10097 DEFUN (show_ip_bgp_large_community_list
,
10098 show_ip_bgp_large_community_list_cmd
,
10099 "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]",
10103 BGP_INSTANCE_HELP_STR
10105 BGP_SAFI_WITH_LABEL_HELP_STR
10106 "Display routes matching the large-community-list\n"
10107 "large-community-list number\n"
10108 "large-community-list name\n"
10109 "Exact match of the large-communities\n"
10113 afi_t afi
= AFI_IP6
;
10114 safi_t safi
= SAFI_UNICAST
;
10116 bool exact_match
= 0;
10118 if (argv_find(argv
, argc
, "ip", &idx
))
10120 if (argv_find(argv
, argc
, "view", &idx
)
10121 || argv_find(argv
, argc
, "vrf", &idx
))
10122 vrf
= argv
[++idx
]->arg
;
10123 if (argv_find(argv
, argc
, "ipv4", &idx
)
10124 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10125 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10126 if (argv_find(argv
, argc
, "unicast", &idx
)
10127 || argv_find(argv
, argc
, "multicast", &idx
))
10128 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10131 bool uj
= use_json(argc
, argv
);
10133 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10135 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10136 return CMD_WARNING
;
10139 argv_find(argv
, argc
, "large-community-list", &idx
);
10141 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10143 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10146 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10147 exact_match
, afi
, safi
, uj
);
10149 DEFUN (show_ip_bgp_large_community
,
10150 show_ip_bgp_large_community_cmd
,
10151 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10155 BGP_INSTANCE_HELP_STR
10157 BGP_SAFI_WITH_LABEL_HELP_STR
10158 "Display routes matching the large-communities\n"
10159 "List of large-community numbers\n"
10160 "Exact match of the large-communities\n"
10164 afi_t afi
= AFI_IP6
;
10165 safi_t safi
= SAFI_UNICAST
;
10167 bool exact_match
= 0;
10169 if (argv_find(argv
, argc
, "ip", &idx
))
10171 if (argv_find(argv
, argc
, "view", &idx
)
10172 || argv_find(argv
, argc
, "vrf", &idx
))
10173 vrf
= argv
[++idx
]->arg
;
10174 if (argv_find(argv
, argc
, "ipv4", &idx
)
10175 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10176 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10177 if (argv_find(argv
, argc
, "unicast", &idx
)
10178 || argv_find(argv
, argc
, "multicast", &idx
))
10179 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10182 bool uj
= use_json(argc
, argv
);
10184 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10186 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10187 return CMD_WARNING
;
10190 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10191 if (argv_find(argv
, argc
, "exact-match", &idx
))
10193 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10194 exact_match
, afi
, safi
, uj
);
10196 return bgp_show(vty
, bgp
, afi
, safi
,
10197 bgp_show_type_lcommunity_all
, NULL
, uj
);
10200 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10204 /* BGP route print out function without JSON */
10205 DEFUN (show_ip_bgp
,
10207 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10208 <dampening <parameters>\
10213 |community-list <(1-500)|WORD> [exact-match]\
10214 |A.B.C.D/M longer-prefixes\
10215 |X:X::X:X/M longer-prefixes\
10220 BGP_INSTANCE_HELP_STR
10222 BGP_SAFI_WITH_LABEL_HELP_STR
10223 "Display detailed information about dampening\n"
10224 "Display detail of configured dampening parameters\n"
10225 "Display routes matching the route-map\n"
10226 "A route-map to match on\n"
10227 "Display routes conforming to the prefix-list\n"
10228 "Prefix-list name\n"
10229 "Display routes conforming to the filter-list\n"
10230 "Regular expression access list name\n"
10231 "BGP RIB advertisement statistics\n"
10232 "Display routes matching the community-list\n"
10233 "community-list number\n"
10234 "community-list name\n"
10235 "Exact match of the communities\n"
10237 "Display route and more specific routes\n"
10239 "Display route and more specific routes\n")
10241 afi_t afi
= AFI_IP6
;
10242 safi_t safi
= SAFI_UNICAST
;
10243 int exact_match
= 0;
10244 struct bgp
*bgp
= NULL
;
10247 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10250 return CMD_WARNING
;
10252 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10253 if (argv_find(argv
, argc
, "parameters", &idx
))
10254 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10257 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10258 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10259 safi
, bgp_show_type_prefix_list
);
10261 if (argv_find(argv
, argc
, "filter-list", &idx
))
10262 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10263 safi
, bgp_show_type_filter_list
);
10265 if (argv_find(argv
, argc
, "statistics", &idx
))
10266 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10268 if (argv_find(argv
, argc
, "route-map", &idx
))
10269 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10270 safi
, bgp_show_type_route_map
);
10272 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10273 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10274 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10276 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10277 exact_match
, afi
, safi
);
10279 /* prefix-longer */
10280 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10281 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10282 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10284 bgp_show_type_prefix_longer
);
10286 return CMD_WARNING
;
10289 /* BGP route print out function with JSON */
10290 DEFUN (show_ip_bgp_json
,
10291 show_ip_bgp_json_cmd
,
10292 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10294 |dampening <flap-statistics|dampened-paths>\
10295 |community [AA:NN|local-AS|no-advertise|no-export\
10296 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10297 |accept-own|accept-own-nexthop|route-filter-v6\
10298 |route-filter-v4|route-filter-translated-v6\
10299 |route-filter-translated-v4] [exact-match]\
10304 BGP_INSTANCE_HELP_STR
10306 BGP_SAFI_WITH_LABEL_HELP_STR
10307 "Display only routes with non-natural netmasks\n"
10308 "Display detailed information about dampening\n"
10309 "Display flap statistics of routes\n"
10310 "Display paths suppressed due to dampening\n"
10311 "Display routes matching the communities\n"
10313 "Do not send outside local AS (well-known community)\n"
10314 "Do not advertise to any peer (well-known community)\n"
10315 "Do not export to next AS (well-known community)\n"
10316 "Graceful shutdown (well-known community)\n"
10317 "Do not export to any peer (well-known community)\n"
10318 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10319 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10320 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10321 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10322 "Should accept VPN route with local nexthop (well-known community)\n"
10323 "RT VPNv6 route filtering (well-known community)\n"
10324 "RT VPNv4 route filtering (well-known community)\n"
10325 "RT translated VPNv6 route filtering (well-known community)\n"
10326 "RT translated VPNv4 route filtering (well-known community)\n"
10327 "Exact match of the communities\n"
10330 afi_t afi
= AFI_IP6
;
10331 safi_t safi
= SAFI_UNICAST
;
10332 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10333 struct bgp
*bgp
= NULL
;
10335 int exact_match
= 0;
10336 bool uj
= use_json(argc
, argv
);
10341 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10344 return CMD_WARNING
;
10346 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10347 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10350 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10351 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10352 return bgp_show(vty
, bgp
, afi
, safi
,
10353 bgp_show_type_dampend_paths
, NULL
, uj
);
10354 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10355 return bgp_show(vty
, bgp
, afi
, safi
,
10356 bgp_show_type_flap_statistics
, NULL
,
10360 if (argv_find(argv
, argc
, "community", &idx
)) {
10361 char *maybecomm
= NULL
;
10362 char *community
= NULL
;
10364 if (idx
+ 1 < argc
) {
10365 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10366 maybecomm
= argv
[idx
+ 1]->arg
;
10368 maybecomm
= argv
[idx
+ 1]->text
;
10371 if (maybecomm
&& !strmatch(maybecomm
, "json")
10372 && !strmatch(maybecomm
, "exact-match"))
10373 community
= maybecomm
;
10375 if (argv_find(argv
, argc
, "exact-match", &idx
))
10379 return bgp_show_community(vty
, bgp
, community
,
10380 exact_match
, afi
, safi
, uj
);
10382 return (bgp_show(vty
, bgp
, afi
, safi
,
10383 bgp_show_type_community_all
, NULL
,
10387 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10390 DEFUN (show_ip_bgp_route
,
10391 show_ip_bgp_route_cmd
,
10392 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10393 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10397 BGP_INSTANCE_HELP_STR
10399 BGP_SAFI_WITH_LABEL_HELP_STR
10400 "Network in the BGP routing table to display\n"
10402 "Network in the BGP routing table to display\n"
10404 "Display only the bestpath\n"
10405 "Display only multipaths\n"
10408 int prefix_check
= 0;
10410 afi_t afi
= AFI_IP6
;
10411 safi_t safi
= SAFI_UNICAST
;
10412 char *prefix
= NULL
;
10413 struct bgp
*bgp
= NULL
;
10414 enum bgp_path_type path_type
;
10415 bool uj
= use_json(argc
, argv
);
10419 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10422 return CMD_WARNING
;
10426 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10427 return CMD_WARNING
;
10430 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10431 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10432 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10434 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10435 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10438 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10439 && afi
!= AFI_IP6
) {
10441 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10442 return CMD_WARNING
;
10444 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10445 && afi
!= AFI_IP
) {
10447 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10448 return CMD_WARNING
;
10451 prefix
= argv
[idx
]->arg
;
10453 /* [<bestpath|multipath>] */
10454 if (argv_find(argv
, argc
, "bestpath", &idx
))
10455 path_type
= BGP_PATH_SHOW_BESTPATH
;
10456 else if (argv_find(argv
, argc
, "multipath", &idx
))
10457 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10459 path_type
= BGP_PATH_SHOW_ALL
;
10461 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10465 DEFUN (show_ip_bgp_regexp
,
10466 show_ip_bgp_regexp_cmd
,
10467 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10471 BGP_INSTANCE_HELP_STR
10473 BGP_SAFI_WITH_LABEL_HELP_STR
10474 "Display routes matching the AS path regular expression\n"
10475 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10477 afi_t afi
= AFI_IP6
;
10478 safi_t safi
= SAFI_UNICAST
;
10479 struct bgp
*bgp
= NULL
;
10482 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10485 return CMD_WARNING
;
10487 // get index of regex
10488 argv_find(argv
, argc
, "regexp", &idx
);
10491 char *regstr
= argv_concat(argv
, argc
, idx
);
10492 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10493 bgp_show_type_regexp
);
10494 XFREE(MTYPE_TMP
, regstr
);
10498 DEFUN (show_ip_bgp_instance_all
,
10499 show_ip_bgp_instance_all_cmd
,
10500 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10504 BGP_INSTANCE_ALL_HELP_STR
10506 BGP_SAFI_WITH_LABEL_HELP_STR
10509 afi_t afi
= AFI_IP
;
10510 safi_t safi
= SAFI_UNICAST
;
10511 struct bgp
*bgp
= NULL
;
10513 bool uj
= use_json(argc
, argv
);
10518 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10521 return CMD_WARNING
;
10523 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10524 return CMD_SUCCESS
;
10527 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10528 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10533 if (!config_bgp_aspath_validate(regstr
)) {
10534 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10536 return CMD_WARNING_CONFIG_FAILED
;
10539 regex
= bgp_regcomp(regstr
);
10541 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10542 return CMD_WARNING
;
10545 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10546 bgp_regex_free(regex
);
10550 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10551 const char *prefix_list_str
, afi_t afi
,
10552 safi_t safi
, enum bgp_show_type type
)
10554 struct prefix_list
*plist
;
10556 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10557 if (plist
== NULL
) {
10558 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10560 return CMD_WARNING
;
10563 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10566 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10567 const char *filter
, afi_t afi
, safi_t safi
,
10568 enum bgp_show_type type
)
10570 struct as_list
*as_list
;
10572 as_list
= as_list_lookup(filter
);
10573 if (as_list
== NULL
) {
10574 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10576 return CMD_WARNING
;
10579 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10582 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10583 const char *rmap_str
, afi_t afi
, safi_t safi
,
10584 enum bgp_show_type type
)
10586 struct route_map
*rmap
;
10588 rmap
= route_map_lookup_by_name(rmap_str
);
10590 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10591 return CMD_WARNING
;
10594 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10597 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10598 const char *comstr
, int exact
, afi_t afi
,
10599 safi_t safi
, bool use_json
)
10601 struct community
*com
;
10604 com
= community_str2com(comstr
);
10606 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10607 return CMD_WARNING
;
10610 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10611 (exact
? bgp_show_type_community_exact
10612 : bgp_show_type_community
),
10614 community_free(&com
);
10619 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10620 const char *com
, int exact
, afi_t afi
,
10623 struct community_list
*list
;
10625 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10626 if (list
== NULL
) {
10627 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10628 return CMD_WARNING
;
10631 return bgp_show(vty
, bgp
, afi
, safi
,
10632 (exact
? bgp_show_type_community_list_exact
10633 : bgp_show_type_community_list
),
10637 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10638 const char *prefix
, afi_t afi
, safi_t safi
,
10639 enum bgp_show_type type
)
10646 ret
= str2prefix(prefix
, p
);
10648 vty_out(vty
, "%% Malformed Prefix\n");
10649 return CMD_WARNING
;
10652 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10658 BGP_STATS_MAXBITLEN
= 0,
10660 BGP_STATS_PREFIXES
,
10662 BGP_STATS_UNAGGREGATEABLE
,
10663 BGP_STATS_MAX_AGGREGATEABLE
,
10664 BGP_STATS_AGGREGATES
,
10666 BGP_STATS_ASPATH_COUNT
,
10667 BGP_STATS_ASPATH_MAXHOPS
,
10668 BGP_STATS_ASPATH_TOTHOPS
,
10669 BGP_STATS_ASPATH_MAXSIZE
,
10670 BGP_STATS_ASPATH_TOTSIZE
,
10671 BGP_STATS_ASN_HIGHEST
,
10675 static const char *const table_stats_strs
[] = {
10676 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10677 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10678 [BGP_STATS_RIB
] = "Total Advertisements",
10679 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10680 [BGP_STATS_MAX_AGGREGATEABLE
] =
10681 "Maximum aggregateable prefixes",
10682 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10683 [BGP_STATS_SPACE
] = "Address space advertised",
10684 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10685 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10686 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10687 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10688 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10689 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10690 [BGP_STATS_MAX
] = NULL
,
10693 struct bgp_table_stats
{
10694 struct bgp_table
*table
;
10695 unsigned long long counts
[BGP_STATS_MAX
];
10696 double total_space
;
10700 #define TALLY_SIGFIG 100000
10701 static unsigned long
10702 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10704 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10705 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10706 unsigned long ret
= newtot
/ count
;
10708 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10715 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10716 struct bgp_table_stats
*ts
, unsigned int space
)
10718 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10719 struct bgp_path_info
*pi
;
10724 if (!bgp_node_has_bgp_path_info_data(rn
))
10727 ts
->counts
[BGP_STATS_PREFIXES
]++;
10728 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10731 ts
->counts
[BGP_STATS_AVGPLEN
]
10732 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10733 ts
->counts
[BGP_STATS_AVGPLEN
],
10737 /* check if the prefix is included by any other announcements */
10738 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10739 prn
= bgp_node_parent_nolock(prn
);
10741 if (prn
== NULL
|| prn
== top
) {
10742 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10743 /* announced address space */
10745 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10746 } else if (bgp_node_has_bgp_path_info_data(prn
))
10747 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10750 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10751 ts
->counts
[BGP_STATS_RIB
]++;
10753 if (CHECK_FLAG(pi
->attr
->flag
,
10754 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
10755 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10757 /* as-path stats */
10758 if (pi
->attr
->aspath
) {
10759 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10760 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10761 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10763 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10765 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10766 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10768 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10769 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10771 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10772 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10774 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10775 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10776 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10778 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10779 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10780 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10783 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10784 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10789 static int bgp_table_stats_walker(struct thread
*t
)
10791 struct bgp_node
*rn
, *nrn
;
10792 struct bgp_node
*top
;
10793 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10794 unsigned int space
= 0;
10796 if (!(top
= bgp_table_top(ts
->table
)))
10799 switch (ts
->table
->afi
) {
10801 space
= IPV4_MAX_BITLEN
;
10804 space
= IPV6_MAX_BITLEN
;
10810 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10812 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10813 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10814 struct bgp_table
*table
;
10816 table
= bgp_node_get_bgp_table_info(rn
);
10820 top
= bgp_table_top(table
);
10821 for (nrn
= bgp_table_top(table
); nrn
;
10822 nrn
= bgp_route_next(nrn
))
10823 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10825 bgp_table_stats_rn(rn
, top
, ts
, space
);
10832 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10835 struct bgp_table_stats ts
;
10838 if (!bgp
->rib
[afi
][safi
]) {
10839 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10841 return CMD_WARNING
;
10844 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
10846 /* labeled-unicast routes live in the unicast table */
10847 if (safi
== SAFI_LABELED_UNICAST
)
10848 safi
= SAFI_UNICAST
;
10850 memset(&ts
, 0, sizeof(ts
));
10851 ts
.table
= bgp
->rib
[afi
][safi
];
10852 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10854 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10855 if (!table_stats_strs
[i
])
10860 case BGP_STATS_ASPATH_AVGHOPS
:
10861 case BGP_STATS_ASPATH_AVGSIZE
:
10862 case BGP_STATS_AVGPLEN
:
10863 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10864 vty_out (vty
, "%12.2f",
10865 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10868 case BGP_STATS_ASPATH_TOTHOPS
:
10869 case BGP_STATS_ASPATH_TOTSIZE
:
10870 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10871 vty_out(vty
, "%12.2f",
10873 ? (float)ts
.counts
[i
]
10875 [BGP_STATS_ASPATH_COUNT
]
10878 case BGP_STATS_TOTPLEN
:
10879 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10880 vty_out(vty
, "%12.2f",
10882 ? (float)ts
.counts
[i
]
10884 [BGP_STATS_PREFIXES
]
10887 case BGP_STATS_SPACE
:
10888 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10889 vty_out(vty
, "%12g\n", ts
.total_space
);
10891 if (afi
== AFI_IP6
) {
10892 vty_out(vty
, "%30s: ", "/32 equivalent ");
10893 vty_out(vty
, "%12g\n",
10894 ts
.total_space
* pow(2.0, -128 + 32));
10895 vty_out(vty
, "%30s: ", "/48 equivalent ");
10896 vty_out(vty
, "%12g\n",
10897 ts
.total_space
* pow(2.0, -128 + 48));
10899 vty_out(vty
, "%30s: ", "% announced ");
10900 vty_out(vty
, "%12.2f\n",
10901 ts
.total_space
* 100. * pow(2.0, -32));
10902 vty_out(vty
, "%30s: ", "/8 equivalent ");
10903 vty_out(vty
, "%12.2f\n",
10904 ts
.total_space
* pow(2.0, -32 + 8));
10905 vty_out(vty
, "%30s: ", "/24 equivalent ");
10906 vty_out(vty
, "%12.2f\n",
10907 ts
.total_space
* pow(2.0, -32 + 24));
10911 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10912 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10915 vty_out(vty
, "\n");
10917 return CMD_SUCCESS
;
10929 PCOUNT_PFCNT
, /* the figure we display to users */
10933 static const char *const pcount_strs
[] = {
10934 [PCOUNT_ADJ_IN
] = "Adj-in",
10935 [PCOUNT_DAMPED
] = "Damped",
10936 [PCOUNT_REMOVED
] = "Removed",
10937 [PCOUNT_HISTORY
] = "History",
10938 [PCOUNT_STALE
] = "Stale",
10939 [PCOUNT_VALID
] = "Valid",
10940 [PCOUNT_ALL
] = "All RIB",
10941 [PCOUNT_COUNTED
] = "PfxCt counted",
10942 [PCOUNT_PFCNT
] = "Useable",
10943 [PCOUNT_MAX
] = NULL
,
10946 struct peer_pcounts
{
10947 unsigned int count
[PCOUNT_MAX
];
10948 const struct peer
*peer
;
10949 const struct bgp_table
*table
;
10953 static void bgp_peer_count_proc(struct bgp_node
*rn
,
10954 struct peer_pcounts
*pc
)
10956 const struct bgp_adj_in
*ain
;
10957 const struct bgp_path_info
*pi
;
10958 const struct peer
*peer
= pc
->peer
;
10960 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10961 if (ain
->peer
== peer
)
10962 pc
->count
[PCOUNT_ADJ_IN
]++;
10964 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10966 if (pi
->peer
!= peer
)
10969 pc
->count
[PCOUNT_ALL
]++;
10971 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10972 pc
->count
[PCOUNT_DAMPED
]++;
10973 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10974 pc
->count
[PCOUNT_HISTORY
]++;
10975 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10976 pc
->count
[PCOUNT_REMOVED
]++;
10977 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10978 pc
->count
[PCOUNT_STALE
]++;
10979 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10980 pc
->count
[PCOUNT_VALID
]++;
10981 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10982 pc
->count
[PCOUNT_PFCNT
]++;
10984 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10985 pc
->count
[PCOUNT_COUNTED
]++;
10986 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10988 EC_LIB_DEVELOPMENT
,
10989 "Attempting to count but flags say it is unusable");
10991 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10993 EC_LIB_DEVELOPMENT
,
10994 "Not counted but flags say we should");
10999 static int bgp_peer_count_walker(struct thread
*t
)
11001 struct bgp_node
*rn
, *rm
;
11002 const struct bgp_table
*table
;
11003 struct peer_pcounts
*pc
= THREAD_ARG(t
);
11005 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
11006 || pc
->safi
== SAFI_EVPN
) {
11007 /* Special handling for 2-level routing tables. */
11008 for (rn
= bgp_table_top(pc
->table
); rn
;
11009 rn
= bgp_route_next(rn
)) {
11010 table
= bgp_node_get_bgp_table_info(rn
);
11012 for (rm
= bgp_table_top(table
); rm
;
11013 rm
= bgp_route_next(rm
))
11014 bgp_peer_count_proc(rm
, pc
);
11017 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
11018 bgp_peer_count_proc(rn
, pc
);
11023 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11024 safi_t safi
, bool use_json
)
11026 struct peer_pcounts pcounts
= {.peer
= peer
};
11028 json_object
*json
= NULL
;
11029 json_object
*json_loop
= NULL
;
11032 json
= json_object_new_object();
11033 json_loop
= json_object_new_object();
11036 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
11037 || !peer
->bgp
->rib
[afi
][safi
]) {
11039 json_object_string_add(
11041 "No such neighbor or address family");
11042 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11043 json_object_free(json
);
11045 vty_out(vty
, "%% No such neighbor or address family\n");
11047 return CMD_WARNING
;
11050 memset(&pcounts
, 0, sizeof(pcounts
));
11051 pcounts
.peer
= peer
;
11052 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11053 pcounts
.safi
= safi
;
11055 /* in-place call via thread subsystem so as to record execution time
11056 * stats for the thread-walk (i.e. ensure this can't be blamed on
11057 * on just vty_read()).
11059 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11062 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11063 json_object_string_add(json
, "multiProtocol",
11064 get_afi_safi_str(afi
, safi
, true));
11065 json_object_int_add(json
, "pfxCounter",
11066 peer
->pcount
[afi
][safi
]);
11068 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11069 json_object_int_add(json_loop
, pcount_strs
[i
],
11072 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
11074 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11075 json_object_string_add(json
, "pfxctDriftFor",
11077 json_object_string_add(
11078 json
, "recommended",
11079 "Please report this bug, with the above command output");
11081 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11082 json
, JSON_C_TO_STRING_PRETTY
));
11083 json_object_free(json
);
11087 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
11088 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
11089 peer
->hostname
, peer
->host
,
11090 get_afi_safi_str(afi
, safi
, false));
11092 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11093 get_afi_safi_str(afi
, safi
, false));
11096 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
11097 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11099 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11100 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
11103 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11104 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
11106 "Please report this bug, with the above command output\n");
11110 return CMD_SUCCESS
;
11113 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11114 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11115 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11116 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11120 BGP_INSTANCE_HELP_STR
11123 "Detailed information on TCP and BGP neighbor connections\n"
11124 "Neighbor to display information about\n"
11125 "Neighbor to display information about\n"
11126 "Neighbor on BGP configured interface\n"
11127 "Display detailed prefix count information\n"
11130 afi_t afi
= AFI_IP6
;
11131 safi_t safi
= SAFI_UNICAST
;
11134 struct bgp
*bgp
= NULL
;
11135 bool uj
= use_json(argc
, argv
);
11140 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11143 return CMD_WARNING
;
11145 argv_find(argv
, argc
, "neighbors", &idx
);
11146 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11148 return CMD_WARNING
;
11150 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11153 #ifdef KEEP_OLD_VPN_COMMANDS
11154 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11155 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11156 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11161 "Display information about all VPNv4 NLRIs\n"
11162 "Detailed information on TCP and BGP neighbor connections\n"
11163 "Neighbor to display information about\n"
11164 "Neighbor to display information about\n"
11165 "Neighbor on BGP configured interface\n"
11166 "Display detailed prefix count information\n"
11171 bool uj
= use_json(argc
, argv
);
11173 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11175 return CMD_WARNING
;
11177 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11180 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11181 show_ip_bgp_vpn_all_route_prefix_cmd
,
11182 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11187 "Display information about all VPNv4 NLRIs\n"
11188 "Network in the BGP routing table to display\n"
11189 "Network in the BGP routing table to display\n"
11193 char *network
= NULL
;
11194 struct bgp
*bgp
= bgp_get_default();
11196 vty_out(vty
, "Can't find default instance\n");
11197 return CMD_WARNING
;
11200 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11201 network
= argv
[idx
]->arg
;
11202 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11203 network
= argv
[idx
]->arg
;
11205 vty_out(vty
, "Unable to figure out Network\n");
11206 return CMD_WARNING
;
11209 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11210 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11212 #endif /* KEEP_OLD_VPN_COMMANDS */
11214 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11215 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11216 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11221 "Network in the BGP routing table to display\n"
11222 "Network in the BGP routing table to display\n"
11223 "Network in the BGP routing table to display\n"
11224 "Network in the BGP routing table to display\n"
11228 char *network
= NULL
;
11229 int prefix_check
= 0;
11231 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11232 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11233 network
= argv
[idx
]->arg
;
11234 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11235 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11236 network
= argv
[idx
]->arg
;
11239 vty_out(vty
, "Unable to figure out Network\n");
11240 return CMD_WARNING
;
11242 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11243 prefix_check
, BGP_PATH_SHOW_ALL
,
11244 use_json(argc
, argv
));
11247 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11248 safi_t safi
, enum bgp_show_adj_route_type type
,
11249 const char *rmap_name
, bool use_json
,
11252 struct bgp_table
*table
;
11253 struct bgp_adj_in
*ain
;
11254 struct bgp_adj_out
*adj
;
11255 unsigned long output_count
;
11256 unsigned long filtered_count
;
11257 struct bgp_node
*rn
;
11263 struct update_subgroup
*subgrp
;
11264 json_object
*json_scode
= NULL
;
11265 json_object
*json_ocode
= NULL
;
11266 json_object
*json_ar
= NULL
;
11267 struct peer_af
*paf
;
11268 bool route_filtered
;
11271 json_scode
= json_object_new_object();
11272 json_ocode
= json_object_new_object();
11273 json_ar
= json_object_new_object();
11275 json_object_string_add(json_scode
, "suppressed", "s");
11276 json_object_string_add(json_scode
, "damped", "d");
11277 json_object_string_add(json_scode
, "history", "h");
11278 json_object_string_add(json_scode
, "valid", "*");
11279 json_object_string_add(json_scode
, "best", ">");
11280 json_object_string_add(json_scode
, "multipath", "=");
11281 json_object_string_add(json_scode
, "internal", "i");
11282 json_object_string_add(json_scode
, "ribFailure", "r");
11283 json_object_string_add(json_scode
, "stale", "S");
11284 json_object_string_add(json_scode
, "removed", "R");
11286 json_object_string_add(json_ocode
, "igp", "i");
11287 json_object_string_add(json_ocode
, "egp", "e");
11288 json_object_string_add(json_ocode
, "incomplete", "?");
11295 json_object_string_add(json
, "alert", "no BGP");
11296 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11297 json_object_free(json
);
11299 vty_out(vty
, "%% No bgp\n");
11303 /* labeled-unicast routes live in the unicast table */
11304 if (safi
== SAFI_LABELED_UNICAST
)
11305 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11307 table
= bgp
->rib
[afi
][safi
];
11309 output_count
= filtered_count
= 0;
11310 subgrp
= peer_subgroup(peer
, afi
, safi
);
11312 if (type
== bgp_show_adj_route_advertised
&& subgrp
11313 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11315 json_object_int_add(json
, "bgpTableVersion",
11317 json_object_string_add(json
, "bgpLocalRouterId",
11318 inet_ntoa(bgp
->router_id
));
11319 json_object_int_add(json
, "defaultLocPrf",
11320 bgp
->default_local_pref
);
11321 json_object_int_add(json
, "localAS", bgp
->as
);
11322 json_object_object_add(json
, "bgpStatusCodes",
11324 json_object_object_add(json
, "bgpOriginCodes",
11326 json_object_string_add(
11327 json
, "bgpOriginatingDefaultNetwork",
11328 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11330 vty_out(vty
, "BGP table version is %" PRIu64
11331 ", local router ID is %s, vrf id ",
11332 table
->version
, inet_ntoa(bgp
->router_id
));
11333 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11334 vty_out(vty
, "%s", VRFID_NONE_STR
);
11336 vty_out(vty
, "%u", bgp
->vrf_id
);
11337 vty_out(vty
, "\n");
11338 vty_out(vty
, "Default local pref %u, ",
11339 bgp
->default_local_pref
);
11340 vty_out(vty
, "local AS %u\n", bgp
->as
);
11341 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11342 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11343 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11345 vty_out(vty
, "Originating default network %s\n\n",
11346 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11351 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11352 if (type
== bgp_show_adj_route_received
11353 || type
== bgp_show_adj_route_filtered
) {
11354 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11355 if (ain
->peer
!= peer
)
11360 json_object_int_add(
11361 json
, "bgpTableVersion",
11363 json_object_string_add(
11365 "bgpLocalRouterId",
11368 json_object_int_add(json
,
11370 bgp
->default_local_pref
);
11371 json_object_int_add(json
,
11372 "localAS", bgp
->as
);
11373 json_object_object_add(
11374 json
, "bgpStatusCodes",
11376 json_object_object_add(
11377 json
, "bgpOriginCodes",
11381 "BGP table version is 0, local router ID is %s, vrf id ",
11384 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11390 vty_out(vty
, "\n");
11392 "Default local pref %u, ",
11393 bgp
->default_local_pref
);
11394 vty_out(vty
, "local AS %u\n",
11397 BGP_SHOW_SCODE_HEADER
);
11399 BGP_SHOW_NCODE_HEADER
);
11401 BGP_SHOW_OCODE_HEADER
);
11407 vty_out(vty
, BGP_SHOW_HEADER
);
11412 route_filtered
= false;
11414 /* Filter prefix using distribute list,
11415 * filter list or prefix list
11417 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11418 safi
)) == FILTER_DENY
)
11419 route_filtered
= true;
11421 /* Filter prefix using route-map */
11422 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11423 afi
, safi
, rmap_name
, NULL
, 0,
11426 if (type
== bgp_show_adj_route_filtered
&&
11427 !route_filtered
&& ret
!= RMAP_DENY
) {
11428 bgp_attr_undup(&attr
, ain
->attr
);
11432 if (type
== bgp_show_adj_route_received
&&
11433 (route_filtered
|| ret
== RMAP_DENY
))
11436 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11437 use_json
, json_ar
);
11438 bgp_attr_undup(&attr
, ain
->attr
);
11441 } else if (type
== bgp_show_adj_route_advertised
) {
11442 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11443 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11444 if (paf
->peer
!= peer
|| !adj
->attr
)
11449 json_object_int_add(
11453 json_object_string_add(
11455 "bgpLocalRouterId",
11458 json_object_int_add(
11459 json
, "defaultLocPrf",
11460 bgp
->default_local_pref
11462 json_object_int_add(
11465 json_object_object_add(
11469 json_object_object_add(
11475 "BGP table version is %" PRIu64
11476 ", local router ID is %s, vrf id ",
11489 vty_out(vty
, "\n");
11491 "Default local pref %u, ",
11492 bgp
->default_local_pref
11498 BGP_SHOW_SCODE_HEADER
);
11500 BGP_SHOW_NCODE_HEADER
);
11502 BGP_SHOW_OCODE_HEADER
);
11514 ret
= bgp_output_modifier(
11515 peer
, &rn
->p
, &attr
, afi
, safi
,
11518 if (ret
!= RMAP_DENY
) {
11519 route_vty_out_tmp(vty
, &rn
->p
,
11528 bgp_attr_undup(&attr
, adj
->attr
);
11534 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11535 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11536 json_object_int_add(json
, "filteredPrefixCounter",
11539 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11540 json
, JSON_C_TO_STRING_PRETTY
));
11541 json_object_free(json
);
11542 } else if (output_count
> 0) {
11543 if (filtered_count
> 0)
11545 "\nTotal number of prefixes %ld (%ld filtered)\n",
11546 output_count
, filtered_count
);
11548 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11553 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11554 safi_t safi
, enum bgp_show_adj_route_type type
,
11555 const char *rmap_name
, bool use_json
)
11557 json_object
*json
= NULL
;
11560 json
= json_object_new_object();
11562 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11564 json_object_string_add(
11566 "No such neighbor or address family");
11567 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11568 json_object_free(json
);
11570 vty_out(vty
, "%% No such neighbor or address family\n");
11572 return CMD_WARNING
;
11575 if ((type
== bgp_show_adj_route_received
11576 || type
== bgp_show_adj_route_filtered
)
11577 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11578 PEER_FLAG_SOFT_RECONFIG
)) {
11580 json_object_string_add(
11582 "Inbound soft reconfiguration not enabled");
11583 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11584 json_object_free(json
);
11587 "%% Inbound soft reconfiguration not enabled\n");
11589 return CMD_WARNING
;
11592 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11594 return CMD_SUCCESS
;
11597 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11598 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11599 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11600 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11604 BGP_INSTANCE_HELP_STR
11606 BGP_SAFI_WITH_LABEL_HELP_STR
11607 "Detailed information on TCP and BGP neighbor connections\n"
11608 "Neighbor to display information about\n"
11609 "Neighbor to display information about\n"
11610 "Neighbor on BGP configured interface\n"
11611 "Display the routes advertised to a BGP neighbor\n"
11612 "Display the received routes from neighbor\n"
11613 "Display the filtered routes received from neighbor\n"
11614 "Route-map to modify the attributes\n"
11615 "Name of the route map\n"
11618 afi_t afi
= AFI_IP6
;
11619 safi_t safi
= SAFI_UNICAST
;
11620 char *rmap_name
= NULL
;
11621 char *peerstr
= NULL
;
11622 struct bgp
*bgp
= NULL
;
11624 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11626 bool uj
= use_json(argc
, argv
);
11631 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11634 return CMD_WARNING
;
11636 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11637 argv_find(argv
, argc
, "neighbors", &idx
);
11638 peerstr
= argv
[++idx
]->arg
;
11640 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11642 return CMD_WARNING
;
11644 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11645 type
= bgp_show_adj_route_advertised
;
11646 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11647 type
= bgp_show_adj_route_received
;
11648 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11649 type
= bgp_show_adj_route_filtered
;
11651 if (argv_find(argv
, argc
, "route-map", &idx
))
11652 rmap_name
= argv
[++idx
]->arg
;
11654 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11657 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11658 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11659 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11665 "Address Family modifier\n"
11666 "Detailed information on TCP and BGP neighbor connections\n"
11667 "Neighbor to display information about\n"
11668 "Neighbor to display information about\n"
11669 "Neighbor on BGP configured interface\n"
11670 "Display information received from a BGP neighbor\n"
11671 "Display the prefixlist filter\n"
11674 afi_t afi
= AFI_IP6
;
11675 safi_t safi
= SAFI_UNICAST
;
11676 char *peerstr
= NULL
;
11679 union sockunion su
;
11685 /* show [ip] bgp */
11686 if (argv_find(argv
, argc
, "ip", &idx
))
11688 /* [<ipv4|ipv6> [unicast]] */
11689 if (argv_find(argv
, argc
, "ipv4", &idx
))
11691 if (argv_find(argv
, argc
, "ipv6", &idx
))
11693 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11694 argv_find(argv
, argc
, "neighbors", &idx
);
11695 peerstr
= argv
[++idx
]->arg
;
11697 bool uj
= use_json(argc
, argv
);
11699 ret
= str2sockunion(peerstr
, &su
);
11701 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11704 vty_out(vty
, "{}\n");
11707 "%% Malformed address or name: %s\n",
11709 return CMD_WARNING
;
11712 peer
= peer_lookup(NULL
, &su
);
11715 vty_out(vty
, "{}\n");
11717 vty_out(vty
, "No peer\n");
11718 return CMD_WARNING
;
11722 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11723 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11726 vty_out(vty
, "Address Family: %s\n",
11727 get_afi_safi_str(afi
, safi
, false));
11728 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11731 vty_out(vty
, "{}\n");
11733 vty_out(vty
, "No functional output\n");
11736 return CMD_SUCCESS
;
11739 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11740 afi_t afi
, safi_t safi
,
11741 enum bgp_show_type type
, bool use_json
)
11743 /* labeled-unicast routes live in the unicast table */
11744 if (safi
== SAFI_LABELED_UNICAST
)
11745 safi
= SAFI_UNICAST
;
11747 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11749 json_object
*json_no
= NULL
;
11750 json_no
= json_object_new_object();
11751 json_object_string_add(
11752 json_no
, "warning",
11753 "No such neighbor or address family");
11754 vty_out(vty
, "%s\n",
11755 json_object_to_json_string(json_no
));
11756 json_object_free(json_no
);
11758 vty_out(vty
, "%% No such neighbor or address family\n");
11759 return CMD_WARNING
;
11762 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11765 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11766 show_ip_bgp_flowspec_routes_detailed_cmd
,
11767 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11771 BGP_INSTANCE_HELP_STR
11774 "Detailed information on flowspec entries\n"
11777 afi_t afi
= AFI_IP
;
11778 safi_t safi
= SAFI_UNICAST
;
11779 struct bgp
*bgp
= NULL
;
11781 bool uj
= use_json(argc
, argv
);
11786 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11789 return CMD_WARNING
;
11791 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11794 DEFUN (show_ip_bgp_neighbor_routes
,
11795 show_ip_bgp_neighbor_routes_cmd
,
11796 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11797 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11801 BGP_INSTANCE_HELP_STR
11803 BGP_SAFI_WITH_LABEL_HELP_STR
11804 "Detailed information on TCP and BGP neighbor connections\n"
11805 "Neighbor to display information about\n"
11806 "Neighbor to display information about\n"
11807 "Neighbor on BGP configured interface\n"
11808 "Display flap statistics of the routes learned from neighbor\n"
11809 "Display the dampened routes received from neighbor\n"
11810 "Display routes learned from neighbor\n"
11813 char *peerstr
= NULL
;
11814 struct bgp
*bgp
= NULL
;
11815 afi_t afi
= AFI_IP6
;
11816 safi_t safi
= SAFI_UNICAST
;
11818 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11820 bool uj
= use_json(argc
, argv
);
11825 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11828 return CMD_WARNING
;
11830 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11831 argv_find(argv
, argc
, "neighbors", &idx
);
11832 peerstr
= argv
[++idx
]->arg
;
11834 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11836 return CMD_WARNING
;
11838 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11839 sh_type
= bgp_show_type_flap_neighbor
;
11840 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11841 sh_type
= bgp_show_type_damp_neighbor
;
11842 else if (argv_find(argv
, argc
, "routes", &idx
))
11843 sh_type
= bgp_show_type_neighbor
;
11845 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11848 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11850 struct bgp_distance
{
11851 /* Distance value for the IP source prefix. */
11854 /* Name of the access-list to be matched. */
11858 DEFUN (show_bgp_afi_vpn_rd_route
,
11859 show_bgp_afi_vpn_rd_route_cmd
,
11860 "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]",
11864 "Address Family modifier\n"
11865 "Display information for a route distinguisher\n"
11866 "Route Distinguisher\n"
11867 "Network in the BGP routing table to display\n"
11868 "Network in the BGP routing table to display\n"
11872 struct prefix_rd prd
;
11873 afi_t afi
= AFI_MAX
;
11876 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11877 vty_out(vty
, "%% Malformed Address Family\n");
11878 return CMD_WARNING
;
11881 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11883 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11884 return CMD_WARNING
;
11887 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11888 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11891 static struct bgp_distance
*bgp_distance_new(void)
11893 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11896 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11898 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11901 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11902 const char *ip_str
, const char *access_list_str
)
11909 struct bgp_node
*rn
;
11910 struct bgp_distance
*bdistance
;
11912 afi
= bgp_node_afi(vty
);
11913 safi
= bgp_node_safi(vty
);
11915 ret
= str2prefix(ip_str
, &p
);
11917 vty_out(vty
, "Malformed prefix\n");
11918 return CMD_WARNING_CONFIG_FAILED
;
11921 distance
= atoi(distance_str
);
11923 /* Get BGP distance node. */
11924 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11925 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11927 bgp_unlock_node(rn
);
11929 bdistance
= bgp_distance_new();
11930 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11933 /* Set distance value. */
11934 bdistance
->distance
= distance
;
11936 /* Reset access-list configuration. */
11937 if (bdistance
->access_list
) {
11938 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11939 bdistance
->access_list
= NULL
;
11941 if (access_list_str
)
11942 bdistance
->access_list
=
11943 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11945 return CMD_SUCCESS
;
11948 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11949 const char *ip_str
, const char *access_list_str
)
11956 struct bgp_node
*rn
;
11957 struct bgp_distance
*bdistance
;
11959 afi
= bgp_node_afi(vty
);
11960 safi
= bgp_node_safi(vty
);
11962 ret
= str2prefix(ip_str
, &p
);
11964 vty_out(vty
, "Malformed prefix\n");
11965 return CMD_WARNING_CONFIG_FAILED
;
11968 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11969 (struct prefix
*)&p
);
11971 vty_out(vty
, "Can't find specified prefix\n");
11972 return CMD_WARNING_CONFIG_FAILED
;
11975 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11976 distance
= atoi(distance_str
);
11978 if (bdistance
->distance
!= distance
) {
11979 vty_out(vty
, "Distance does not match configured\n");
11980 return CMD_WARNING_CONFIG_FAILED
;
11983 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11984 bgp_distance_free(bdistance
);
11986 bgp_node_set_bgp_path_info(rn
, NULL
);
11987 bgp_unlock_node(rn
);
11988 bgp_unlock_node(rn
);
11990 return CMD_SUCCESS
;
11993 /* Apply BGP information to distance method. */
11994 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11995 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11997 struct bgp_node
*rn
;
12000 struct bgp_distance
*bdistance
;
12001 struct access_list
*alist
;
12002 struct bgp_static
*bgp_static
;
12007 peer
= pinfo
->peer
;
12009 if (pinfo
->attr
->distance
)
12010 return pinfo
->attr
->distance
;
12012 /* Check source address. */
12013 sockunion2hostprefix(&peer
->su
, &q
);
12014 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
12016 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12017 bgp_unlock_node(rn
);
12019 if (bdistance
->access_list
) {
12020 alist
= access_list_lookup(afi
, bdistance
->access_list
);
12022 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
12023 return bdistance
->distance
;
12025 return bdistance
->distance
;
12028 /* Backdoor check. */
12029 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
12031 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12032 bgp_unlock_node(rn
);
12034 if (bgp_static
->backdoor
) {
12035 if (bgp
->distance_local
[afi
][safi
])
12036 return bgp
->distance_local
[afi
][safi
];
12038 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12042 if (peer
->sort
== BGP_PEER_EBGP
) {
12043 if (bgp
->distance_ebgp
[afi
][safi
])
12044 return bgp
->distance_ebgp
[afi
][safi
];
12045 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
12047 if (bgp
->distance_ibgp
[afi
][safi
])
12048 return bgp
->distance_ibgp
[afi
][safi
];
12049 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12053 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12054 * we should tell ZEBRA update the routes for a specific
12055 * AFI/SAFI to reflect changes in RIB.
12057 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
12059 safi_t update_safi
)
12064 FOREACH_AFI_SAFI (afi
, safi
) {
12065 if (!bgp_fibupd_safi(safi
))
12068 if (afi
!= update_afi
&& safi
!= update_safi
)
12071 if (BGP_DEBUG(zebra
, ZEBRA
))
12073 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12074 __func__
, afi
, safi
);
12075 bgp_zebra_announce_table(bgp
, afi
, safi
);
12079 DEFUN (bgp_distance
,
12081 "distance bgp (1-255) (1-255) (1-255)",
12082 "Define an administrative distance\n"
12084 "Distance for routes external to the AS\n"
12085 "Distance for routes internal to the AS\n"
12086 "Distance for local routes\n")
12088 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12089 int idx_number
= 2;
12090 int idx_number_2
= 3;
12091 int idx_number_3
= 4;
12092 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
12093 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
12094 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
12098 afi
= bgp_node_afi(vty
);
12099 safi
= bgp_node_safi(vty
);
12101 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
12102 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
12103 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
12104 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
12105 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
12106 bgp
->distance_local
[afi
][safi
] = distance_local
;
12107 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12109 return CMD_SUCCESS
;
12112 DEFUN (no_bgp_distance
,
12113 no_bgp_distance_cmd
,
12114 "no distance bgp [(1-255) (1-255) (1-255)]",
12116 "Define an administrative distance\n"
12118 "Distance for routes external to the AS\n"
12119 "Distance for routes internal to the AS\n"
12120 "Distance for local routes\n")
12122 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12126 afi
= bgp_node_afi(vty
);
12127 safi
= bgp_node_safi(vty
);
12129 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12130 || bgp
->distance_ibgp
[afi
][safi
] != 0
12131 || bgp
->distance_local
[afi
][safi
] != 0) {
12132 bgp
->distance_ebgp
[afi
][safi
] = 0;
12133 bgp
->distance_ibgp
[afi
][safi
] = 0;
12134 bgp
->distance_local
[afi
][safi
] = 0;
12135 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12137 return CMD_SUCCESS
;
12141 DEFUN (bgp_distance_source
,
12142 bgp_distance_source_cmd
,
12143 "distance (1-255) A.B.C.D/M",
12144 "Define an administrative distance\n"
12145 "Administrative distance\n"
12146 "IP source prefix\n")
12148 int idx_number
= 1;
12149 int idx_ipv4_prefixlen
= 2;
12150 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12151 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12152 return CMD_SUCCESS
;
12155 DEFUN (no_bgp_distance_source
,
12156 no_bgp_distance_source_cmd
,
12157 "no distance (1-255) A.B.C.D/M",
12159 "Define an administrative distance\n"
12160 "Administrative distance\n"
12161 "IP source prefix\n")
12163 int idx_number
= 2;
12164 int idx_ipv4_prefixlen
= 3;
12165 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12166 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12167 return CMD_SUCCESS
;
12170 DEFUN (bgp_distance_source_access_list
,
12171 bgp_distance_source_access_list_cmd
,
12172 "distance (1-255) A.B.C.D/M WORD",
12173 "Define an administrative distance\n"
12174 "Administrative distance\n"
12175 "IP source prefix\n"
12176 "Access list name\n")
12178 int idx_number
= 1;
12179 int idx_ipv4_prefixlen
= 2;
12181 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12182 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12183 return CMD_SUCCESS
;
12186 DEFUN (no_bgp_distance_source_access_list
,
12187 no_bgp_distance_source_access_list_cmd
,
12188 "no distance (1-255) A.B.C.D/M WORD",
12190 "Define an administrative distance\n"
12191 "Administrative distance\n"
12192 "IP source prefix\n"
12193 "Access list name\n")
12195 int idx_number
= 2;
12196 int idx_ipv4_prefixlen
= 3;
12198 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12199 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12200 return CMD_SUCCESS
;
12203 DEFUN (ipv6_bgp_distance_source
,
12204 ipv6_bgp_distance_source_cmd
,
12205 "distance (1-255) X:X::X:X/M",
12206 "Define an administrative distance\n"
12207 "Administrative distance\n"
12208 "IP source prefix\n")
12210 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12211 return CMD_SUCCESS
;
12214 DEFUN (no_ipv6_bgp_distance_source
,
12215 no_ipv6_bgp_distance_source_cmd
,
12216 "no distance (1-255) X:X::X:X/M",
12218 "Define an administrative distance\n"
12219 "Administrative distance\n"
12220 "IP source prefix\n")
12222 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12223 return CMD_SUCCESS
;
12226 DEFUN (ipv6_bgp_distance_source_access_list
,
12227 ipv6_bgp_distance_source_access_list_cmd
,
12228 "distance (1-255) X:X::X:X/M WORD",
12229 "Define an administrative distance\n"
12230 "Administrative distance\n"
12231 "IP source prefix\n"
12232 "Access list name\n")
12234 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12235 return CMD_SUCCESS
;
12238 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12239 no_ipv6_bgp_distance_source_access_list_cmd
,
12240 "no distance (1-255) X:X::X:X/M WORD",
12242 "Define an administrative distance\n"
12243 "Administrative distance\n"
12244 "IP source prefix\n"
12245 "Access list name\n")
12247 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12248 return CMD_SUCCESS
;
12251 DEFUN (bgp_damp_set
,
12253 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12254 "BGP Specific commands\n"
12255 "Enable route-flap dampening\n"
12256 "Half-life time for the penalty\n"
12257 "Value to start reusing a route\n"
12258 "Value to start suppressing a route\n"
12259 "Maximum duration to suppress a stable route\n")
12261 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12262 int idx_half_life
= 2;
12264 int idx_suppress
= 4;
12265 int idx_max_suppress
= 5;
12266 int half
= DEFAULT_HALF_LIFE
* 60;
12267 int reuse
= DEFAULT_REUSE
;
12268 int suppress
= DEFAULT_SUPPRESS
;
12269 int max
= 4 * half
;
12272 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12273 reuse
= atoi(argv
[idx_reuse
]->arg
);
12274 suppress
= atoi(argv
[idx_suppress
]->arg
);
12275 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12276 } else if (argc
== 3) {
12277 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12282 * These can't be 0 but our SA doesn't understand the
12283 * way our cli is constructed
12287 if (suppress
< reuse
) {
12289 "Suppress value cannot be less than reuse value \n");
12293 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12294 reuse
, suppress
, max
);
12297 DEFUN (bgp_damp_unset
,
12298 bgp_damp_unset_cmd
,
12299 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12301 "BGP Specific commands\n"
12302 "Enable route-flap dampening\n"
12303 "Half-life time for the penalty\n"
12304 "Value to start reusing a route\n"
12305 "Value to start suppressing a route\n"
12306 "Maximum duration to suppress a stable route\n")
12308 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12309 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12312 /* Display specified route of BGP table. */
12313 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12314 const char *ip_str
, afi_t afi
, safi_t safi
,
12315 struct prefix_rd
*prd
, int prefix_check
)
12318 struct prefix match
;
12319 struct bgp_node
*rn
;
12320 struct bgp_node
*rm
;
12321 struct bgp_path_info
*pi
;
12322 struct bgp_path_info
*pi_temp
;
12324 struct bgp_table
*table
;
12326 /* BGP structure lookup. */
12328 bgp
= bgp_lookup_by_name(view_name
);
12330 vty_out(vty
, "%% Can't find BGP instance %s\n",
12332 return CMD_WARNING
;
12335 bgp
= bgp_get_default();
12337 vty_out(vty
, "%% No BGP process is configured\n");
12338 return CMD_WARNING
;
12342 /* Check IP address argument. */
12343 ret
= str2prefix(ip_str
, &match
);
12345 vty_out(vty
, "%% address is malformed\n");
12346 return CMD_WARNING
;
12349 match
.family
= afi2family(afi
);
12351 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12352 || (safi
== SAFI_EVPN
)) {
12353 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12354 rn
= bgp_route_next(rn
)) {
12355 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12357 table
= bgp_node_get_bgp_table_info(rn
);
12360 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12364 || rm
->p
.prefixlen
== match
.prefixlen
) {
12365 pi
= bgp_node_get_bgp_path_info(rm
);
12367 if (pi
->extra
&& pi
->extra
->damp_info
) {
12368 pi_temp
= pi
->next
;
12369 bgp_damp_info_free(
12370 pi
->extra
->damp_info
,
12378 bgp_unlock_node(rm
);
12381 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12384 || rn
->p
.prefixlen
== match
.prefixlen
) {
12385 pi
= bgp_node_get_bgp_path_info(rn
);
12387 if (pi
->extra
&& pi
->extra
->damp_info
) {
12388 pi_temp
= pi
->next
;
12389 bgp_damp_info_free(
12390 pi
->extra
->damp_info
,
12398 bgp_unlock_node(rn
);
12402 return CMD_SUCCESS
;
12405 DEFUN (clear_ip_bgp_dampening
,
12406 clear_ip_bgp_dampening_cmd
,
12407 "clear ip bgp dampening",
12411 "Clear route flap dampening information\n")
12413 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
12414 return CMD_SUCCESS
;
12417 DEFUN (clear_ip_bgp_dampening_prefix
,
12418 clear_ip_bgp_dampening_prefix_cmd
,
12419 "clear ip bgp dampening A.B.C.D/M",
12423 "Clear route flap dampening information\n"
12426 int idx_ipv4_prefixlen
= 4;
12427 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12428 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12431 DEFUN (clear_ip_bgp_dampening_address
,
12432 clear_ip_bgp_dampening_address_cmd
,
12433 "clear ip bgp dampening A.B.C.D",
12437 "Clear route flap dampening information\n"
12438 "Network to clear damping information\n")
12441 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12442 SAFI_UNICAST
, NULL
, 0);
12445 DEFUN (clear_ip_bgp_dampening_address_mask
,
12446 clear_ip_bgp_dampening_address_mask_cmd
,
12447 "clear ip bgp dampening A.B.C.D A.B.C.D",
12451 "Clear route flap dampening information\n"
12452 "Network to clear damping information\n"
12456 int idx_ipv4_2
= 5;
12458 char prefix_str
[BUFSIZ
];
12460 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12463 vty_out(vty
, "%% Inconsistent address and mask\n");
12464 return CMD_WARNING
;
12467 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12471 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12473 struct vty
*vty
= arg
;
12474 struct peer
*peer
= bucket
->data
;
12475 char buf
[SU_ADDRSTRLEN
];
12477 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12478 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12481 DEFUN (show_bgp_peerhash
,
12482 show_bgp_peerhash_cmd
,
12483 "show bgp peerhash",
12486 "Display information about the BGP peerhash\n")
12488 struct list
*instances
= bm
->bgp
;
12489 struct listnode
*node
;
12492 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12493 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12494 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12498 return CMD_SUCCESS
;
12501 /* also used for encap safi */
12502 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12503 afi_t afi
, safi_t safi
)
12505 struct bgp_node
*prn
;
12506 struct bgp_node
*rn
;
12507 struct bgp_table
*table
;
12509 struct prefix_rd
*prd
;
12510 struct bgp_static
*bgp_static
;
12511 mpls_label_t label
;
12512 char buf
[SU_ADDRSTRLEN
];
12513 char rdbuf
[RD_ADDRSTRLEN
];
12515 /* Network configuration. */
12516 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12517 prn
= bgp_route_next(prn
)) {
12518 table
= bgp_node_get_bgp_table_info(prn
);
12522 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12523 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12524 if (bgp_static
== NULL
)
12528 prd
= (struct prefix_rd
*)&prn
->p
;
12530 /* "network" configuration display. */
12531 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12532 label
= decode_label(&bgp_static
->label
);
12534 vty_out(vty
, " network %s/%d rd %s",
12535 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12537 p
->prefixlen
, rdbuf
);
12538 if (safi
== SAFI_MPLS_VPN
)
12539 vty_out(vty
, " label %u", label
);
12541 if (bgp_static
->rmap
.name
)
12542 vty_out(vty
, " route-map %s",
12543 bgp_static
->rmap
.name
);
12545 if (bgp_static
->backdoor
)
12546 vty_out(vty
, " backdoor");
12548 vty_out(vty
, "\n");
12553 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12554 afi_t afi
, safi_t safi
)
12556 struct bgp_node
*prn
;
12557 struct bgp_node
*rn
;
12558 struct bgp_table
*table
;
12560 struct prefix_rd
*prd
;
12561 struct bgp_static
*bgp_static
;
12562 char buf
[PREFIX_STRLEN
* 2];
12563 char buf2
[SU_ADDRSTRLEN
];
12564 char rdbuf
[RD_ADDRSTRLEN
];
12566 /* Network configuration. */
12567 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12568 prn
= bgp_route_next(prn
)) {
12569 table
= bgp_node_get_bgp_table_info(prn
);
12573 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12574 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12575 if (bgp_static
== NULL
)
12578 char *macrouter
= NULL
;
12581 if (bgp_static
->router_mac
)
12582 macrouter
= prefix_mac2str(
12583 bgp_static
->router_mac
, NULL
, 0);
12584 if (bgp_static
->eth_s_id
)
12585 esi
= esi2str(bgp_static
->eth_s_id
);
12587 prd
= (struct prefix_rd
*)&prn
->p
;
12589 /* "network" configuration display. */
12590 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12591 if (p
->u
.prefix_evpn
.route_type
== 5) {
12592 char local_buf
[PREFIX_STRLEN
];
12593 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12594 struct prefix_evpn
*)p
)
12598 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12599 local_buf
, PREFIX_STRLEN
);
12600 sprintf(buf
, "%s/%u", local_buf
,
12601 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12603 prefix2str(p
, buf
, sizeof(buf
));
12606 if (bgp_static
->gatewayIp
.family
== AF_INET
12607 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12608 inet_ntop(bgp_static
->gatewayIp
.family
,
12609 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12612 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12614 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12615 decode_label(&bgp_static
->label
), esi
, buf2
,
12618 XFREE(MTYPE_TMP
, macrouter
);
12619 XFREE(MTYPE_TMP
, esi
);
12624 /* Configuration of static route announcement and aggregate
12626 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12629 struct bgp_node
*rn
;
12631 struct bgp_static
*bgp_static
;
12632 struct bgp_aggregate
*bgp_aggregate
;
12633 char buf
[SU_ADDRSTRLEN
];
12635 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12636 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12640 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12641 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12645 /* Network configuration. */
12646 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12647 rn
= bgp_route_next(rn
)) {
12648 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12649 if (bgp_static
== NULL
)
12654 vty_out(vty
, " network %s/%d",
12655 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12658 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12659 vty_out(vty
, " label-index %u",
12660 bgp_static
->label_index
);
12662 if (bgp_static
->rmap
.name
)
12663 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12665 if (bgp_static
->backdoor
)
12666 vty_out(vty
, " backdoor");
12668 vty_out(vty
, "\n");
12671 /* Aggregate-address configuration. */
12672 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12673 rn
= bgp_route_next(rn
)) {
12674 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12675 if (bgp_aggregate
== NULL
)
12680 vty_out(vty
, " aggregate-address %s/%d",
12681 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12684 if (bgp_aggregate
->as_set
)
12685 vty_out(vty
, " as-set");
12687 if (bgp_aggregate
->summary_only
)
12688 vty_out(vty
, " summary-only");
12690 if (bgp_aggregate
->rmap
.name
)
12691 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12693 vty_out(vty
, "\n");
12697 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12700 struct bgp_node
*rn
;
12701 struct bgp_distance
*bdistance
;
12703 /* Distance configuration. */
12704 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12705 && bgp
->distance_local
[afi
][safi
]
12706 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12707 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12708 || bgp
->distance_local
[afi
][safi
]
12709 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12710 vty_out(vty
, " distance bgp %d %d %d\n",
12711 bgp
->distance_ebgp
[afi
][safi
],
12712 bgp
->distance_ibgp
[afi
][safi
],
12713 bgp
->distance_local
[afi
][safi
]);
12716 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12717 rn
= bgp_route_next(rn
)) {
12718 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12719 if (bdistance
!= NULL
) {
12720 char buf
[PREFIX_STRLEN
];
12722 vty_out(vty
, " distance %d %s %s\n",
12723 bdistance
->distance
,
12724 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12725 bdistance
->access_list
? bdistance
->access_list
12731 /* Allocate routing table structure and install commands. */
12732 void bgp_route_init(void)
12737 /* Init BGP distance table. */
12738 FOREACH_AFI_SAFI (afi
, safi
)
12739 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12741 /* IPv4 BGP commands. */
12742 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12743 install_element(BGP_NODE
, &bgp_network_cmd
);
12744 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12746 install_element(BGP_NODE
, &aggregate_address_cmd
);
12747 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12748 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12749 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12751 /* IPv4 unicast configuration. */
12752 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12753 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12754 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12756 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12757 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12758 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12759 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12761 /* IPv4 multicast configuration. */
12762 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12763 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12764 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12765 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12766 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12767 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12768 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12770 /* IPv4 labeled-unicast configuration. */
12771 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12772 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12773 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12774 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12775 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12777 install_element(VIEW_NODE
,
12778 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12779 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12780 install_element(VIEW_NODE
,
12781 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12782 #ifdef KEEP_OLD_VPN_COMMANDS
12783 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12784 #endif /* KEEP_OLD_VPN_COMMANDS */
12785 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12786 install_element(VIEW_NODE
,
12787 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
12789 /* BGP dampening clear commands */
12790 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12791 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12793 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12794 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12797 install_element(ENABLE_NODE
,
12798 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12799 #ifdef KEEP_OLD_VPN_COMMANDS
12800 install_element(ENABLE_NODE
,
12801 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12802 #endif /* KEEP_OLD_VPN_COMMANDS */
12804 /* New config IPv6 BGP commands. */
12805 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12806 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12807 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12809 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12810 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12812 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12814 install_element(BGP_NODE
, &bgp_distance_cmd
);
12815 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12816 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12817 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12818 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12819 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12820 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12821 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12822 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12823 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12824 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12825 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12826 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12827 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12828 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12829 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12830 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12831 install_element(BGP_IPV4M_NODE
,
12832 &no_bgp_distance_source_access_list_cmd
);
12833 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12834 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12835 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12836 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12837 install_element(BGP_IPV6_NODE
,
12838 &ipv6_bgp_distance_source_access_list_cmd
);
12839 install_element(BGP_IPV6_NODE
,
12840 &no_ipv6_bgp_distance_source_access_list_cmd
);
12841 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12842 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12843 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12844 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12845 install_element(BGP_IPV6M_NODE
,
12846 &ipv6_bgp_distance_source_access_list_cmd
);
12847 install_element(BGP_IPV6M_NODE
,
12848 &no_ipv6_bgp_distance_source_access_list_cmd
);
12850 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12851 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12852 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12853 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12855 /* IPv4 Multicast Mode */
12856 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12857 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12859 /* Large Communities */
12860 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12861 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12863 /* show bgp ipv4 flowspec detailed */
12864 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12866 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12869 void bgp_route_finish(void)
12874 FOREACH_AFI_SAFI (afi
, safi
) {
12875 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12876 bgp_distance_table
[afi
][safi
] = NULL
;