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 memcpy(&addpath_id
, pnt
, 4);
4519 addpath_id
= ntohl(addpath_id
);
4520 pnt
+= BGP_ADDPATH_ID_LEN
;
4523 /* Fetch prefix length. */
4524 p
.prefixlen
= *pnt
++;
4525 /* afi/safi validity already verified by caller,
4526 * bgp_update_receive */
4527 p
.family
= afi2family(afi
);
4529 /* Prefix length check. */
4530 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4533 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4534 peer
->host
, p
.prefixlen
, packet
->afi
);
4535 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4538 /* Packet size overflow check. */
4539 psize
= PSIZE(p
.prefixlen
);
4541 /* When packet overflow occur return immediately. */
4542 if (pnt
+ psize
> lim
) {
4545 "%s [Error] Update packet error (prefix length %d overflows packet)",
4546 peer
->host
, p
.prefixlen
);
4547 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4550 /* Defensive coding, double-check the psize fits in a struct
4552 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4555 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4556 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4557 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4560 /* Fetch prefix from NLRI packet. */
4561 memcpy(p
.u
.val
, pnt
, psize
);
4563 /* Check address. */
4564 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4565 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4566 /* From RFC4271 Section 6.3:
4568 * If a prefix in the NLRI field is semantically
4570 * (e.g., an unexpected multicast IP address),
4572 * be logged locally, and the prefix SHOULD be
4577 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4578 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4583 /* Check address. */
4584 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4585 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4590 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4592 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4597 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4602 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4604 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4611 /* Normal process. */
4613 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4614 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4615 NULL
, NULL
, 0, 0, NULL
);
4617 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4618 safi
, ZEBRA_ROUTE_BGP
,
4619 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4622 /* Do not send BGP notification twice when maximum-prefix count
4624 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4625 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4627 /* Address family configuration mismatch. */
4629 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4632 /* Packet length consistency check. */
4636 "%s [Error] Update packet error (prefix length mismatch with total length)",
4638 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4641 return BGP_NLRI_PARSE_OK
;
4644 static struct bgp_static
*bgp_static_new(void)
4646 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4649 static void bgp_static_free(struct bgp_static
*bgp_static
)
4651 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4652 route_map_counter_decrement(bgp_static
->rmap
.map
);
4654 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4655 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4658 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4659 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4661 struct bgp_node
*rn
;
4662 struct bgp_path_info
*pi
;
4663 struct bgp_path_info
*new;
4664 struct bgp_path_info rmap_path
;
4666 struct attr
*attr_new
;
4667 route_map_result_t ret
;
4669 int vnc_implicit_withdraw
= 0;
4676 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4678 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4680 attr
.nexthop
= bgp_static
->igpnexthop
;
4681 attr
.med
= bgp_static
->igpmetric
;
4682 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4684 if (bgp_static
->atomic
)
4685 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4687 /* Store label index, if required. */
4688 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4689 attr
.label_index
= bgp_static
->label_index
;
4690 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4693 /* Apply route-map. */
4694 if (bgp_static
->rmap
.name
) {
4695 struct attr attr_tmp
= attr
;
4697 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4698 rmap_path
.peer
= bgp
->peer_self
;
4699 rmap_path
.attr
= &attr_tmp
;
4701 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4703 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4706 bgp
->peer_self
->rmap_type
= 0;
4708 if (ret
== RMAP_DENYMATCH
) {
4709 /* Free uninterned attribute. */
4710 bgp_attr_flush(&attr_tmp
);
4712 /* Unintern original. */
4713 aspath_unintern(&attr
.aspath
);
4714 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4718 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4719 bgp_attr_add_gshut_community(&attr_tmp
);
4721 attr_new
= bgp_attr_intern(&attr_tmp
);
4724 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4725 bgp_attr_add_gshut_community(&attr
);
4727 attr_new
= bgp_attr_intern(&attr
);
4730 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4731 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4732 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4736 if (attrhash_cmp(pi
->attr
, attr_new
)
4737 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4738 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4739 bgp_unlock_node(rn
);
4740 bgp_attr_unintern(&attr_new
);
4741 aspath_unintern(&attr
.aspath
);
4744 /* The attribute is changed. */
4745 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4747 /* Rewrite BGP route information. */
4748 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4749 bgp_path_info_restore(rn
, pi
);
4751 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4753 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4754 && (safi
== SAFI_UNICAST
)) {
4755 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4757 * Implicit withdraw case.
4758 * We have to do this before pi is
4761 ++vnc_implicit_withdraw
;
4762 vnc_import_bgp_del_route(bgp
, p
, pi
);
4763 vnc_import_bgp_exterior_del_route(
4768 bgp_attr_unintern(&pi
->attr
);
4769 pi
->attr
= attr_new
;
4770 pi
->uptime
= bgp_clock();
4772 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4773 && (safi
== SAFI_UNICAST
)) {
4774 if (vnc_implicit_withdraw
) {
4775 vnc_import_bgp_add_route(bgp
, p
, pi
);
4776 vnc_import_bgp_exterior_add_route(
4782 /* Nexthop reachability check. */
4783 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4784 && (safi
== SAFI_UNICAST
4785 || safi
== SAFI_LABELED_UNICAST
)) {
4787 struct bgp
*bgp_nexthop
= bgp
;
4789 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4790 bgp_nexthop
= pi
->extra
->bgp_orig
;
4792 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4794 bgp_path_info_set_flag(rn
, pi
,
4797 if (BGP_DEBUG(nht
, NHT
)) {
4798 char buf1
[INET6_ADDRSTRLEN
];
4799 inet_ntop(p
->family
,
4803 "%s(%s): Route not in table, not advertising",
4804 __FUNCTION__
, buf1
);
4806 bgp_path_info_unset_flag(
4807 rn
, pi
, BGP_PATH_VALID
);
4810 /* Delete the NHT structure if any, if we're
4812 * enabling/disabling import check. We
4813 * deregister the route
4814 * from NHT to avoid overloading NHT and the
4815 * process interaction
4817 bgp_unlink_nexthop(pi
);
4818 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4820 /* Process change. */
4821 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4822 bgp_process(bgp
, rn
, afi
, safi
);
4824 if (SAFI_UNICAST
== safi
4825 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4827 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4828 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4832 bgp_unlock_node(rn
);
4833 aspath_unintern(&attr
.aspath
);
4838 /* Make new BGP info. */
4839 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4841 /* Nexthop reachability check. */
4842 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4843 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4844 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4845 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4847 if (BGP_DEBUG(nht
, NHT
)) {
4848 char buf1
[INET6_ADDRSTRLEN
];
4849 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4852 "%s(%s): Route not in table, not advertising",
4853 __FUNCTION__
, buf1
);
4855 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4858 /* Delete the NHT structure if any, if we're toggling between
4859 * enabling/disabling import check. We deregister the route
4860 * from NHT to avoid overloading NHT and the process interaction
4862 bgp_unlink_nexthop(new);
4864 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4867 /* Aggregate address increment. */
4868 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4870 /* Register new BGP information. */
4871 bgp_path_info_add(rn
, new);
4873 /* route_node_get lock */
4874 bgp_unlock_node(rn
);
4876 /* Process change. */
4877 bgp_process(bgp
, rn
, afi
, safi
);
4879 if (SAFI_UNICAST
== safi
4880 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4881 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4882 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4885 /* Unintern original. */
4886 aspath_unintern(&attr
.aspath
);
4889 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4892 struct bgp_node
*rn
;
4893 struct bgp_path_info
*pi
;
4895 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4897 /* Check selected route and self inserted route. */
4898 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4899 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4900 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4903 /* Withdraw static BGP route from routing table. */
4905 if (SAFI_UNICAST
== safi
4906 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4907 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4908 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4910 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4911 bgp_unlink_nexthop(pi
);
4912 bgp_path_info_delete(rn
, pi
);
4913 bgp_process(bgp
, rn
, afi
, safi
);
4916 /* Unlock bgp_node_lookup. */
4917 bgp_unlock_node(rn
);
4921 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4923 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4924 afi_t afi
, safi_t safi
,
4925 struct prefix_rd
*prd
)
4927 struct bgp_node
*rn
;
4928 struct bgp_path_info
*pi
;
4930 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4932 /* Check selected route and self inserted route. */
4933 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4934 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4935 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4938 /* Withdraw static BGP route from routing table. */
4941 rfapiProcessWithdraw(
4942 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4943 1); /* Kill, since it is an administrative change */
4945 if (SAFI_MPLS_VPN
== safi
4946 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4947 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4949 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4950 bgp_path_info_delete(rn
, pi
);
4951 bgp_process(bgp
, rn
, afi
, safi
);
4954 /* Unlock bgp_node_lookup. */
4955 bgp_unlock_node(rn
);
4958 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4959 struct bgp_static
*bgp_static
, afi_t afi
,
4962 struct bgp_node
*rn
;
4963 struct bgp_path_info
*new;
4964 struct attr
*attr_new
;
4965 struct attr attr
= {0};
4966 struct bgp_path_info
*pi
;
4968 mpls_label_t label
= 0;
4970 uint32_t num_labels
= 0;
4975 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4977 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4980 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4982 attr
.nexthop
= bgp_static
->igpnexthop
;
4983 attr
.med
= bgp_static
->igpmetric
;
4984 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4986 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4987 || (safi
== SAFI_ENCAP
)) {
4988 if (afi
== AFI_IP
) {
4989 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4990 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4993 if (afi
== AFI_L2VPN
) {
4994 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4996 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4997 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4998 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4999 sizeof(struct in6_addr
));
5000 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
5001 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5002 struct bgp_encap_type_vxlan bet
;
5003 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5004 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5005 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5007 if (bgp_static
->router_mac
) {
5008 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5011 /* Apply route-map. */
5012 if (bgp_static
->rmap
.name
) {
5013 struct attr attr_tmp
= attr
;
5014 struct bgp_path_info rmap_path
;
5015 route_map_result_t ret
;
5017 rmap_path
.peer
= bgp
->peer_self
;
5018 rmap_path
.attr
= &attr_tmp
;
5020 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5022 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5025 bgp
->peer_self
->rmap_type
= 0;
5027 if (ret
== RMAP_DENYMATCH
) {
5028 /* Free uninterned attribute. */
5029 bgp_attr_flush(&attr_tmp
);
5031 /* Unintern original. */
5032 aspath_unintern(&attr
.aspath
);
5033 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5038 attr_new
= bgp_attr_intern(&attr_tmp
);
5040 attr_new
= bgp_attr_intern(&attr
);
5043 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5044 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5045 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5049 memset(&add
, 0, sizeof(union gw_addr
));
5050 if (attrhash_cmp(pi
->attr
, attr_new
)
5051 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
5052 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5053 bgp_unlock_node(rn
);
5054 bgp_attr_unintern(&attr_new
);
5055 aspath_unintern(&attr
.aspath
);
5058 /* The attribute is changed. */
5059 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5061 /* Rewrite BGP route information. */
5062 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5063 bgp_path_info_restore(rn
, pi
);
5065 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5066 bgp_attr_unintern(&pi
->attr
);
5067 pi
->attr
= attr_new
;
5068 pi
->uptime
= bgp_clock();
5071 label
= decode_label(&pi
->extra
->label
[0]);
5074 /* Process change. */
5075 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5076 bgp_process(bgp
, rn
, afi
, safi
);
5078 if (SAFI_MPLS_VPN
== safi
5079 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5080 vpn_leak_to_vrf_update(bgp
, pi
);
5083 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5084 pi
->attr
, afi
, safi
, pi
->type
,
5085 pi
->sub_type
, &label
);
5087 bgp_unlock_node(rn
);
5088 aspath_unintern(&attr
.aspath
);
5094 /* Make new BGP info. */
5095 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5097 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5098 new->extra
= bgp_path_info_extra_new();
5100 new->extra
->label
[0] = bgp_static
->label
;
5101 new->extra
->num_labels
= num_labels
;
5104 label
= decode_label(&bgp_static
->label
);
5107 /* Aggregate address increment. */
5108 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5110 /* Register new BGP information. */
5111 bgp_path_info_add(rn
, new);
5112 /* route_node_get lock */
5113 bgp_unlock_node(rn
);
5115 /* Process change. */
5116 bgp_process(bgp
, rn
, afi
, safi
);
5118 if (SAFI_MPLS_VPN
== safi
5119 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5120 vpn_leak_to_vrf_update(bgp
, new);
5123 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5124 safi
, new->type
, new->sub_type
, &label
);
5127 /* Unintern original. */
5128 aspath_unintern(&attr
.aspath
);
5131 /* Configure static BGP network. When user don't run zebra, static
5132 route should be installed as valid. */
5133 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5134 const char *ip_str
, afi_t afi
, safi_t safi
,
5135 const char *rmap
, int backdoor
, uint32_t label_index
)
5137 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5140 struct bgp_static
*bgp_static
;
5141 struct bgp_node
*rn
;
5142 uint8_t need_update
= 0;
5144 /* Convert IP prefix string to struct prefix. */
5145 ret
= str2prefix(ip_str
, &p
);
5147 vty_out(vty
, "%% Malformed prefix\n");
5148 return CMD_WARNING_CONFIG_FAILED
;
5150 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5151 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5152 return CMD_WARNING_CONFIG_FAILED
;
5159 /* Set BGP static route configuration. */
5160 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5163 vty_out(vty
, "%% Can't find static route specified\n");
5164 return CMD_WARNING_CONFIG_FAILED
;
5167 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5169 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5170 && (label_index
!= bgp_static
->label_index
)) {
5172 "%% label-index doesn't match static route\n");
5173 return CMD_WARNING_CONFIG_FAILED
;
5176 if ((rmap
&& bgp_static
->rmap
.name
)
5177 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5179 "%% route-map name doesn't match static route\n");
5180 return CMD_WARNING_CONFIG_FAILED
;
5183 /* Update BGP RIB. */
5184 if (!bgp_static
->backdoor
)
5185 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5187 /* Clear configuration. */
5188 bgp_static_free(bgp_static
);
5189 bgp_node_set_bgp_static_info(rn
, NULL
);
5190 bgp_unlock_node(rn
);
5191 bgp_unlock_node(rn
);
5194 /* Set BGP static route configuration. */
5195 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5197 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5199 /* Configuration change. */
5200 /* Label index cannot be changed. */
5201 if (bgp_static
->label_index
!= label_index
) {
5202 vty_out(vty
, "%% cannot change label-index\n");
5203 return CMD_WARNING_CONFIG_FAILED
;
5206 /* Check previous routes are installed into BGP. */
5207 if (bgp_static
->valid
5208 && bgp_static
->backdoor
!= backdoor
)
5211 bgp_static
->backdoor
= backdoor
;
5214 XFREE(MTYPE_ROUTE_MAP_NAME
,
5215 bgp_static
->rmap
.name
);
5216 route_map_counter_decrement(
5217 bgp_static
->rmap
.map
);
5218 bgp_static
->rmap
.name
=
5219 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5220 bgp_static
->rmap
.map
=
5221 route_map_lookup_by_name(rmap
);
5222 route_map_counter_increment(
5223 bgp_static
->rmap
.map
);
5225 XFREE(MTYPE_ROUTE_MAP_NAME
,
5226 bgp_static
->rmap
.name
);
5227 route_map_counter_decrement(
5228 bgp_static
->rmap
.map
);
5229 bgp_static
->rmap
.name
= NULL
;
5230 bgp_static
->rmap
.map
= NULL
;
5231 bgp_static
->valid
= 0;
5233 bgp_unlock_node(rn
);
5235 /* New configuration. */
5236 bgp_static
= bgp_static_new();
5237 bgp_static
->backdoor
= backdoor
;
5238 bgp_static
->valid
= 0;
5239 bgp_static
->igpmetric
= 0;
5240 bgp_static
->igpnexthop
.s_addr
= 0;
5241 bgp_static
->label_index
= label_index
;
5244 XFREE(MTYPE_ROUTE_MAP_NAME
,
5245 bgp_static
->rmap
.name
);
5246 route_map_counter_decrement(
5247 bgp_static
->rmap
.map
);
5248 bgp_static
->rmap
.name
=
5249 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5250 bgp_static
->rmap
.map
=
5251 route_map_lookup_by_name(rmap
);
5252 route_map_counter_increment(
5253 bgp_static
->rmap
.map
);
5255 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5258 bgp_static
->valid
= 1;
5260 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5262 if (!bgp_static
->backdoor
)
5263 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5269 void bgp_static_add(struct bgp
*bgp
)
5273 struct bgp_node
*rn
;
5274 struct bgp_node
*rm
;
5275 struct bgp_table
*table
;
5276 struct bgp_static
*bgp_static
;
5278 FOREACH_AFI_SAFI (afi
, safi
)
5279 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5280 rn
= bgp_route_next(rn
)) {
5281 if (!bgp_node_has_bgp_path_info_data(rn
))
5284 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5285 || (safi
== SAFI_EVPN
)) {
5286 table
= bgp_node_get_bgp_table_info(rn
);
5288 for (rm
= bgp_table_top(table
); rm
;
5289 rm
= bgp_route_next(rm
)) {
5291 bgp_node_get_bgp_static_info(
5293 bgp_static_update_safi(bgp
, &rm
->p
,
5300 bgp_node_get_bgp_static_info(rn
), afi
,
5306 /* Called from bgp_delete(). Delete all static routes from the BGP
5308 void bgp_static_delete(struct bgp
*bgp
)
5312 struct bgp_node
*rn
;
5313 struct bgp_node
*rm
;
5314 struct bgp_table
*table
;
5315 struct bgp_static
*bgp_static
;
5317 FOREACH_AFI_SAFI (afi
, safi
)
5318 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5319 rn
= bgp_route_next(rn
)) {
5320 if (!bgp_node_has_bgp_path_info_data(rn
))
5323 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5324 || (safi
== SAFI_EVPN
)) {
5325 table
= bgp_node_get_bgp_table_info(rn
);
5327 for (rm
= bgp_table_top(table
); rm
;
5328 rm
= bgp_route_next(rm
)) {
5330 bgp_node_get_bgp_static_info(
5335 bgp_static_withdraw_safi(
5336 bgp
, &rm
->p
, AFI_IP
, safi
,
5337 (struct prefix_rd
*)&rn
->p
);
5338 bgp_static_free(bgp_static
);
5339 bgp_node_set_bgp_static_info(rn
, NULL
);
5340 bgp_unlock_node(rn
);
5343 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5344 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5345 bgp_static_free(bgp_static
);
5346 bgp_node_set_bgp_static_info(rn
, NULL
);
5347 bgp_unlock_node(rn
);
5352 void bgp_static_redo_import_check(struct bgp
*bgp
)
5356 struct bgp_node
*rn
;
5357 struct bgp_node
*rm
;
5358 struct bgp_table
*table
;
5359 struct bgp_static
*bgp_static
;
5361 /* Use this flag to force reprocessing of the route */
5362 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5363 FOREACH_AFI_SAFI (afi
, safi
) {
5364 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5365 rn
= bgp_route_next(rn
)) {
5366 if (!bgp_node_has_bgp_path_info_data(rn
))
5369 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5370 || (safi
== SAFI_EVPN
)) {
5371 table
= bgp_node_get_bgp_table_info(rn
);
5373 for (rm
= bgp_table_top(table
); rm
;
5374 rm
= bgp_route_next(rm
)) {
5376 bgp_node_get_bgp_static_info(
5378 bgp_static_update_safi(bgp
, &rm
->p
,
5383 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5384 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5389 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5392 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5395 struct bgp_table
*table
;
5396 struct bgp_node
*rn
;
5397 struct bgp_path_info
*pi
;
5399 /* Do not install the aggregate route if BGP is in the
5400 * process of termination.
5402 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5403 (bgp
->peer_self
== NULL
))
5406 table
= bgp
->rib
[afi
][safi
];
5407 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5408 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5409 if (pi
->peer
== bgp
->peer_self
5410 && ((pi
->type
== ZEBRA_ROUTE_BGP
5411 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5412 || (pi
->type
!= ZEBRA_ROUTE_BGP
5414 == BGP_ROUTE_REDISTRIBUTE
))) {
5415 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5417 bgp_unlink_nexthop(pi
);
5418 bgp_path_info_delete(rn
, pi
);
5419 bgp_process(bgp
, rn
, afi
, safi
);
5426 * Purge all networks and redistributed routes from routing table.
5427 * Invoked upon the instance going down.
5429 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5434 FOREACH_AFI_SAFI (afi
, safi
)
5435 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5440 * Currently this is used to set static routes for VPN and ENCAP.
5441 * I think it can probably be factored with bgp_static_set.
5443 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5444 const char *ip_str
, const char *rd_str
,
5445 const char *label_str
, const char *rmap_str
,
5446 int evpn_type
, const char *esi
, const char *gwip
,
5447 const char *ethtag
, const char *routermac
)
5449 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5452 struct prefix_rd prd
;
5453 struct bgp_node
*prn
;
5454 struct bgp_node
*rn
;
5455 struct bgp_table
*table
;
5456 struct bgp_static
*bgp_static
;
5457 mpls_label_t label
= MPLS_INVALID_LABEL
;
5458 struct prefix gw_ip
;
5460 /* validate ip prefix */
5461 ret
= str2prefix(ip_str
, &p
);
5463 vty_out(vty
, "%% Malformed prefix\n");
5464 return CMD_WARNING_CONFIG_FAILED
;
5467 if ((afi
== AFI_L2VPN
)
5468 && (bgp_build_evpn_prefix(evpn_type
,
5469 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5470 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5471 return CMD_WARNING_CONFIG_FAILED
;
5474 ret
= str2prefix_rd(rd_str
, &prd
);
5476 vty_out(vty
, "%% Malformed rd\n");
5477 return CMD_WARNING_CONFIG_FAILED
;
5481 unsigned long label_val
;
5482 label_val
= strtoul(label_str
, NULL
, 10);
5483 encode_label(label_val
, &label
);
5486 if (safi
== SAFI_EVPN
) {
5487 if (esi
&& str2esi(esi
, NULL
) == 0) {
5488 vty_out(vty
, "%% Malformed ESI\n");
5489 return CMD_WARNING_CONFIG_FAILED
;
5491 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5492 vty_out(vty
, "%% Malformed Router MAC\n");
5493 return CMD_WARNING_CONFIG_FAILED
;
5496 memset(&gw_ip
, 0, sizeof(struct prefix
));
5497 ret
= str2prefix(gwip
, &gw_ip
);
5499 vty_out(vty
, "%% Malformed GatewayIp\n");
5500 return CMD_WARNING_CONFIG_FAILED
;
5502 if ((gw_ip
.family
== AF_INET
5503 && is_evpn_prefix_ipaddr_v6(
5504 (struct prefix_evpn
*)&p
))
5505 || (gw_ip
.family
== AF_INET6
5506 && is_evpn_prefix_ipaddr_v4(
5507 (struct prefix_evpn
*)&p
))) {
5509 "%% GatewayIp family differs with IP prefix\n");
5510 return CMD_WARNING_CONFIG_FAILED
;
5514 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5515 if (!bgp_node_has_bgp_path_info_data(prn
))
5516 bgp_node_set_bgp_table_info(prn
,
5517 bgp_table_init(bgp
, afi
, safi
));
5518 table
= bgp_node_get_bgp_table_info(prn
);
5520 rn
= bgp_node_get(table
, &p
);
5522 if (bgp_node_has_bgp_path_info_data(rn
)) {
5523 vty_out(vty
, "%% Same network configuration exists\n");
5524 bgp_unlock_node(rn
);
5526 /* New configuration. */
5527 bgp_static
= bgp_static_new();
5528 bgp_static
->backdoor
= 0;
5529 bgp_static
->valid
= 0;
5530 bgp_static
->igpmetric
= 0;
5531 bgp_static
->igpnexthop
.s_addr
= 0;
5532 bgp_static
->label
= label
;
5533 bgp_static
->prd
= prd
;
5536 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5537 route_map_counter_decrement(bgp_static
->rmap
.map
);
5538 bgp_static
->rmap
.name
=
5539 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5540 bgp_static
->rmap
.map
=
5541 route_map_lookup_by_name(rmap_str
);
5542 route_map_counter_increment(bgp_static
->rmap
.map
);
5545 if (safi
== SAFI_EVPN
) {
5547 bgp_static
->eth_s_id
=
5549 sizeof(struct eth_segment_id
));
5550 str2esi(esi
, bgp_static
->eth_s_id
);
5553 bgp_static
->router_mac
=
5554 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5555 (void)prefix_str2mac(routermac
,
5556 bgp_static
->router_mac
);
5559 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5561 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5563 bgp_static
->valid
= 1;
5564 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5570 /* Configure static BGP network. */
5571 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5572 const char *ip_str
, const char *rd_str
,
5573 const char *label_str
, int evpn_type
, const char *esi
,
5574 const char *gwip
, const char *ethtag
)
5576 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5579 struct prefix_rd prd
;
5580 struct bgp_node
*prn
;
5581 struct bgp_node
*rn
;
5582 struct bgp_table
*table
;
5583 struct bgp_static
*bgp_static
;
5584 mpls_label_t label
= MPLS_INVALID_LABEL
;
5586 /* Convert IP prefix string to struct prefix. */
5587 ret
= str2prefix(ip_str
, &p
);
5589 vty_out(vty
, "%% Malformed prefix\n");
5590 return CMD_WARNING_CONFIG_FAILED
;
5593 if ((afi
== AFI_L2VPN
)
5594 && (bgp_build_evpn_prefix(evpn_type
,
5595 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5596 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5597 return CMD_WARNING_CONFIG_FAILED
;
5599 ret
= str2prefix_rd(rd_str
, &prd
);
5601 vty_out(vty
, "%% Malformed rd\n");
5602 return CMD_WARNING_CONFIG_FAILED
;
5606 unsigned long label_val
;
5607 label_val
= strtoul(label_str
, NULL
, 10);
5608 encode_label(label_val
, &label
);
5611 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5612 if (!bgp_node_has_bgp_path_info_data(prn
))
5613 bgp_node_set_bgp_table_info(prn
,
5614 bgp_table_init(bgp
, afi
, safi
));
5616 bgp_unlock_node(prn
);
5617 table
= bgp_node_get_bgp_table_info(prn
);
5619 rn
= bgp_node_lookup(table
, &p
);
5622 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5624 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5625 bgp_static_free(bgp_static
);
5626 bgp_node_set_bgp_static_info(rn
, NULL
);
5627 bgp_unlock_node(rn
);
5628 bgp_unlock_node(rn
);
5630 vty_out(vty
, "%% Can't find the route\n");
5635 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5636 const char *rmap_name
)
5638 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5639 struct bgp_rmap
*rmap
;
5641 rmap
= &bgp
->table_map
[afi
][safi
];
5643 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5644 route_map_counter_decrement(rmap
->map
);
5645 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5646 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5647 route_map_counter_increment(rmap
->map
);
5649 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5650 route_map_counter_decrement(rmap
->map
);
5655 if (bgp_fibupd_safi(safi
))
5656 bgp_zebra_announce_table(bgp
, afi
, safi
);
5661 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5662 const char *rmap_name
)
5664 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5665 struct bgp_rmap
*rmap
;
5667 rmap
= &bgp
->table_map
[afi
][safi
];
5668 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5669 route_map_counter_decrement(rmap
->map
);
5673 if (bgp_fibupd_safi(safi
))
5674 bgp_zebra_announce_table(bgp
, afi
, safi
);
5679 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5682 if (bgp
->table_map
[afi
][safi
].name
) {
5683 vty_out(vty
, " table-map %s\n",
5684 bgp
->table_map
[afi
][safi
].name
);
5688 DEFUN (bgp_table_map
,
5691 "BGP table to RIB route download filter\n"
5692 "Name of the route map\n")
5695 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5696 argv
[idx_word
]->arg
);
5698 DEFUN (no_bgp_table_map
,
5699 no_bgp_table_map_cmd
,
5700 "no table-map WORD",
5702 "BGP table to RIB route download filter\n"
5703 "Name of the route map\n")
5706 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5707 argv
[idx_word
]->arg
);
5713 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5714 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5715 backdoor$backdoor}]",
5717 "Specify a network to announce via BGP\n"
5722 "Route-map to modify the attributes\n"
5723 "Name of the route map\n"
5724 "Label index to associate with the prefix\n"
5725 "Label index value\n"
5726 "Specify a BGP backdoor route\n")
5728 char addr_prefix_str
[BUFSIZ
];
5733 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5736 vty_out(vty
, "%% Inconsistent address and mask\n");
5737 return CMD_WARNING_CONFIG_FAILED
;
5741 return bgp_static_set(
5742 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5743 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5744 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5747 DEFPY(ipv6_bgp_network
,
5748 ipv6_bgp_network_cmd
,
5749 "[no] network X:X::X:X/M$prefix \
5750 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5752 "Specify a network to announce via BGP\n"
5754 "Route-map to modify the attributes\n"
5755 "Name of the route map\n"
5756 "Label index to associate with the prefix\n"
5757 "Label index value\n")
5759 return bgp_static_set(
5760 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5761 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5764 static struct bgp_aggregate
*bgp_aggregate_new(void)
5766 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5769 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5771 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
5772 route_map_counter_decrement(aggregate
->rmap
.map
);
5773 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5776 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5777 struct aspath
*aspath
,
5778 struct community
*comm
,
5779 struct ecommunity
*ecomm
,
5780 struct lcommunity
*lcomm
)
5782 static struct aspath
*ae
= NULL
;
5785 ae
= aspath_empty();
5790 if (origin
!= pi
->attr
->origin
)
5793 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5796 if (!community_cmp(pi
->attr
->community
, comm
))
5799 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5802 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5805 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5811 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5812 struct prefix
*p
, uint8_t origin
,
5813 struct aspath
*aspath
,
5814 struct community
*community
,
5815 struct ecommunity
*ecommunity
,
5816 struct lcommunity
*lcommunity
,
5817 uint8_t atomic_aggregate
,
5818 struct bgp_aggregate
*aggregate
)
5820 struct bgp_node
*rn
;
5821 struct bgp_table
*table
;
5822 struct bgp_path_info
*pi
, *orig
, *new;
5825 table
= bgp
->rib
[afi
][safi
];
5827 rn
= bgp_node_get(table
, p
);
5829 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5830 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5831 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5834 if (aggregate
->count
> 0) {
5836 * If the aggregate information has not changed
5837 * no need to re-install it again.
5839 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5840 ecommunity
, lcommunity
)) {
5841 bgp_unlock_node(rn
);
5844 aspath_free(aspath
);
5846 community_free(&community
);
5848 ecommunity_free(&ecommunity
);
5850 lcommunity_free(&lcommunity
);
5856 * Mark the old as unusable
5859 bgp_path_info_delete(rn
, pi
);
5861 attr
= bgp_attr_aggregate_intern(
5862 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
5863 aggregate
, atomic_aggregate
, p
);
5866 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
5870 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5871 bgp
->peer_self
, attr
, rn
);
5873 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5875 bgp_path_info_add(rn
, new);
5876 bgp_process(bgp
, rn
, afi
, safi
);
5878 for (pi
= orig
; pi
; pi
= pi
->next
)
5879 if (pi
->peer
== bgp
->peer_self
5880 && pi
->type
== ZEBRA_ROUTE_BGP
5881 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5884 /* Withdraw static BGP route from routing table. */
5886 bgp_path_info_delete(rn
, pi
);
5887 bgp_process(bgp
, rn
, afi
, safi
);
5891 bgp_unlock_node(rn
);
5894 /* Update an aggregate as routes are added/removed from the BGP table */
5895 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5896 afi_t afi
, safi_t safi
,
5897 struct bgp_aggregate
*aggregate
)
5899 struct bgp_table
*table
;
5900 struct bgp_node
*top
;
5901 struct bgp_node
*rn
;
5903 struct aspath
*aspath
= NULL
;
5904 struct community
*community
= NULL
;
5905 struct ecommunity
*ecommunity
= NULL
;
5906 struct lcommunity
*lcommunity
= NULL
;
5907 struct bgp_path_info
*pi
;
5908 unsigned long match
= 0;
5909 uint8_t atomic_aggregate
= 0;
5911 /* If the bgp instance is being deleted or self peer is deleted
5912 * then do not create aggregate route
5914 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5915 (bgp
->peer_self
== NULL
))
5918 /* ORIGIN attribute: If at least one route among routes that are
5919 aggregated has ORIGIN with the value INCOMPLETE, then the
5920 aggregated route must have the ORIGIN attribute with the value
5921 INCOMPLETE. Otherwise, if at least one route among routes that
5922 are aggregated has ORIGIN with the value EGP, then the aggregated
5923 route must have the origin attribute with the value EGP. In all
5924 other case the value of the ORIGIN attribute of the aggregated
5925 route is INTERNAL. */
5926 origin
= BGP_ORIGIN_IGP
;
5928 table
= bgp
->rib
[afi
][safi
];
5930 top
= bgp_node_get(table
, p
);
5931 for (rn
= bgp_node_get(table
, p
); rn
;
5932 rn
= bgp_route_next_until(rn
, top
)) {
5933 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5938 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5939 if (BGP_PATH_HOLDDOWN(pi
))
5943 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5944 atomic_aggregate
= 1;
5946 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5950 * summary-only aggregate route suppress
5951 * aggregated route announcements.
5953 if (aggregate
->summary_only
) {
5954 (bgp_path_info_extra_get(pi
))->suppress
++;
5955 bgp_path_info_set_flag(rn
, pi
,
5956 BGP_PATH_ATTR_CHANGED
);
5963 * If at least one route among routes that are
5964 * aggregated has ORIGIN with the value INCOMPLETE,
5965 * then the aggregated route MUST have the ORIGIN
5966 * attribute with the value INCOMPLETE. Otherwise, if
5967 * at least one route among routes that are aggregated
5968 * has ORIGIN with the value EGP, then the aggregated
5969 * route MUST have the ORIGIN attribute with the value
5972 switch (pi
->attr
->origin
) {
5973 case BGP_ORIGIN_INCOMPLETE
:
5974 aggregate
->incomplete_origin_count
++;
5976 case BGP_ORIGIN_EGP
:
5977 aggregate
->egp_origin_count
++;
5985 if (!aggregate
->as_set
)
5989 * as-set aggregate route generate origin, as path,
5990 * and community aggregation.
5992 /* Compute aggregate route's as-path.
5994 bgp_compute_aggregate_aspath_hash(aggregate
,
5997 /* Compute aggregate route's community.
5999 if (pi
->attr
->community
)
6000 bgp_compute_aggregate_community_hash(
6002 pi
->attr
->community
);
6004 /* Compute aggregate route's extended community.
6006 if (pi
->attr
->ecommunity
)
6007 bgp_compute_aggregate_ecommunity_hash(
6009 pi
->attr
->ecommunity
);
6011 /* Compute aggregate route's large community.
6013 if (pi
->attr
->lcommunity
)
6014 bgp_compute_aggregate_lcommunity_hash(
6016 pi
->attr
->lcommunity
);
6019 bgp_process(bgp
, rn
, afi
, safi
);
6021 if (aggregate
->as_set
) {
6022 bgp_compute_aggregate_aspath_val(aggregate
);
6023 bgp_compute_aggregate_community_val(aggregate
);
6024 bgp_compute_aggregate_ecommunity_val(aggregate
);
6025 bgp_compute_aggregate_lcommunity_val(aggregate
);
6029 bgp_unlock_node(top
);
6032 if (aggregate
->incomplete_origin_count
> 0)
6033 origin
= BGP_ORIGIN_INCOMPLETE
;
6034 else if (aggregate
->egp_origin_count
> 0)
6035 origin
= BGP_ORIGIN_EGP
;
6037 if (aggregate
->as_set
) {
6038 if (aggregate
->aspath
)
6039 /* Retrieve aggregate route's as-path.
6041 aspath
= aspath_dup(aggregate
->aspath
);
6043 if (aggregate
->community
)
6044 /* Retrieve aggregate route's community.
6046 community
= community_dup(aggregate
->community
);
6048 if (aggregate
->ecommunity
)
6049 /* Retrieve aggregate route's ecommunity.
6051 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6053 if (aggregate
->lcommunity
)
6054 /* Retrieve aggregate route's lcommunity.
6056 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6059 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6060 ecommunity
, lcommunity
, atomic_aggregate
,
6064 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6065 safi_t safi
, struct bgp_aggregate
*aggregate
)
6067 struct bgp_table
*table
;
6068 struct bgp_node
*top
;
6069 struct bgp_node
*rn
;
6070 struct bgp_path_info
*pi
;
6071 unsigned long match
;
6073 table
= bgp
->rib
[afi
][safi
];
6075 /* If routes exists below this node, generate aggregate routes. */
6076 top
= bgp_node_get(table
, p
);
6077 for (rn
= bgp_node_get(table
, p
); rn
;
6078 rn
= bgp_route_next_until(rn
, top
)) {
6079 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6083 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6084 if (BGP_PATH_HOLDDOWN(pi
))
6087 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6090 if (aggregate
->summary_only
&& pi
->extra
) {
6091 pi
->extra
->suppress
--;
6093 if (pi
->extra
->suppress
== 0) {
6094 bgp_path_info_set_flag(
6095 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6101 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6102 aggregate
->incomplete_origin_count
--;
6103 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6104 aggregate
->egp_origin_count
--;
6106 if (aggregate
->as_set
) {
6107 /* Remove as-path from aggregate.
6109 bgp_remove_aspath_from_aggregate_hash(
6113 if (pi
->attr
->community
)
6114 /* Remove community from aggregate.
6116 bgp_remove_comm_from_aggregate_hash(
6118 pi
->attr
->community
);
6120 if (pi
->attr
->ecommunity
)
6121 /* Remove ecommunity from aggregate.
6123 bgp_remove_ecomm_from_aggregate_hash(
6125 pi
->attr
->ecommunity
);
6127 if (pi
->attr
->lcommunity
)
6128 /* Remove lcommunity from aggregate.
6130 bgp_remove_lcomm_from_aggregate_hash(
6132 pi
->attr
->lcommunity
);
6137 /* If this node was suppressed, process the change. */
6139 bgp_process(bgp
, rn
, afi
, safi
);
6141 if (aggregate
->as_set
) {
6142 aspath_free(aggregate
->aspath
);
6143 aggregate
->aspath
= NULL
;
6144 if (aggregate
->community
)
6145 community_free(&aggregate
->community
);
6146 if (aggregate
->ecommunity
)
6147 ecommunity_free(&aggregate
->ecommunity
);
6148 if (aggregate
->lcommunity
)
6149 lcommunity_free(&aggregate
->lcommunity
);
6152 bgp_unlock_node(top
);
6155 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6156 struct bgp_path_info
*pinew
, afi_t afi
,
6158 struct bgp_aggregate
*aggregate
)
6161 struct aspath
*aspath
= NULL
;
6162 uint8_t atomic_aggregate
= 0;
6163 struct community
*community
= NULL
;
6164 struct ecommunity
*ecommunity
= NULL
;
6165 struct lcommunity
*lcommunity
= NULL
;
6167 /* ORIGIN attribute: If at least one route among routes that are
6168 * aggregated has ORIGIN with the value INCOMPLETE, then the
6169 * aggregated route must have the ORIGIN attribute with the value
6170 * INCOMPLETE. Otherwise, if at least one route among routes that
6171 * are aggregated has ORIGIN with the value EGP, then the aggregated
6172 * route must have the origin attribute with the value EGP. In all
6173 * other case the value of the ORIGIN attribute of the aggregated
6174 * route is INTERNAL.
6176 origin
= BGP_ORIGIN_IGP
;
6180 if (aggregate
->summary_only
)
6181 (bgp_path_info_extra_get(pinew
))->suppress
++;
6183 switch (pinew
->attr
->origin
) {
6184 case BGP_ORIGIN_INCOMPLETE
:
6185 aggregate
->incomplete_origin_count
++;
6187 case BGP_ORIGIN_EGP
:
6188 aggregate
->egp_origin_count
++;
6196 if (aggregate
->incomplete_origin_count
> 0)
6197 origin
= BGP_ORIGIN_INCOMPLETE
;
6198 else if (aggregate
->egp_origin_count
> 0)
6199 origin
= BGP_ORIGIN_EGP
;
6201 if (aggregate
->as_set
) {
6202 /* Compute aggregate route's as-path.
6204 bgp_compute_aggregate_aspath(aggregate
,
6205 pinew
->attr
->aspath
);
6207 /* Compute aggregate route's community.
6209 if (pinew
->attr
->community
)
6210 bgp_compute_aggregate_community(
6212 pinew
->attr
->community
);
6214 /* Compute aggregate route's extended community.
6216 if (pinew
->attr
->ecommunity
)
6217 bgp_compute_aggregate_ecommunity(
6219 pinew
->attr
->ecommunity
);
6221 /* Compute aggregate route's large community.
6223 if (pinew
->attr
->lcommunity
)
6224 bgp_compute_aggregate_lcommunity(
6226 pinew
->attr
->lcommunity
);
6228 /* Retrieve aggregate route's as-path.
6230 if (aggregate
->aspath
)
6231 aspath
= aspath_dup(aggregate
->aspath
);
6233 /* Retrieve aggregate route's community.
6235 if (aggregate
->community
)
6236 community
= community_dup(aggregate
->community
);
6238 /* Retrieve aggregate route's ecommunity.
6240 if (aggregate
->ecommunity
)
6241 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6243 /* Retrieve aggregate route's lcommunity.
6245 if (aggregate
->lcommunity
)
6246 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6249 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6250 aspath
, community
, ecommunity
,
6251 lcommunity
, atomic_aggregate
, aggregate
);
6254 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6256 struct bgp_path_info
*pi
,
6257 struct bgp_aggregate
*aggregate
,
6258 struct prefix
*aggr_p
)
6261 struct aspath
*aspath
= NULL
;
6262 uint8_t atomic_aggregate
= 0;
6263 struct community
*community
= NULL
;
6264 struct ecommunity
*ecommunity
= NULL
;
6265 struct lcommunity
*lcommunity
= NULL
;
6266 unsigned long match
= 0;
6268 if (BGP_PATH_HOLDDOWN(pi
))
6271 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6274 if (aggregate
->summary_only
6276 && pi
->extra
->suppress
> 0) {
6277 pi
->extra
->suppress
--;
6279 if (pi
->extra
->suppress
== 0) {
6280 bgp_path_info_set_flag(pi
->net
, pi
,
6281 BGP_PATH_ATTR_CHANGED
);
6286 if (aggregate
->count
> 0)
6289 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6290 aggregate
->incomplete_origin_count
--;
6291 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6292 aggregate
->egp_origin_count
--;
6294 if (aggregate
->as_set
) {
6295 /* Remove as-path from aggregate.
6297 bgp_remove_aspath_from_aggregate(aggregate
,
6300 if (pi
->attr
->community
)
6301 /* Remove community from aggregate.
6303 bgp_remove_community_from_aggregate(
6305 pi
->attr
->community
);
6307 if (pi
->attr
->ecommunity
)
6308 /* Remove ecommunity from aggregate.
6310 bgp_remove_ecommunity_from_aggregate(
6312 pi
->attr
->ecommunity
);
6314 if (pi
->attr
->lcommunity
)
6315 /* Remove lcommunity from aggregate.
6317 bgp_remove_lcommunity_from_aggregate(
6319 pi
->attr
->lcommunity
);
6322 /* If this node was suppressed, process the change. */
6324 bgp_process(bgp
, pi
->net
, afi
, safi
);
6326 origin
= BGP_ORIGIN_IGP
;
6327 if (aggregate
->incomplete_origin_count
> 0)
6328 origin
= BGP_ORIGIN_INCOMPLETE
;
6329 else if (aggregate
->egp_origin_count
> 0)
6330 origin
= BGP_ORIGIN_EGP
;
6332 if (aggregate
->as_set
) {
6333 /* Retrieve aggregate route's as-path.
6335 if (aggregate
->aspath
)
6336 aspath
= aspath_dup(aggregate
->aspath
);
6338 /* Retrieve aggregate route's community.
6340 if (aggregate
->community
)
6341 community
= community_dup(aggregate
->community
);
6343 /* Retrieve aggregate route's ecommunity.
6345 if (aggregate
->ecommunity
)
6346 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6348 /* Retrieve aggregate route's lcommunity.
6350 if (aggregate
->lcommunity
)
6351 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6354 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6355 aspath
, community
, ecommunity
,
6356 lcommunity
, atomic_aggregate
, aggregate
);
6359 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6360 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6362 struct bgp_node
*child
;
6363 struct bgp_node
*rn
;
6364 struct bgp_aggregate
*aggregate
;
6365 struct bgp_table
*table
;
6367 table
= bgp
->aggregate
[afi
][safi
];
6369 /* No aggregates configured. */
6370 if (bgp_table_top_nolock(table
) == NULL
)
6373 if (p
->prefixlen
== 0)
6376 if (BGP_PATH_HOLDDOWN(pi
))
6379 child
= bgp_node_get(table
, p
);
6381 /* Aggregate address configuration check. */
6382 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6383 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6384 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6385 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6389 bgp_unlock_node(child
);
6392 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6393 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6395 struct bgp_node
*child
;
6396 struct bgp_node
*rn
;
6397 struct bgp_aggregate
*aggregate
;
6398 struct bgp_table
*table
;
6400 table
= bgp
->aggregate
[afi
][safi
];
6402 /* No aggregates configured. */
6403 if (bgp_table_top_nolock(table
) == NULL
)
6406 if (p
->prefixlen
== 0)
6409 child
= bgp_node_get(table
, p
);
6411 /* Aggregate address configuration check. */
6412 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6413 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6414 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6415 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6416 del
, aggregate
, &rn
->p
);
6419 bgp_unlock_node(child
);
6422 /* Aggregate route attribute. */
6423 #define AGGREGATE_SUMMARY_ONLY 1
6424 #define AGGREGATE_AS_SET 1
6425 #define AGGREGATE_AS_UNSET 0
6427 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6428 afi_t afi
, safi_t safi
)
6430 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6433 struct bgp_node
*rn
;
6434 struct bgp_aggregate
*aggregate
;
6436 /* Convert string to prefix structure. */
6437 ret
= str2prefix(prefix_str
, &p
);
6439 vty_out(vty
, "Malformed prefix\n");
6440 return CMD_WARNING_CONFIG_FAILED
;
6444 /* Old configuration check. */
6445 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6448 "%% There is no aggregate-address configuration.\n");
6449 return CMD_WARNING_CONFIG_FAILED
;
6452 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6453 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6454 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6455 NULL
, NULL
, 0, aggregate
);
6457 /* Unlock aggregate address configuration. */
6458 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6460 if (aggregate
->community
)
6461 community_free(&aggregate
->community
);
6463 if (aggregate
->community_hash
) {
6464 /* Delete all communities in the hash.
6466 hash_clean(aggregate
->community_hash
,
6467 bgp_aggr_community_remove
);
6468 /* Free up the community_hash.
6470 hash_free(aggregate
->community_hash
);
6473 if (aggregate
->ecommunity
)
6474 ecommunity_free(&aggregate
->ecommunity
);
6476 if (aggregate
->ecommunity_hash
) {
6477 /* Delete all ecommunities in the hash.
6479 hash_clean(aggregate
->ecommunity_hash
,
6480 bgp_aggr_ecommunity_remove
);
6481 /* Free up the ecommunity_hash.
6483 hash_free(aggregate
->ecommunity_hash
);
6486 if (aggregate
->lcommunity
)
6487 lcommunity_free(&aggregate
->lcommunity
);
6489 if (aggregate
->lcommunity_hash
) {
6490 /* Delete all lcommunities in the hash.
6492 hash_clean(aggregate
->lcommunity_hash
,
6493 bgp_aggr_lcommunity_remove
);
6494 /* Free up the lcommunity_hash.
6496 hash_free(aggregate
->lcommunity_hash
);
6499 if (aggregate
->aspath
)
6500 aspath_free(aggregate
->aspath
);
6502 if (aggregate
->aspath_hash
) {
6503 /* Delete all as-paths in the hash.
6505 hash_clean(aggregate
->aspath_hash
,
6506 bgp_aggr_aspath_remove
);
6507 /* Free up the aspath_hash.
6509 hash_free(aggregate
->aspath_hash
);
6512 bgp_aggregate_free(aggregate
);
6513 bgp_unlock_node(rn
);
6514 bgp_unlock_node(rn
);
6519 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6520 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6523 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6526 struct bgp_node
*rn
;
6527 struct bgp_aggregate
*aggregate
;
6528 uint8_t as_set_new
= as_set
;
6530 /* Convert string to prefix structure. */
6531 ret
= str2prefix(prefix_str
, &p
);
6533 vty_out(vty
, "Malformed prefix\n");
6534 return CMD_WARNING_CONFIG_FAILED
;
6538 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6539 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6540 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6542 return CMD_WARNING_CONFIG_FAILED
;
6545 /* Old configuration check. */
6546 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6547 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6550 vty_out(vty
, "There is already same aggregate network.\n");
6551 /* try to remove the old entry */
6552 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6554 vty_out(vty
, "Error deleting aggregate.\n");
6555 bgp_unlock_node(rn
);
6556 return CMD_WARNING_CONFIG_FAILED
;
6560 /* Make aggregate address structure. */
6561 aggregate
= bgp_aggregate_new();
6562 aggregate
->summary_only
= summary_only
;
6564 /* Network operators MUST NOT locally generate any new
6565 * announcements containing AS_SET or AS_CONFED_SET. If they have
6566 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6567 * SHOULD withdraw those routes and re-announce routes for the
6568 * aggregate or component prefixes (i.e., the more-specific routes
6569 * subsumed by the previously aggregated route) without AS_SET
6570 * or AS_CONFED_SET in the updates.
6572 if (bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
) {
6573 if (as_set
== AGGREGATE_AS_SET
) {
6574 as_set_new
= AGGREGATE_AS_UNSET
;
6576 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
6579 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6583 aggregate
->as_set
= as_set_new
;
6584 aggregate
->safi
= safi
;
6587 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6588 route_map_counter_decrement(aggregate
->rmap
.map
);
6589 aggregate
->rmap
.name
=
6590 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6591 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6592 route_map_counter_increment(aggregate
->rmap
.map
);
6594 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6596 /* Aggregate address insert into BGP routing table. */
6597 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6602 DEFUN (aggregate_address
,
6603 aggregate_address_cmd
,
6604 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6605 "Configure BGP aggregate entries\n"
6606 "Aggregate prefix\n"
6607 "Generate AS set path information\n"
6608 "Filter more specific routes from updates\n"
6609 "Filter more specific routes from updates\n"
6610 "Generate AS set path information\n"
6611 "Apply route map to aggregate network\n"
6612 "Name of route map\n")
6615 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6616 char *prefix
= argv
[idx
]->arg
;
6618 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6619 : AGGREGATE_AS_UNSET
;
6621 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6622 ? AGGREGATE_SUMMARY_ONLY
6626 argv_find(argv
, argc
, "WORD", &idx
);
6628 rmap
= argv
[idx
]->arg
;
6630 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6631 rmap
, summary_only
, as_set
);
6634 DEFUN (aggregate_address_mask
,
6635 aggregate_address_mask_cmd
,
6636 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6637 "Configure BGP aggregate entries\n"
6638 "Aggregate address\n"
6640 "Generate AS set path information\n"
6641 "Filter more specific routes from updates\n"
6642 "Filter more specific routes from updates\n"
6643 "Generate AS set path information\n"
6644 "Apply route map to aggregate network\n"
6645 "Name of route map\n")
6648 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6649 char *prefix
= argv
[idx
]->arg
;
6650 char *mask
= argv
[idx
+ 1]->arg
;
6653 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6654 : AGGREGATE_AS_UNSET
;
6656 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6657 ? AGGREGATE_SUMMARY_ONLY
6660 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6662 rmap
= argv
[idx
]->arg
;
6664 char prefix_str
[BUFSIZ
];
6665 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6668 vty_out(vty
, "%% Inconsistent address and mask\n");
6669 return CMD_WARNING_CONFIG_FAILED
;
6672 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6673 rmap
, summary_only
, as_set
);
6676 DEFUN (no_aggregate_address
,
6677 no_aggregate_address_cmd
,
6678 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6680 "Configure BGP aggregate entries\n"
6681 "Aggregate prefix\n"
6682 "Generate AS set path information\n"
6683 "Filter more specific routes from updates\n"
6684 "Filter more specific routes from updates\n"
6685 "Generate AS set path information\n"
6686 "Apply route map to aggregate network\n"
6687 "Name of route map\n")
6690 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6691 char *prefix
= argv
[idx
]->arg
;
6692 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6695 DEFUN (no_aggregate_address_mask
,
6696 no_aggregate_address_mask_cmd
,
6697 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6699 "Configure BGP aggregate entries\n"
6700 "Aggregate address\n"
6702 "Generate AS set path information\n"
6703 "Filter more specific routes from updates\n"
6704 "Filter more specific routes from updates\n"
6705 "Generate AS set path information\n"
6706 "Apply route map to aggregate network\n"
6707 "Name of route map\n")
6710 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6711 char *prefix
= argv
[idx
]->arg
;
6712 char *mask
= argv
[idx
+ 1]->arg
;
6714 char prefix_str
[BUFSIZ
];
6715 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6718 vty_out(vty
, "%% Inconsistent address and mask\n");
6719 return CMD_WARNING_CONFIG_FAILED
;
6722 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6725 DEFUN (ipv6_aggregate_address
,
6726 ipv6_aggregate_address_cmd
,
6727 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6728 "Configure BGP aggregate entries\n"
6729 "Aggregate prefix\n"
6730 "Generate AS set path information\n"
6731 "Filter more specific routes from updates\n"
6732 "Filter more specific routes from updates\n"
6733 "Generate AS set path information\n"
6734 "Apply route map to aggregate network\n"
6735 "Name of route map\n")
6738 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6739 char *prefix
= argv
[idx
]->arg
;
6742 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6743 : AGGREGATE_AS_UNSET
;
6746 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6747 ? AGGREGATE_SUMMARY_ONLY
6750 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6752 rmap
= argv
[idx
]->arg
;
6754 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6758 DEFUN (no_ipv6_aggregate_address
,
6759 no_ipv6_aggregate_address_cmd
,
6760 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6762 "Configure BGP aggregate entries\n"
6763 "Aggregate prefix\n"
6764 "Generate AS set path information\n"
6765 "Filter more specific routes from updates\n"
6766 "Filter more specific routes from updates\n"
6767 "Generate AS set path information\n"
6768 "Apply route map to aggregate network\n"
6769 "Name of route map\n")
6772 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6773 char *prefix
= argv
[idx
]->arg
;
6774 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6777 /* Redistribute route treatment. */
6778 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6779 const union g_addr
*nexthop
, ifindex_t ifindex
,
6780 enum nexthop_types_t nhtype
, uint32_t metric
,
6781 uint8_t type
, unsigned short instance
,
6784 struct bgp_path_info
*new;
6785 struct bgp_path_info
*bpi
;
6786 struct bgp_path_info rmap_path
;
6787 struct bgp_node
*bn
;
6789 struct attr
*new_attr
;
6791 route_map_result_t ret
;
6792 struct bgp_redist
*red
;
6794 /* Make default attribute. */
6795 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6797 * This must not be NULL to satisfy Coverity SA
6799 assert(attr
.aspath
);
6802 case NEXTHOP_TYPE_IFINDEX
:
6804 case NEXTHOP_TYPE_IPV4
:
6805 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6806 attr
.nexthop
= nexthop
->ipv4
;
6808 case NEXTHOP_TYPE_IPV6
:
6809 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6810 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6811 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6813 case NEXTHOP_TYPE_BLACKHOLE
:
6814 switch (p
->family
) {
6816 attr
.nexthop
.s_addr
= INADDR_ANY
;
6819 memset(&attr
.mp_nexthop_global
, 0,
6820 sizeof(attr
.mp_nexthop_global
));
6821 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6826 attr
.nh_ifindex
= ifindex
;
6829 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6832 afi
= family2afi(p
->family
);
6834 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6836 struct attr attr_new
;
6838 /* Copy attribute for modification. */
6841 if (red
->redist_metric_flag
)
6842 attr_new
.med
= red
->redist_metric
;
6844 /* Apply route-map. */
6845 if (red
->rmap
.name
) {
6846 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6847 rmap_path
.peer
= bgp
->peer_self
;
6848 rmap_path
.attr
= &attr_new
;
6850 SET_FLAG(bgp
->peer_self
->rmap_type
,
6851 PEER_RMAP_TYPE_REDISTRIBUTE
);
6853 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6856 bgp
->peer_self
->rmap_type
= 0;
6858 if (ret
== RMAP_DENYMATCH
) {
6859 /* Free uninterned attribute. */
6860 bgp_attr_flush(&attr_new
);
6862 /* Unintern original. */
6863 aspath_unintern(&attr
.aspath
);
6864 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6869 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6870 bgp_attr_add_gshut_community(&attr_new
);
6872 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6873 SAFI_UNICAST
, p
, NULL
);
6875 new_attr
= bgp_attr_intern(&attr_new
);
6877 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6879 if (bpi
->peer
== bgp
->peer_self
6880 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6884 /* Ensure the (source route) type is updated. */
6886 if (attrhash_cmp(bpi
->attr
, new_attr
)
6887 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6888 bgp_attr_unintern(&new_attr
);
6889 aspath_unintern(&attr
.aspath
);
6890 bgp_unlock_node(bn
);
6893 /* The attribute is changed. */
6894 bgp_path_info_set_flag(bn
, bpi
,
6895 BGP_PATH_ATTR_CHANGED
);
6897 /* Rewrite BGP route information. */
6898 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6899 bgp_path_info_restore(bn
, bpi
);
6901 bgp_aggregate_decrement(
6902 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6903 bgp_attr_unintern(&bpi
->attr
);
6904 bpi
->attr
= new_attr
;
6905 bpi
->uptime
= bgp_clock();
6907 /* Process change. */
6908 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6910 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6911 bgp_unlock_node(bn
);
6912 aspath_unintern(&attr
.aspath
);
6914 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6916 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6918 vpn_leak_from_vrf_update(
6919 bgp_get_default(), bgp
, bpi
);
6925 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6926 bgp
->peer_self
, new_attr
, bn
);
6927 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6929 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6930 bgp_path_info_add(bn
, new);
6931 bgp_unlock_node(bn
);
6932 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6934 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6935 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6937 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6941 /* Unintern original. */
6942 aspath_unintern(&attr
.aspath
);
6945 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6946 unsigned short instance
)
6949 struct bgp_node
*rn
;
6950 struct bgp_path_info
*pi
;
6951 struct bgp_redist
*red
;
6953 afi
= family2afi(p
->family
);
6955 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6957 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6958 SAFI_UNICAST
, p
, NULL
);
6960 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6961 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6965 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6966 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6968 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6971 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6972 bgp_path_info_delete(rn
, pi
);
6973 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6975 bgp_unlock_node(rn
);
6979 /* Withdraw specified route type's route. */
6980 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6981 unsigned short instance
)
6983 struct bgp_node
*rn
;
6984 struct bgp_path_info
*pi
;
6985 struct bgp_table
*table
;
6987 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6989 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6990 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6991 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6992 && pi
->instance
== instance
)
6996 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6997 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6999 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7002 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
7004 bgp_path_info_delete(rn
, pi
);
7005 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7010 /* Static function to display route. */
7011 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
7018 if (p
->family
== AF_INET
) {
7022 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7025 json_object_string_add(json
, "prefix",
7026 inet_ntop(p
->family
,
7029 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7030 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7031 json_object_string_add(json
, "network", buf2
);
7033 } else if (p
->family
== AF_ETHERNET
) {
7034 prefix2str(p
, buf
, PREFIX_STRLEN
);
7035 len
= vty_out(vty
, "%s", buf
);
7036 } else if (p
->family
== AF_EVPN
) {
7040 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7043 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7044 } else if (p
->family
== AF_FLOWSPEC
) {
7045 route_vty_out_flowspec(vty
, p
, NULL
,
7047 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7048 NLRI_STRING_FORMAT_MIN
, json
);
7053 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7056 json_object_string_add(json
, "prefix",
7057 inet_ntop(p
->family
,
7060 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7061 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7062 json_object_string_add(json
, "network", buf2
);
7069 vty_out(vty
, "\n%*s", 20, " ");
7071 vty_out(vty
, "%*s", len
, " ");
7075 enum bgp_display_type
{
7079 /* Print the short form route status for a bgp_path_info */
7080 static void route_vty_short_status_out(struct vty
*vty
,
7081 struct bgp_path_info
*path
,
7082 json_object
*json_path
)
7086 /* Route status display. */
7087 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7088 json_object_boolean_true_add(json_path
, "removed");
7090 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7091 json_object_boolean_true_add(json_path
, "stale");
7093 if (path
->extra
&& path
->extra
->suppress
)
7094 json_object_boolean_true_add(json_path
, "suppressed");
7096 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7097 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7098 json_object_boolean_true_add(json_path
, "valid");
7101 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7102 json_object_boolean_true_add(json_path
, "history");
7104 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7105 json_object_boolean_true_add(json_path
, "damped");
7107 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7108 json_object_boolean_true_add(json_path
, "bestpath");
7110 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7111 json_object_boolean_true_add(json_path
, "multipath");
7113 /* Internal route. */
7114 if ((path
->peer
->as
)
7115 && (path
->peer
->as
== path
->peer
->local_as
))
7116 json_object_string_add(json_path
, "pathFrom",
7119 json_object_string_add(json_path
, "pathFrom",
7125 /* Route status display. */
7126 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7128 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7130 else if (path
->extra
&& path
->extra
->suppress
)
7132 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7133 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7139 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7141 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7143 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7145 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7150 /* Internal route. */
7151 if (path
->peer
&& (path
->peer
->as
)
7152 && (path
->peer
->as
== path
->peer
->local_as
))
7158 static char *bgp_nexthop_hostname(struct peer
*peer
, struct attr
*attr
)
7160 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)
7161 && !(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))
7162 return peer
->hostname
;
7166 /* called from terminal list command */
7167 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7168 struct bgp_path_info
*path
, int display
, safi_t safi
,
7169 json_object
*json_paths
)
7171 struct attr
*attr
= path
->attr
;
7172 json_object
*json_path
= NULL
;
7173 json_object
*json_nexthops
= NULL
;
7174 json_object
*json_nexthop_global
= NULL
;
7175 json_object
*json_nexthop_ll
= NULL
;
7176 json_object
*json_ext_community
= NULL
;
7177 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7179 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7180 bool nexthop_othervrf
= false;
7181 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7182 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7183 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
7186 json_path
= json_object_new_object();
7188 /* short status lead text */
7189 route_vty_short_status_out(vty
, path
, json_path
);
7192 /* print prefix and mask */
7194 route_vty_out_route(p
, vty
, json_path
);
7196 vty_out(vty
, "%*s", 17, " ");
7198 route_vty_out_route(p
, vty
, json_path
);
7202 * If vrf id of nexthop is different from that of prefix,
7203 * set up printable string to append
7205 if (path
->extra
&& path
->extra
->bgp_orig
) {
7206 const char *self
= "";
7211 nexthop_othervrf
= true;
7212 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7214 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7215 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7216 "@%s%s", VRFID_NONE_STR
, self
);
7218 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7219 path
->extra
->bgp_orig
->vrf_id
, self
);
7221 if (path
->extra
->bgp_orig
->inst_type
7222 != BGP_INSTANCE_TYPE_DEFAULT
)
7224 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7226 const char *self
= "";
7231 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7235 * For ENCAP and EVPN routes, nexthop address family is not
7236 * neccessarily the same as the prefix address family.
7237 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7238 * EVPN routes are also exchanged with a MP nexthop. Currently,
7240 * is only IPv4, the value will be present in either
7242 * attr->mp_nexthop_global_in
7244 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7247 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7251 sprintf(nexthop
, "%s",
7252 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7256 sprintf(nexthop
, "%s",
7257 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7261 sprintf(nexthop
, "?");
7266 json_nexthop_global
= json_object_new_object();
7268 json_object_string_add(json_nexthop_global
, "ip",
7271 if (nexthop_hostname
)
7272 json_object_string_add(json_nexthop_global
,
7276 json_object_string_add(json_nexthop_global
, "afi",
7277 (af
== AF_INET
) ? "ipv4"
7279 json_object_boolean_true_add(json_nexthop_global
,
7282 vty_out(vty
, "%s%s",
7283 nexthop_hostname
? nexthop_hostname
: nexthop
,
7285 } else if (safi
== SAFI_EVPN
) {
7287 json_nexthop_global
= json_object_new_object();
7289 json_object_string_add(json_nexthop_global
, "ip",
7290 inet_ntoa(attr
->nexthop
));
7292 if (nexthop_hostname
)
7293 json_object_string_add(json_nexthop_global
,
7297 json_object_string_add(json_nexthop_global
, "afi",
7299 json_object_boolean_true_add(json_nexthop_global
,
7302 vty_out(vty
, "%-16s%s",
7303 nexthop_hostname
? nexthop_hostname
7304 : inet_ntoa(attr
->nexthop
),
7306 } else if (safi
== SAFI_FLOWSPEC
) {
7307 if (attr
->nexthop
.s_addr
!= 0) {
7309 json_nexthop_global
= json_object_new_object();
7311 json_object_string_add(json_nexthop_global
,
7313 json_object_string_add(
7314 json_nexthop_global
, "ip",
7315 inet_ntoa(attr
->nexthop
));
7317 if (nexthop_hostname
)
7318 json_object_string_add(
7319 json_nexthop_global
, "hostname",
7322 json_object_boolean_true_add(
7323 json_nexthop_global
,
7326 vty_out(vty
, "%-16s",
7329 : inet_ntoa(attr
->nexthop
));
7332 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7334 json_nexthop_global
= json_object_new_object();
7336 json_object_string_add(json_nexthop_global
, "ip",
7337 inet_ntoa(attr
->nexthop
));
7339 if (nexthop_hostname
)
7340 json_object_string_add(json_nexthop_global
,
7344 json_object_string_add(json_nexthop_global
, "afi",
7346 json_object_boolean_true_add(json_nexthop_global
,
7351 snprintf(buf
, sizeof(buf
), "%s%s",
7352 nexthop_hostname
? nexthop_hostname
7353 : inet_ntoa(attr
->nexthop
),
7355 vty_out(vty
, "%-16s", buf
);
7360 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7365 json_nexthop_global
= json_object_new_object();
7366 json_object_string_add(
7367 json_nexthop_global
, "ip",
7368 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7371 if (nexthop_hostname
)
7372 json_object_string_add(json_nexthop_global
,
7376 json_object_string_add(json_nexthop_global
, "afi",
7378 json_object_string_add(json_nexthop_global
, "scope",
7381 /* We display both LL & GL if both have been
7383 if ((attr
->mp_nexthop_len
7384 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7385 || (path
->peer
->conf_if
)) {
7386 json_nexthop_ll
= json_object_new_object();
7387 json_object_string_add(
7388 json_nexthop_ll
, "ip",
7390 &attr
->mp_nexthop_local
, buf
,
7393 if (nexthop_hostname
)
7394 json_object_string_add(
7395 json_nexthop_ll
, "hostname",
7398 json_object_string_add(json_nexthop_ll
, "afi",
7400 json_object_string_add(json_nexthop_ll
, "scope",
7403 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7404 &attr
->mp_nexthop_local
)
7406 && !attr
->mp_nexthop_prefer_global
)
7407 json_object_boolean_true_add(
7408 json_nexthop_ll
, "used");
7410 json_object_boolean_true_add(
7411 json_nexthop_global
, "used");
7413 json_object_boolean_true_add(
7414 json_nexthop_global
, "used");
7416 /* Display LL if LL/Global both in table unless
7417 * prefer-global is set */
7418 if (((attr
->mp_nexthop_len
7419 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7420 && !attr
->mp_nexthop_prefer_global
)
7421 || (path
->peer
->conf_if
)) {
7422 if (path
->peer
->conf_if
) {
7423 len
= vty_out(vty
, "%s",
7424 path
->peer
->conf_if
);
7425 len
= 16 - len
; /* len of IPv6
7431 vty_out(vty
, "\n%*s", 36, " ");
7433 vty_out(vty
, "%*s", len
, " ");
7441 &attr
->mp_nexthop_local
,
7447 vty_out(vty
, "\n%*s", 36, " ");
7449 vty_out(vty
, "%*s", len
, " ");
7458 &attr
->mp_nexthop_global
,
7464 vty_out(vty
, "\n%*s", 36, " ");
7466 vty_out(vty
, "%*s", len
, " ");
7472 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7476 * Adding "metric" field to match with corresponding
7477 * CLI. "med" will be deprecated in future.
7479 json_object_int_add(json_path
, "med", attr
->med
);
7480 json_object_int_add(json_path
, "metric", attr
->med
);
7482 vty_out(vty
, "%10u", attr
->med
);
7483 else if (!json_paths
)
7487 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7491 * Adding "locPrf" field to match with corresponding
7492 * CLI. "localPref" will be deprecated in future.
7494 json_object_int_add(json_path
, "localpref",
7496 json_object_int_add(json_path
, "locPrf",
7499 vty_out(vty
, "%7u", attr
->local_pref
);
7500 else if (!json_paths
)
7504 json_object_int_add(json_path
, "weight", attr
->weight
);
7506 vty_out(vty
, "%7u ", attr
->weight
);
7510 json_object_string_add(
7511 json_path
, "peerId",
7512 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7520 * Adding "path" field to match with corresponding
7521 * CLI. "aspath" will be deprecated in future.
7523 json_object_string_add(json_path
, "aspath",
7525 json_object_string_add(json_path
, "path",
7528 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7533 json_object_string_add(json_path
, "origin",
7534 bgp_origin_long_str
[attr
->origin
]);
7536 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7539 if (safi
== SAFI_EVPN
&&
7540 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7541 json_ext_community
= json_object_new_object();
7542 json_object_string_add(json_ext_community
,
7544 attr
->ecommunity
->str
);
7545 json_object_object_add(json_path
,
7546 "extendedCommunity",
7547 json_ext_community
);
7551 json_object_boolean_true_add(json_path
,
7552 "announceNexthopSelf");
7553 if (nexthop_othervrf
) {
7554 json_object_string_add(json_path
, "nhVrfName",
7557 json_object_int_add(json_path
, "nhVrfId",
7558 ((nexthop_vrfid
== VRF_UNKNOWN
)
7560 : (int)nexthop_vrfid
));
7565 if (json_nexthop_global
|| json_nexthop_ll
) {
7566 json_nexthops
= json_object_new_array();
7568 if (json_nexthop_global
)
7569 json_object_array_add(json_nexthops
,
7570 json_nexthop_global
);
7572 if (json_nexthop_ll
)
7573 json_object_array_add(json_nexthops
,
7576 json_object_object_add(json_path
, "nexthops",
7580 json_object_array_add(json_paths
, json_path
);
7584 if (safi
== SAFI_EVPN
&&
7585 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7586 vty_out(vty
, "%*s", 20, " ");
7587 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7591 /* prints an additional line, indented, with VNC info, if
7593 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7594 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7599 /* called from terminal list command */
7600 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7601 safi_t safi
, bool use_json
, json_object
*json_ar
)
7603 json_object
*json_status
= NULL
;
7604 json_object
*json_net
= NULL
;
7607 /* Route status display. */
7609 json_status
= json_object_new_object();
7610 json_net
= json_object_new_object();
7617 /* print prefix and mask */
7619 if (safi
== SAFI_EVPN
)
7620 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7621 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7622 json_object_string_add(
7623 json_net
, "addrPrefix",
7624 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7626 json_object_int_add(json_net
, "prefixLen",
7628 prefix2str(p
, buff
, PREFIX_STRLEN
);
7629 json_object_string_add(json_net
, "network", buff
);
7632 route_vty_out_route(p
, vty
, NULL
);
7634 /* Print attribute */
7637 if (p
->family
== AF_INET
7638 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7639 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7640 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7641 json_object_string_add(
7642 json_net
, "nextHop",
7644 attr
->mp_nexthop_global_in
));
7646 json_object_string_add(
7647 json_net
, "nextHop",
7648 inet_ntoa(attr
->nexthop
));
7649 } else if (p
->family
== AF_INET6
7650 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7653 json_object_string_add(
7654 json_net
, "nextHopGlobal",
7656 &attr
->mp_nexthop_global
, buf
,
7658 } else if (p
->family
== AF_EVPN
&&
7659 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7660 json_object_string_add(json_net
,
7661 "nextHop", inet_ntoa(
7662 attr
->mp_nexthop_global_in
));
7665 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7666 json_object_int_add(json_net
, "metric",
7669 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7672 * Adding "locPrf" field to match with
7673 * corresponding CLI. "localPref" will be
7674 * deprecated in future.
7676 json_object_int_add(json_net
, "localPref",
7678 json_object_int_add(json_net
, "locPrf",
7682 json_object_int_add(json_net
, "weight", attr
->weight
);
7688 * Adding "path" field to match with
7689 * corresponding CLI. "localPref" will be
7690 * deprecated in future.
7692 json_object_string_add(json_net
, "asPath",
7694 json_object_string_add(json_net
, "path",
7699 json_object_string_add(json_net
, "bgpOriginCode",
7700 bgp_origin_str
[attr
->origin
]);
7702 if (p
->family
== AF_INET
7703 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7704 || safi
== SAFI_EVPN
7705 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7706 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7707 || safi
== SAFI_EVPN
)
7708 vty_out(vty
, "%-16s",
7710 attr
->mp_nexthop_global_in
));
7712 vty_out(vty
, "%-16s",
7713 inet_ntoa(attr
->nexthop
));
7714 } else if (p
->family
== AF_INET6
7715 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7722 &attr
->mp_nexthop_global
, buf
,
7726 vty_out(vty
, "\n%*s", 36, " ");
7728 vty_out(vty
, "%*s", len
, " ");
7731 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7732 vty_out(vty
, "%10u", attr
->med
);
7736 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7737 vty_out(vty
, "%7u", attr
->local_pref
);
7741 vty_out(vty
, "%7u ", attr
->weight
);
7745 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7748 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7752 json_object_boolean_true_add(json_status
, "*");
7753 json_object_boolean_true_add(json_status
, ">");
7754 json_object_object_add(json_net
, "appliedStatusSymbols",
7757 prefix2str(p
, buff
, PREFIX_STRLEN
);
7758 json_object_object_add(json_ar
, buff
, json_net
);
7763 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7764 struct bgp_path_info
*path
, int display
, safi_t safi
,
7767 json_object
*json_out
= NULL
;
7769 mpls_label_t label
= MPLS_INVALID_LABEL
;
7775 json_out
= json_object_new_object();
7777 /* short status lead text */
7778 route_vty_short_status_out(vty
, path
, json_out
);
7780 /* print prefix and mask */
7783 route_vty_out_route(p
, vty
, NULL
);
7785 vty_out(vty
, "%*s", 17, " ");
7788 /* Print attribute */
7790 if (((p
->family
== AF_INET
)
7791 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7792 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7793 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7794 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7795 || safi
== SAFI_EVPN
) {
7797 json_object_string_add(
7798 json_out
, "mpNexthopGlobalIn",
7799 inet_ntoa(attr
->mp_nexthop_global_in
));
7801 vty_out(vty
, "%-16s",
7802 inet_ntoa(attr
->mp_nexthop_global_in
));
7805 json_object_string_add(
7806 json_out
, "nexthop",
7807 inet_ntoa(attr
->nexthop
));
7809 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
7811 } else if (((p
->family
== AF_INET6
)
7812 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7813 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7814 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7817 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7819 json_object_string_add(
7820 json_out
, "mpNexthopGlobalIn",
7822 &attr
->mp_nexthop_global
,
7823 buf_a
, sizeof(buf_a
)));
7827 &attr
->mp_nexthop_global
,
7828 buf_a
, sizeof(buf_a
)));
7829 } else if (attr
->mp_nexthop_len
7830 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7831 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
7832 &attr
->mp_nexthop_global
,
7833 &attr
->mp_nexthop_local
);
7835 json_object_string_add(json_out
,
7836 "mpNexthopGlobalLocal",
7839 vty_out(vty
, "%s", buf_a
);
7843 label
= decode_label(&path
->extra
->label
[0]);
7845 if (bgp_is_valid_label(&label
)) {
7847 json_object_int_add(json_out
, "notag", label
);
7848 json_object_array_add(json
, json_out
);
7850 vty_out(vty
, "notag/%d", label
);
7856 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7857 struct bgp_path_info
*path
, int display
,
7858 json_object
*json_paths
)
7861 char buf
[BUFSIZ
] = {0};
7862 json_object
*json_path
= NULL
;
7863 json_object
*json_nexthop
= NULL
;
7864 json_object
*json_overlay
= NULL
;
7870 json_path
= json_object_new_object();
7871 json_overlay
= json_object_new_object();
7872 json_nexthop
= json_object_new_object();
7875 /* short status lead text */
7876 route_vty_short_status_out(vty
, path
, json_path
);
7878 /* print prefix and mask */
7880 route_vty_out_route(p
, vty
, json_path
);
7882 vty_out(vty
, "%*s", 17, " ");
7884 /* Print attribute */
7887 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7891 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
7893 vty_out(vty
, "%-16s", buf
);
7895 json_object_string_add(json_nexthop
, "ip", buf
);
7897 json_object_string_add(json_nexthop
, "afi", "ipv4");
7899 json_object_object_add(json_path
, "nexthop",
7904 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
7905 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
7907 vty_out(vty
, "%s(%s)", buf
, buf1
);
7909 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
7911 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
7914 json_object_string_add(json_nexthop
, "afi", "ipv6");
7916 json_object_object_add(json_path
, "nexthop",
7924 json_object_string_add(json_nexthop
, "Error",
7925 "Unsupported address-family");
7929 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7932 vty_out(vty
, "%s", str
);
7934 json_object_string_add(json_overlay
, "esi", str
);
7936 XFREE(MTYPE_TMP
, str
);
7938 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7939 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
7941 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7942 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7947 vty_out(vty
, "/%s", buf
);
7949 json_object_string_add(json_overlay
, "gw", buf
);
7951 if (attr
->ecommunity
) {
7953 struct ecommunity_val
*routermac
= ecommunity_lookup(
7954 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7955 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7958 mac
= ecom_mac2str((char *)routermac
->val
);
7961 vty_out(vty
, "/%s", (char *)mac
);
7963 json_object_string_add(json_overlay
, "rmac",
7966 XFREE(MTYPE_TMP
, mac
);
7973 json_object_object_add(json_path
, "overlay", json_overlay
);
7975 json_object_array_add(json_paths
, json_path
);
7979 /* dampening route */
7980 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7981 struct bgp_path_info
*path
, int display
, afi_t afi
,
7982 safi_t safi
, bool use_json
, json_object
*json
)
7986 char timebuf
[BGP_UPTIME_LEN
];
7988 /* short status lead text */
7989 route_vty_short_status_out(vty
, path
, json
);
7991 /* print prefix and mask */
7994 route_vty_out_route(p
, vty
, NULL
);
7996 vty_out(vty
, "%*s", 17, " ");
7999 len
= vty_out(vty
, "%s", path
->peer
->host
);
8003 vty_out(vty
, "\n%*s", 34, " ");
8006 json_object_int_add(json
, "peerHost", len
);
8008 vty_out(vty
, "%*s", len
, " ");
8012 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8013 safi
, use_json
, json
);
8016 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8017 BGP_UPTIME_LEN
, afi
, safi
,
8020 /* Print attribute */
8026 json_object_string_add(json
, "asPath",
8029 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8034 json_object_string_add(json
, "origin",
8035 bgp_origin_str
[attr
->origin
]);
8037 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8044 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8045 struct bgp_path_info
*path
, int display
, afi_t afi
,
8046 safi_t safi
, bool use_json
, json_object
*json
)
8049 struct bgp_damp_info
*bdi
;
8050 char timebuf
[BGP_UPTIME_LEN
];
8056 bdi
= path
->extra
->damp_info
;
8058 /* short status lead text */
8059 route_vty_short_status_out(vty
, path
, json
);
8061 /* print prefix and mask */
8064 route_vty_out_route(p
, vty
, NULL
);
8066 vty_out(vty
, "%*s", 17, " ");
8069 len
= vty_out(vty
, "%s", path
->peer
->host
);
8073 vty_out(vty
, "\n%*s", 33, " ");
8076 json_object_int_add(json
, "peerHost", len
);
8078 vty_out(vty
, "%*s", len
, " ");
8081 len
= vty_out(vty
, "%d", bdi
->flap
);
8088 json_object_int_add(json
, "bdiFlap", len
);
8090 vty_out(vty
, "%*s", len
, " ");
8094 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8097 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8098 BGP_UPTIME_LEN
, 0, NULL
));
8100 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8101 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8103 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8104 BGP_UPTIME_LEN
, afi
, safi
,
8108 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8109 BGP_UPTIME_LEN
, afi
,
8110 safi
, use_json
, json
));
8113 vty_out(vty
, "%*s ", 8, " ");
8116 /* Print attribute */
8122 json_object_string_add(json
, "asPath",
8125 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8130 json_object_string_add(json
, "origin",
8131 bgp_origin_str
[attr
->origin
]);
8133 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8139 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8140 int *first
, const char *header
,
8141 json_object
*json_adv_to
)
8143 char buf1
[INET6_ADDRSTRLEN
];
8144 json_object
*json_peer
= NULL
;
8147 /* 'advertised-to' is a dictionary of peers we have advertised
8149 * prefix too. The key is the peer's IP or swpX, the value is
8151 * hostname if we know it and "" if not.
8153 json_peer
= json_object_new_object();
8156 json_object_string_add(json_peer
, "hostname",
8160 json_object_object_add(json_adv_to
, peer
->conf_if
,
8163 json_object_object_add(
8165 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8169 vty_out(vty
, "%s", header
);
8174 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8176 vty_out(vty
, " %s(%s)", peer
->hostname
,
8179 vty_out(vty
, " %s(%s)", peer
->hostname
,
8180 sockunion2str(&peer
->su
, buf1
,
8184 vty_out(vty
, " %s", peer
->conf_if
);
8187 sockunion2str(&peer
->su
, buf1
,
8193 static void route_vty_out_tx_ids(struct vty
*vty
,
8194 struct bgp_addpath_info_data
*d
)
8198 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8199 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8200 d
->addpath_tx_id
[i
],
8201 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8205 static const char *bgp_path_selection_reason2str(
8206 enum bgp_path_selection_reason reason
)
8209 case bgp_path_selection_none
:
8210 return "Nothing to Select";
8212 case bgp_path_selection_first
:
8213 return "First path received";
8215 case bgp_path_selection_evpn_sticky_mac
:
8216 return "EVPN Sticky Mac";
8218 case bgp_path_selection_evpn_seq
:
8219 return "EVPN sequence number";
8221 case bgp_path_selection_evpn_lower_ip
:
8222 return "EVPN lower IP";
8224 case bgp_path_selection_weight
:
8227 case bgp_path_selection_local_pref
:
8228 return "Local Pref";
8230 case bgp_path_selection_local_route
:
8231 return "Local Route";
8233 case bgp_path_selection_confed_as_path
:
8234 return "Confederation based AS Path";
8236 case bgp_path_selection_as_path
:
8239 case bgp_path_selection_origin
:
8242 case bgp_path_selection_med
:
8245 case bgp_path_selection_peer
:
8248 case bgp_path_selection_confed
:
8249 return "Confed Peer Type";
8251 case bgp_path_selection_igp_metric
:
8252 return "IGP Metric";
8254 case bgp_path_selection_older
:
8255 return "Older Path";
8257 case bgp_path_selection_router_id
:
8260 case bgp_path_selection_cluster_length
:
8261 return "Cluser length";
8263 case bgp_path_selection_stale
:
8264 return "Path Staleness";
8266 case bgp_path_selection_local_configured
:
8267 return "Locally configured route";
8269 case bgp_path_selection_neighbor_ip
:
8270 return "Neighbor IP";
8272 case bgp_path_selection_default
:
8273 return "Nothing left to compare";
8276 return "Invalid (internal error)";
8279 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8280 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8281 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8283 char buf
[INET6_ADDRSTRLEN
];
8285 char buf2
[EVPN_ROUTE_STRLEN
];
8286 struct attr
*attr
= path
->attr
;
8287 int sockunion_vty_out(struct vty
*, union sockunion
*);
8289 json_object
*json_bestpath
= NULL
;
8290 json_object
*json_cluster_list
= NULL
;
8291 json_object
*json_cluster_list_list
= NULL
;
8292 json_object
*json_ext_community
= NULL
;
8293 json_object
*json_last_update
= NULL
;
8294 json_object
*json_pmsi
= NULL
;
8295 json_object
*json_nexthop_global
= NULL
;
8296 json_object
*json_nexthop_ll
= NULL
;
8297 json_object
*json_nexthops
= NULL
;
8298 json_object
*json_path
= NULL
;
8299 json_object
*json_peer
= NULL
;
8300 json_object
*json_string
= NULL
;
8301 json_object
*json_adv_to
= NULL
;
8303 struct listnode
*node
, *nnode
;
8305 int addpath_capable
;
8307 unsigned int first_as
;
8309 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8311 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
8314 json_path
= json_object_new_object();
8315 json_peer
= json_object_new_object();
8316 json_nexthop_global
= json_object_new_object();
8324 if (path
->extra
&& path
->extra
->num_labels
) {
8325 bgp_evpn_label2str(path
->extra
->label
,
8326 path
->extra
->num_labels
, tag_buf
,
8329 if (safi
== SAFI_EVPN
) {
8331 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8332 buf2
, sizeof(buf2
));
8333 vty_out(vty
, " Route %s", buf2
);
8334 if (tag_buf
[0] != '\0')
8335 vty_out(vty
, " VNI %s", tag_buf
);
8339 json_object_string_add(json_path
, "VNI",
8344 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8345 struct bgp_path_info
*parent_ri
;
8346 struct bgp_node
*rn
, *prn
;
8348 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8349 rn
= parent_ri
->net
;
8350 if (rn
&& rn
->prn
) {
8352 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8353 buf1
, sizeof(buf1
));
8354 if (is_pi_family_evpn(parent_ri
)) {
8355 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8356 buf2
, sizeof(buf2
));
8357 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8359 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8364 /* Line1 display AS-path, Aggregator */
8367 if (!attr
->aspath
->json
)
8368 aspath_str_update(attr
->aspath
, true);
8369 json_object_lock(attr
->aspath
->json
);
8370 json_object_object_add(json_path
, "aspath",
8371 attr
->aspath
->json
);
8373 if (attr
->aspath
->segments
)
8374 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8376 vty_out(vty
, " Local");
8380 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8382 json_object_boolean_true_add(json_path
, "removed");
8384 vty_out(vty
, ", (removed)");
8387 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8389 json_object_boolean_true_add(json_path
, "stale");
8391 vty_out(vty
, ", (stale)");
8394 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8396 json_object_int_add(json_path
, "aggregatorAs",
8397 attr
->aggregator_as
);
8398 json_object_string_add(
8399 json_path
, "aggregatorId",
8400 inet_ntoa(attr
->aggregator_addr
));
8402 vty_out(vty
, ", (aggregated by %u %s)",
8403 attr
->aggregator_as
,
8404 inet_ntoa(attr
->aggregator_addr
));
8408 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8409 PEER_FLAG_REFLECTOR_CLIENT
)) {
8411 json_object_boolean_true_add(json_path
,
8412 "rxedFromRrClient");
8414 vty_out(vty
, ", (Received from a RR-client)");
8417 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8418 PEER_FLAG_RSERVER_CLIENT
)) {
8420 json_object_boolean_true_add(json_path
,
8421 "rxedFromRsClient");
8423 vty_out(vty
, ", (Received from a RS-client)");
8426 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8428 json_object_boolean_true_add(json_path
,
8429 "dampeningHistoryEntry");
8431 vty_out(vty
, ", (history entry)");
8432 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8434 json_object_boolean_true_add(json_path
,
8435 "dampeningSuppressed");
8437 vty_out(vty
, ", (suppressed due to dampening)");
8443 /* Line2 display Next-hop, Neighbor, Router-id */
8444 /* Display the nexthop */
8445 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8446 || bn
->p
.family
== AF_EVPN
)
8447 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8448 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8449 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8450 || safi
== SAFI_EVPN
) {
8452 json_object_string_add(
8453 json_nexthop_global
, "ip",
8454 inet_ntoa(attr
->mp_nexthop_global_in
));
8456 if (nexthop_hostname
)
8457 json_object_string_add(
8458 json_nexthop_global
, "hostname",
8465 attr
->mp_nexthop_global_in
));
8468 json_object_string_add(
8469 json_nexthop_global
, "ip",
8470 inet_ntoa(attr
->nexthop
));
8472 if (nexthop_hostname
)
8473 json_object_string_add(
8474 json_nexthop_global
, "hostname",
8480 : inet_ntoa(attr
->nexthop
));
8484 json_object_string_add(json_nexthop_global
, "afi",
8488 json_object_string_add(
8489 json_nexthop_global
, "ip",
8490 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8491 buf
, INET6_ADDRSTRLEN
));
8493 if (nexthop_hostname
)
8494 json_object_string_add(json_nexthop_global
,
8498 json_object_string_add(json_nexthop_global
, "afi",
8500 json_object_string_add(json_nexthop_global
, "scope",
8506 : inet_ntop(AF_INET6
,
8507 &attr
->mp_nexthop_global
,
8508 buf
, INET6_ADDRSTRLEN
));
8512 /* Display the IGP cost or 'inaccessible' */
8513 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8515 json_object_boolean_false_add(json_nexthop_global
,
8518 vty_out(vty
, " (inaccessible)");
8520 if (path
->extra
&& path
->extra
->igpmetric
) {
8522 json_object_int_add(json_nexthop_global
,
8524 path
->extra
->igpmetric
);
8526 vty_out(vty
, " (metric %u)",
8527 path
->extra
->igpmetric
);
8530 /* IGP cost is 0, display this only for json */
8533 json_object_int_add(json_nexthop_global
,
8538 json_object_boolean_true_add(json_nexthop_global
,
8542 /* Display peer "from" output */
8543 /* This path was originated locally */
8544 if (path
->peer
== bgp
->peer_self
) {
8546 if (safi
== SAFI_EVPN
8547 || (bn
->p
.family
== AF_INET
8548 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8550 json_object_string_add(json_peer
, "peerId",
8553 vty_out(vty
, " from 0.0.0.0 ");
8556 json_object_string_add(json_peer
, "peerId",
8559 vty_out(vty
, " from :: ");
8563 json_object_string_add(json_peer
, "routerId",
8564 inet_ntoa(bgp
->router_id
));
8566 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8569 /* We RXed this path from one of our peers */
8573 json_object_string_add(json_peer
, "peerId",
8574 sockunion2str(&path
->peer
->su
,
8577 json_object_string_add(json_peer
, "routerId",
8579 &path
->peer
->remote_id
,
8580 buf1
, sizeof(buf1
)));
8582 if (path
->peer
->hostname
)
8583 json_object_string_add(json_peer
, "hostname",
8584 path
->peer
->hostname
);
8586 if (path
->peer
->domainname
)
8587 json_object_string_add(json_peer
, "domainname",
8588 path
->peer
->domainname
);
8590 if (path
->peer
->conf_if
)
8591 json_object_string_add(json_peer
, "interface",
8592 path
->peer
->conf_if
);
8594 if (path
->peer
->conf_if
) {
8595 if (path
->peer
->hostname
8596 && bgp_flag_check(path
->peer
->bgp
,
8597 BGP_FLAG_SHOW_HOSTNAME
))
8598 vty_out(vty
, " from %s(%s)",
8599 path
->peer
->hostname
,
8600 path
->peer
->conf_if
);
8602 vty_out(vty
, " from %s",
8603 path
->peer
->conf_if
);
8605 if (path
->peer
->hostname
8606 && bgp_flag_check(path
->peer
->bgp
,
8607 BGP_FLAG_SHOW_HOSTNAME
))
8608 vty_out(vty
, " from %s(%s)",
8609 path
->peer
->hostname
,
8612 vty_out(vty
, " from %s",
8613 sockunion2str(&path
->peer
->su
,
8618 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8619 vty_out(vty
, " (%s)",
8620 inet_ntoa(attr
->originator_id
));
8622 vty_out(vty
, " (%s)",
8624 &path
->peer
->remote_id
, buf1
,
8630 * Note when vrfid of nexthop is different from that of prefix
8632 if (path
->extra
&& path
->extra
->bgp_orig
) {
8633 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8638 if (path
->extra
->bgp_orig
->inst_type
8639 == BGP_INSTANCE_TYPE_DEFAULT
)
8640 vn
= VRF_DEFAULT_NAME
;
8642 vn
= path
->extra
->bgp_orig
->name
;
8644 json_object_string_add(json_path
, "nhVrfName", vn
);
8646 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8647 json_object_int_add(json_path
, "nhVrfId", -1);
8649 json_object_int_add(json_path
, "nhVrfId",
8650 (int)nexthop_vrfid
);
8653 if (nexthop_vrfid
== VRF_UNKNOWN
)
8654 vty_out(vty
, " vrf ?");
8656 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8662 json_object_boolean_true_add(json_path
,
8663 "announceNexthopSelf");
8665 vty_out(vty
, " announce-nh-self");
8672 /* display the link-local nexthop */
8673 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8675 json_nexthop_ll
= json_object_new_object();
8676 json_object_string_add(
8677 json_nexthop_ll
, "ip",
8678 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8679 buf
, INET6_ADDRSTRLEN
));
8681 if (nexthop_hostname
)
8682 json_object_string_add(json_nexthop_ll
,
8686 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8687 json_object_string_add(json_nexthop_ll
, "scope",
8690 json_object_boolean_true_add(json_nexthop_ll
,
8693 if (!attr
->mp_nexthop_prefer_global
)
8694 json_object_boolean_true_add(json_nexthop_ll
,
8697 json_object_boolean_true_add(
8698 json_nexthop_global
, "used");
8700 vty_out(vty
, " (%s) %s\n",
8701 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8702 buf
, INET6_ADDRSTRLEN
),
8703 attr
->mp_nexthop_prefer_global
8708 /* If we do not have a link-local nexthop then we must flag the
8712 json_object_boolean_true_add(json_nexthop_global
,
8716 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8717 * Int/Ext/Local, Atomic, best */
8719 json_object_string_add(json_path
, "origin",
8720 bgp_origin_long_str
[attr
->origin
]);
8722 vty_out(vty
, " Origin %s",
8723 bgp_origin_long_str
[attr
->origin
]);
8725 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8728 * Adding "metric" field to match with
8729 * corresponding CLI. "med" will be
8730 * deprecated in future.
8732 json_object_int_add(json_path
, "med", attr
->med
);
8733 json_object_int_add(json_path
, "metric", attr
->med
);
8735 vty_out(vty
, ", metric %u", attr
->med
);
8738 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8740 json_object_int_add(json_path
, "localpref",
8743 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8746 if (attr
->weight
!= 0) {
8748 json_object_int_add(json_path
, "weight", attr
->weight
);
8750 vty_out(vty
, ", weight %u", attr
->weight
);
8753 if (attr
->tag
!= 0) {
8755 json_object_int_add(json_path
, "tag", attr
->tag
);
8757 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
8760 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8762 json_object_boolean_false_add(json_path
, "valid");
8764 vty_out(vty
, ", invalid");
8765 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8767 json_object_boolean_true_add(json_path
, "valid");
8769 vty_out(vty
, ", valid");
8772 if (path
->peer
!= bgp
->peer_self
) {
8773 if (path
->peer
->as
== path
->peer
->local_as
) {
8774 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
8776 json_object_string_add(
8780 vty_out(vty
, ", confed-internal");
8783 json_object_string_add(
8784 json_peer
, "type", "internal");
8786 vty_out(vty
, ", internal");
8789 if (bgp_confederation_peers_check(bgp
,
8792 json_object_string_add(
8796 vty_out(vty
, ", confed-external");
8799 json_object_string_add(
8800 json_peer
, "type", "external");
8802 vty_out(vty
, ", external");
8805 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8807 json_object_boolean_true_add(json_path
, "aggregated");
8808 json_object_boolean_true_add(json_path
, "local");
8810 vty_out(vty
, ", aggregated, local");
8812 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8814 json_object_boolean_true_add(json_path
, "sourced");
8816 vty_out(vty
, ", sourced");
8819 json_object_boolean_true_add(json_path
, "sourced");
8820 json_object_boolean_true_add(json_path
, "local");
8822 vty_out(vty
, ", sourced, local");
8826 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8828 json_object_boolean_true_add(json_path
,
8831 vty_out(vty
, ", atomic-aggregate");
8834 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8835 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8836 && bgp_path_info_mpath_count(path
))) {
8838 json_object_boolean_true_add(json_path
, "multipath");
8840 vty_out(vty
, ", multipath");
8843 // Mark the bestpath(s)
8844 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8845 first_as
= aspath_get_first_as(attr
->aspath
);
8849 json_bestpath
= json_object_new_object();
8850 json_object_int_add(json_bestpath
, "bestpathFromAs",
8854 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
8856 vty_out(vty
, ", bestpath-from-AS Local");
8860 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8863 json_bestpath
= json_object_new_object();
8864 json_object_boolean_true_add(json_bestpath
, "overall");
8865 json_object_string_add(
8866 json_bestpath
, "selectionReason",
8867 bgp_path_selection_reason2str(bn
->reason
));
8869 vty_out(vty
, ", best");
8870 vty_out(vty
, " (%s)",
8871 bgp_path_selection_reason2str(bn
->reason
));
8876 json_object_object_add(json_path
, "bestpath", json_bestpath
);
8881 /* Line 4 display Community */
8882 if (attr
->community
) {
8884 if (!attr
->community
->json
)
8885 community_str(attr
->community
, true);
8886 json_object_lock(attr
->community
->json
);
8887 json_object_object_add(json_path
, "community",
8888 attr
->community
->json
);
8890 vty_out(vty
, " Community: %s\n",
8891 attr
->community
->str
);
8895 /* Line 5 display Extended-community */
8896 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8898 json_ext_community
= json_object_new_object();
8899 json_object_string_add(json_ext_community
, "string",
8900 attr
->ecommunity
->str
);
8901 json_object_object_add(json_path
, "extendedCommunity",
8902 json_ext_community
);
8904 vty_out(vty
, " Extended Community: %s\n",
8905 attr
->ecommunity
->str
);
8909 /* Line 6 display Large community */
8910 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8912 if (!attr
->lcommunity
->json
)
8913 lcommunity_str(attr
->lcommunity
, true);
8914 json_object_lock(attr
->lcommunity
->json
);
8915 json_object_object_add(json_path
, "largeCommunity",
8916 attr
->lcommunity
->json
);
8918 vty_out(vty
, " Large Community: %s\n",
8919 attr
->lcommunity
->str
);
8923 /* Line 7 display Originator, Cluster-id */
8924 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8925 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8926 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8928 json_object_string_add(
8929 json_path
, "originatorId",
8930 inet_ntoa(attr
->originator_id
));
8932 vty_out(vty
, " Originator: %s",
8933 inet_ntoa(attr
->originator_id
));
8936 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8940 json_cluster_list
= json_object_new_object();
8941 json_cluster_list_list
=
8942 json_object_new_array();
8944 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8946 json_string
= json_object_new_string(
8947 inet_ntoa(attr
->cluster
8949 json_object_array_add(
8950 json_cluster_list_list
,
8955 * struct cluster_list does not have
8956 * "str" variable like aspath and community
8957 * do. Add this someday if someone asks
8959 * json_object_string_add(json_cluster_list,
8960 * "string", attr->cluster->str);
8962 json_object_object_add(json_cluster_list
,
8964 json_cluster_list_list
);
8965 json_object_object_add(json_path
, "clusterList",
8968 vty_out(vty
, ", Cluster list: ");
8970 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8973 inet_ntoa(attr
->cluster
8983 if (path
->extra
&& path
->extra
->damp_info
)
8984 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
8987 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8988 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
8989 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8992 json_object_int_add(json_path
, "remoteLabel", label
);
8994 vty_out(vty
, " Remote label: %d\n", label
);
8998 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
9000 json_object_int_add(json_path
, "labelIndex",
9003 vty_out(vty
, " Label Index: %d\n",
9007 /* Line 8 display Addpath IDs */
9008 if (path
->addpath_rx_id
9009 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9011 json_object_int_add(json_path
, "addpathRxId",
9012 path
->addpath_rx_id
);
9014 /* Keep backwards compatibility with the old API
9015 * by putting TX All's ID in the old field
9017 json_object_int_add(
9018 json_path
, "addpathTxId",
9020 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9022 /* ... but create a specific field for each
9025 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9026 json_object_int_add(
9028 bgp_addpath_names(i
)->id_json_name
,
9029 path
->tx_addpath
.addpath_tx_id
[i
]);
9032 vty_out(vty
, " AddPath ID: RX %u, ",
9033 path
->addpath_rx_id
);
9035 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9039 /* If we used addpath to TX a non-bestpath we need to display
9040 * "Advertised to" on a path-by-path basis
9042 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9045 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9047 bgp_addpath_encode_tx(peer
, afi
, safi
);
9048 has_adj
= bgp_adj_out_lookup(
9050 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9051 &path
->tx_addpath
));
9053 if ((addpath_capable
&& has_adj
)
9054 || (!addpath_capable
&& has_adj
9055 && CHECK_FLAG(path
->flags
,
9056 BGP_PATH_SELECTED
))) {
9057 if (json_path
&& !json_adv_to
)
9058 json_adv_to
= json_object_new_object();
9060 route_vty_out_advertised_to(
9062 " Advertised to:", json_adv_to
);
9068 json_object_object_add(
9069 json_path
, "advertisedTo", json_adv_to
);
9078 /* Line 9 display Uptime */
9079 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9081 json_last_update
= json_object_new_object();
9082 json_object_int_add(json_last_update
, "epoch", tbuf
);
9083 json_object_string_add(json_last_update
, "string",
9085 json_object_object_add(json_path
, "lastUpdate",
9088 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9090 /* Line 10 display PMSI tunnel attribute, if present */
9091 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9093 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9094 PMSI_TNLTYPE_STR_DEFAULT
);
9097 json_pmsi
= json_object_new_object();
9098 json_object_string_add(json_pmsi
, "tunnelType", str
);
9099 json_object_int_add(json_pmsi
, "label",
9100 label2vni(&attr
->label
));
9101 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9103 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9104 str
, label2vni(&attr
->label
));
9107 /* We've constructed the json object for this path, add it to the json
9111 if (json_nexthop_global
|| json_nexthop_ll
) {
9112 json_nexthops
= json_object_new_array();
9114 if (json_nexthop_global
)
9115 json_object_array_add(json_nexthops
,
9116 json_nexthop_global
);
9118 if (json_nexthop_ll
)
9119 json_object_array_add(json_nexthops
,
9122 json_object_object_add(json_path
, "nexthops",
9126 json_object_object_add(json_path
, "peer", json_peer
);
9127 json_object_array_add(json_paths
, json_path
);
9131 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9132 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9133 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9135 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9136 const char *prefix_list_str
, afi_t afi
,
9137 safi_t safi
, enum bgp_show_type type
);
9138 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9139 const char *filter
, afi_t afi
, safi_t safi
,
9140 enum bgp_show_type type
);
9141 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9142 const char *rmap_str
, afi_t afi
, safi_t safi
,
9143 enum bgp_show_type type
);
9144 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9145 const char *com
, int exact
, afi_t afi
,
9147 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9148 const char *prefix
, afi_t afi
, safi_t safi
,
9149 enum bgp_show_type type
);
9150 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9151 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
9153 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9154 const char *comstr
, int exact
, afi_t afi
,
9155 safi_t safi
, bool use_json
);
9158 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9159 struct bgp_table
*table
, enum bgp_show_type type
,
9160 void *output_arg
, bool use_json
, char *rd
,
9161 int is_last
, unsigned long *output_cum
,
9162 unsigned long *total_cum
,
9163 unsigned long *json_header_depth
)
9165 struct bgp_path_info
*pi
;
9166 struct bgp_node
*rn
;
9169 unsigned long output_count
= 0;
9170 unsigned long total_count
= 0;
9173 json_object
*json_paths
= NULL
;
9176 if (output_cum
&& *output_cum
!= 0)
9179 if (use_json
&& !*json_header_depth
) {
9181 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9182 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9183 " \"localAS\": %u,\n \"routes\": { ",
9184 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9185 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9188 table
->version
, inet_ntoa(bgp
->router_id
),
9189 bgp
->default_local_pref
, bgp
->as
);
9190 *json_header_depth
= 2;
9192 vty_out(vty
, " \"routeDistinguishers\" : {");
9193 ++*json_header_depth
;
9197 if (use_json
&& rd
) {
9198 vty_out(vty
, " \"%s\" : { ", rd
);
9201 /* Start processing of routes. */
9202 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9203 pi
= bgp_node_get_bgp_path_info(rn
);
9209 json_paths
= json_object_new_array();
9213 for (; pi
; pi
= pi
->next
) {
9215 if (type
== bgp_show_type_flap_statistics
9216 || type
== bgp_show_type_flap_neighbor
9217 || type
== bgp_show_type_dampend_paths
9218 || type
== bgp_show_type_damp_neighbor
) {
9219 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9222 if (type
== bgp_show_type_regexp
) {
9223 regex_t
*regex
= output_arg
;
9225 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9229 if (type
== bgp_show_type_prefix_list
) {
9230 struct prefix_list
*plist
= output_arg
;
9232 if (prefix_list_apply(plist
, &rn
->p
)
9236 if (type
== bgp_show_type_filter_list
) {
9237 struct as_list
*as_list
= output_arg
;
9239 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9240 != AS_FILTER_PERMIT
)
9243 if (type
== bgp_show_type_route_map
) {
9244 struct route_map
*rmap
= output_arg
;
9245 struct bgp_path_info path
;
9246 struct attr dummy_attr
;
9247 route_map_result_t ret
;
9249 dummy_attr
= *pi
->attr
;
9251 path
.peer
= pi
->peer
;
9252 path
.attr
= &dummy_attr
;
9254 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9256 if (ret
== RMAP_DENYMATCH
)
9259 if (type
== bgp_show_type_neighbor
9260 || type
== bgp_show_type_flap_neighbor
9261 || type
== bgp_show_type_damp_neighbor
) {
9262 union sockunion
*su
= output_arg
;
9264 if (pi
->peer
== NULL
9265 || pi
->peer
->su_remote
== NULL
9266 || !sockunion_same(pi
->peer
->su_remote
, su
))
9269 if (type
== bgp_show_type_cidr_only
) {
9270 uint32_t destination
;
9272 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9273 if (IN_CLASSC(destination
)
9274 && rn
->p
.prefixlen
== 24)
9276 if (IN_CLASSB(destination
)
9277 && rn
->p
.prefixlen
== 16)
9279 if (IN_CLASSA(destination
)
9280 && rn
->p
.prefixlen
== 8)
9283 if (type
== bgp_show_type_prefix_longer
) {
9285 if (!prefix_match(p
, &rn
->p
))
9288 if (type
== bgp_show_type_community_all
) {
9289 if (!pi
->attr
->community
)
9292 if (type
== bgp_show_type_community
) {
9293 struct community
*com
= output_arg
;
9295 if (!pi
->attr
->community
9296 || !community_match(pi
->attr
->community
,
9300 if (type
== bgp_show_type_community_exact
) {
9301 struct community
*com
= output_arg
;
9303 if (!pi
->attr
->community
9304 || !community_cmp(pi
->attr
->community
, com
))
9307 if (type
== bgp_show_type_community_list
) {
9308 struct community_list
*list
= output_arg
;
9310 if (!community_list_match(pi
->attr
->community
,
9314 if (type
== bgp_show_type_community_list_exact
) {
9315 struct community_list
*list
= output_arg
;
9317 if (!community_list_exact_match(
9318 pi
->attr
->community
, list
))
9321 if (type
== bgp_show_type_lcommunity
) {
9322 struct lcommunity
*lcom
= output_arg
;
9324 if (!pi
->attr
->lcommunity
9325 || !lcommunity_match(pi
->attr
->lcommunity
,
9330 if (type
== bgp_show_type_lcommunity_exact
) {
9331 struct lcommunity
*lcom
= output_arg
;
9333 if (!pi
->attr
->lcommunity
9334 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9338 if (type
== bgp_show_type_lcommunity_list
) {
9339 struct community_list
*list
= output_arg
;
9341 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9346 == bgp_show_type_lcommunity_list_exact
) {
9347 struct community_list
*list
= output_arg
;
9349 if (!lcommunity_list_exact_match(
9350 pi
->attr
->lcommunity
, list
))
9353 if (type
== bgp_show_type_lcommunity_all
) {
9354 if (!pi
->attr
->lcommunity
)
9357 if (type
== bgp_show_type_dampend_paths
9358 || type
== bgp_show_type_damp_neighbor
) {
9359 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9360 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9364 if (!use_json
&& header
) {
9365 vty_out(vty
, "BGP table version is %" PRIu64
9366 ", local router ID is %s, vrf id ",
9368 inet_ntoa(bgp
->router_id
));
9369 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9370 vty_out(vty
, "%s", VRFID_NONE_STR
);
9372 vty_out(vty
, "%u", bgp
->vrf_id
);
9374 vty_out(vty
, "Default local pref %u, ",
9375 bgp
->default_local_pref
);
9376 vty_out(vty
, "local AS %u\n", bgp
->as
);
9377 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9378 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9379 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9380 if (type
== bgp_show_type_dampend_paths
9381 || type
== bgp_show_type_damp_neighbor
)
9382 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9383 else if (type
== bgp_show_type_flap_statistics
9384 || type
== bgp_show_type_flap_neighbor
)
9385 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9387 vty_out(vty
, BGP_SHOW_HEADER
);
9390 if (rd
!= NULL
&& !display
&& !output_count
) {
9393 "Route Distinguisher: %s\n",
9396 if (type
== bgp_show_type_dampend_paths
9397 || type
== bgp_show_type_damp_neighbor
)
9398 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9399 safi
, use_json
, json_paths
);
9400 else if (type
== bgp_show_type_flap_statistics
9401 || type
== bgp_show_type_flap_neighbor
)
9402 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9403 safi
, use_json
, json_paths
);
9405 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9417 if (p
->family
== AF_FLOWSPEC
) {
9418 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9420 bgp_fs_nlri_get_string((unsigned char *)
9421 p
->u
.prefix_flowspec
.ptr
,
9422 p
->u
.prefix_flowspec
9425 NLRI_STRING_FORMAT_MIN
,
9428 vty_out(vty
, "\"%s/%d\": ",
9430 p
->u
.prefix_flowspec
.prefixlen
);
9432 vty_out(vty
, ",\"%s/%d\": ",
9434 p
->u
.prefix_flowspec
.prefixlen
);
9436 prefix2str(p
, buf2
, sizeof(buf2
));
9438 vty_out(vty
, "\"%s\": ", buf2
);
9440 vty_out(vty
, ",\"%s\": ", buf2
);
9443 json_object_to_json_string_ext(
9444 json_paths
, JSON_C_TO_STRING_PRETTY
));
9445 json_object_free(json_paths
);
9449 json_object_free(json_paths
);
9453 output_count
+= *output_cum
;
9454 *output_cum
= output_count
;
9457 total_count
+= *total_cum
;
9458 *total_cum
= total_count
;
9462 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9466 for (i
= 0; i
< *json_header_depth
; ++i
)
9467 vty_out(vty
, " } ");
9472 /* No route is displayed */
9473 if (output_count
== 0) {
9474 if (type
== bgp_show_type_normal
)
9476 "No BGP prefixes displayed, %ld exist\n",
9480 "\nDisplayed %ld routes and %ld total paths\n",
9481 output_count
, total_count
);
9488 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9489 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9490 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9492 struct bgp_node
*rn
, *next
;
9493 unsigned long output_cum
= 0;
9494 unsigned long total_cum
= 0;
9495 unsigned long json_header_depth
= 0;
9496 struct bgp_table
*itable
;
9499 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9501 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9502 next
= bgp_route_next(rn
);
9503 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9506 itable
= bgp_node_get_bgp_table_info(rn
);
9507 if (itable
!= NULL
) {
9508 struct prefix_rd prd
;
9509 char rd
[RD_ADDRSTRLEN
];
9511 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9512 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9513 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9514 use_json
, rd
, next
== NULL
, &output_cum
,
9515 &total_cum
, &json_header_depth
);
9521 if (output_cum
== 0)
9522 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9526 "\nDisplayed %ld routes and %ld total paths\n",
9527 output_cum
, total_cum
);
9531 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9532 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9534 struct bgp_table
*table
;
9535 unsigned long json_header_depth
= 0;
9538 bgp
= bgp_get_default();
9543 vty_out(vty
, "No BGP process is configured\n");
9545 vty_out(vty
, "{}\n");
9549 table
= bgp
->rib
[afi
][safi
];
9550 /* use MPLS and ENCAP specific shows until they are merged */
9551 if (safi
== SAFI_MPLS_VPN
) {
9552 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9553 output_arg
, use_json
);
9556 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9557 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9558 output_arg
, use_json
,
9561 /* labeled-unicast routes live in the unicast table */
9562 else if (safi
== SAFI_LABELED_UNICAST
)
9563 safi
= SAFI_UNICAST
;
9565 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9566 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9569 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9570 safi_t safi
, bool use_json
)
9572 struct listnode
*node
, *nnode
;
9575 bool route_output
= false;
9578 vty_out(vty
, "{\n");
9580 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9581 route_output
= true;
9584 vty_out(vty
, ",\n");
9588 vty_out(vty
, "\"%s\":",
9589 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9593 vty_out(vty
, "\nInstance %s:\n",
9594 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9598 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9603 vty_out(vty
, "}\n");
9604 else if (!route_output
)
9605 vty_out(vty
, "%% BGP instance not found\n");
9608 /* Header of detailed BGP route information */
9609 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9610 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9611 afi_t afi
, safi_t safi
, json_object
*json
)
9613 struct bgp_path_info
*pi
;
9616 struct listnode
*node
, *nnode
;
9617 char buf1
[RD_ADDRSTRLEN
];
9618 char buf2
[INET6_ADDRSTRLEN
];
9619 char buf3
[EVPN_ROUTE_STRLEN
];
9620 char prefix_str
[BUFSIZ
];
9625 int route_filter_translated_v4
= 0;
9626 int route_filter_v4
= 0;
9627 int route_filter_translated_v6
= 0;
9628 int route_filter_v6
= 0;
9631 int accept_own_nexthop
= 0;
9634 int no_advertise
= 0;
9638 int has_valid_label
= 0;
9639 mpls_label_t label
= 0;
9640 json_object
*json_adv_to
= NULL
;
9643 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9645 if (has_valid_label
)
9646 label
= label_pton(&rn
->local_label
);
9648 if (safi
== SAFI_EVPN
) {
9651 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9652 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9653 : "", prd
? ":" : "",
9654 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9655 buf3
, sizeof(buf3
)));
9657 json_object_string_add(json
, "rd",
9658 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9660 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9664 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9665 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9666 ? prefix_rd2str(prd
, buf1
,
9669 safi
== SAFI_MPLS_VPN
? ":" : "",
9670 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9675 json_object_string_add(json
, "prefix",
9676 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9679 if (has_valid_label
) {
9681 json_object_int_add(json
, "localLabel", label
);
9683 vty_out(vty
, "Local label: %d\n", label
);
9687 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9688 vty_out(vty
, "not allocated\n");
9690 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9692 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9694 if (pi
->extra
&& pi
->extra
->suppress
)
9697 if (pi
->attr
->community
== NULL
)
9700 no_advertise
+= community_include(
9701 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9702 no_export
+= community_include(pi
->attr
->community
,
9703 COMMUNITY_NO_EXPORT
);
9704 local_as
+= community_include(pi
->attr
->community
,
9705 COMMUNITY_LOCAL_AS
);
9706 accept_own
+= community_include(pi
->attr
->community
,
9707 COMMUNITY_ACCEPT_OWN
);
9708 route_filter_translated_v4
+= community_include(
9709 pi
->attr
->community
,
9710 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9711 route_filter_translated_v6
+= community_include(
9712 pi
->attr
->community
,
9713 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9714 route_filter_v4
+= community_include(
9715 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9716 route_filter_v6
+= community_include(
9717 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9718 llgr_stale
+= community_include(pi
->attr
->community
,
9719 COMMUNITY_LLGR_STALE
);
9720 no_llgr
+= community_include(pi
->attr
->community
,
9722 accept_own_nexthop
+=
9723 community_include(pi
->attr
->community
,
9724 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9725 blackhole
+= community_include(pi
->attr
->community
,
9726 COMMUNITY_BLACKHOLE
);
9727 no_peer
+= community_include(pi
->attr
->community
,
9733 vty_out(vty
, "Paths: (%d available", count
);
9735 vty_out(vty
, ", best #%d", best
);
9736 if (safi
== SAFI_UNICAST
) {
9737 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9738 vty_out(vty
, ", table %s",
9741 vty_out(vty
, ", vrf %s",
9745 vty_out(vty
, ", no best path");
9749 ", accept own local route exported and imported in different VRF");
9750 else if (route_filter_translated_v4
)
9752 ", mark translated RTs for VPNv4 route filtering");
9753 else if (route_filter_v4
)
9755 ", attach RT as-is for VPNv4 route filtering");
9756 else if (route_filter_translated_v6
)
9758 ", mark translated RTs for VPNv6 route filtering");
9759 else if (route_filter_v6
)
9761 ", attach RT as-is for VPNv6 route filtering");
9762 else if (llgr_stale
)
9764 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9767 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9768 else if (accept_own_nexthop
)
9770 ", accept local nexthop");
9772 vty_out(vty
, ", inform peer to blackhole prefix");
9774 vty_out(vty
, ", not advertised to EBGP peer");
9775 else if (no_advertise
)
9776 vty_out(vty
, ", not advertised to any peer");
9778 vty_out(vty
, ", not advertised outside local AS");
9781 ", inform EBGP peer not to advertise to their EBGP peers");
9785 ", Advertisements suppressed by an aggregate.");
9786 vty_out(vty
, ")\n");
9789 /* If we are not using addpath then we can display Advertised to and
9791 * show what peers we advertised the bestpath to. If we are using
9793 * though then we must display Advertised to on a path-by-path basis. */
9794 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9795 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9796 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9797 if (json
&& !json_adv_to
)
9798 json_adv_to
= json_object_new_object();
9800 route_vty_out_advertised_to(
9802 " Advertised to non peer-group peers:\n ",
9809 json_object_object_add(json
, "advertisedTo",
9814 vty_out(vty
, " Not advertised to any peer");
9820 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
9821 struct bgp_node
*bgp_node
, struct vty
*vty
,
9822 struct bgp
*bgp
, afi_t afi
,
9823 safi_t safi
, json_object
*json
,
9824 enum bgp_path_type pathtype
, int *display
)
9826 struct bgp_path_info
*pi
;
9828 char rdbuf
[RD_ADDRSTRLEN
];
9829 json_object
*json_header
= NULL
;
9830 json_object
*json_paths
= NULL
;
9832 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
9835 if (json
&& !json_paths
) {
9836 /* Instantiate json_paths only if path is valid */
9837 json_paths
= json_object_new_array();
9839 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
9840 json_header
= json_object_new_object();
9846 route_vty_out_detail_header(
9847 vty
, bgp
, bgp_node
, pfx_rd
,
9848 AFI_IP
, safi
, json_header
);
9853 if (pathtype
== BGP_PATH_SHOW_ALL
9854 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9855 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
9856 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9857 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
9858 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
9859 route_vty_out_detail(vty
, bgp
, bgp_node
,
9864 if (json
&& json_paths
) {
9865 json_object_object_add(json_header
, "paths", json_paths
);
9868 json_object_object_add(json
, rdbuf
, json_header
);
9872 /* Display specified route of BGP table. */
9873 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9874 struct bgp_table
*rib
, const char *ip_str
,
9875 afi_t afi
, safi_t safi
,
9876 struct prefix_rd
*prd
, int prefix_check
,
9877 enum bgp_path_type pathtype
, bool use_json
)
9881 struct prefix match
;
9882 struct bgp_node
*rn
;
9883 struct bgp_node
*rm
;
9884 struct bgp_table
*table
;
9885 json_object
*json
= NULL
;
9886 json_object
*json_paths
= NULL
;
9888 /* Check IP address argument. */
9889 ret
= str2prefix(ip_str
, &match
);
9891 vty_out(vty
, "address is malformed\n");
9895 match
.family
= afi2family(afi
);
9898 json
= json_object_new_object();
9900 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
9901 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9902 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9904 table
= bgp_node_get_bgp_table_info(rn
);
9908 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9912 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9913 bgp_unlock_node(rm
);
9917 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9918 vty
, bgp
, afi
, safi
, json
,
9919 pathtype
, &display
);
9921 bgp_unlock_node(rm
);
9923 } else if (safi
== SAFI_EVPN
) {
9924 struct bgp_node
*longest_pfx
;
9925 bool is_exact_pfxlen_match
= FALSE
;
9927 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9928 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9930 table
= bgp_node_get_bgp_table_info(rn
);
9935 is_exact_pfxlen_match
= FALSE
;
9937 * Search through all the prefixes for a match. The
9938 * pfx's are enumerated in ascending order of pfxlens.
9939 * So, the last pfx match is the longest match. Set
9940 * is_exact_pfxlen_match when we get exact pfxlen match
9942 for (rm
= bgp_table_top(table
); rm
;
9943 rm
= bgp_route_next(rm
)) {
9945 * Get prefixlen of the ip-prefix within type5
9948 if (evpn_type5_prefix_match(&rm
->p
,
9949 &match
) && rm
->info
) {
9952 bgp_evpn_get_type5_prefixlen(&rm
->p
);
9953 if (type5_pfxlen
== match
.prefixlen
) {
9954 is_exact_pfxlen_match
= TRUE
;
9955 bgp_unlock_node(rm
);
9964 if (prefix_check
&& !is_exact_pfxlen_match
)
9970 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9971 vty
, bgp
, afi
, safi
, json
,
9972 pathtype
, &display
);
9974 bgp_unlock_node(rm
);
9976 } else if (safi
== SAFI_FLOWSPEC
) {
9978 json_paths
= json_object_new_array();
9980 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9981 &match
, prefix_check
,
9985 if (use_json
&& display
)
9986 json_object_object_add(json
, "paths", json_paths
);
9988 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9990 || rn
->p
.prefixlen
== match
.prefixlen
) {
9991 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
9993 pathtype
, &display
);
9996 bgp_unlock_node(rn
);
10001 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10002 json
, JSON_C_TO_STRING_PRETTY
|
10003 JSON_C_TO_STRING_NOSLASHESCAPE
));
10004 json_object_free(json
);
10007 vty_out(vty
, "%% Network not in table\n");
10008 return CMD_WARNING
;
10012 return CMD_SUCCESS
;
10015 /* Display specified route of Main RIB */
10016 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10017 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10018 int prefix_check
, enum bgp_path_type pathtype
,
10022 bgp
= bgp_get_default();
10025 vty_out(vty
, "No BGP process is configured\n");
10027 vty_out(vty
, "{}\n");
10028 return CMD_WARNING
;
10032 /* labeled-unicast routes live in the unicast table */
10033 if (safi
== SAFI_LABELED_UNICAST
)
10034 safi
= SAFI_UNICAST
;
10036 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10037 afi
, safi
, prd
, prefix_check
, pathtype
,
10041 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10042 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10043 safi_t safi
, bool uj
)
10045 struct lcommunity
*lcom
;
10051 b
= buffer_new(1024);
10052 for (i
= 0; i
< argc
; i
++) {
10054 buffer_putc(b
, ' ');
10056 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10058 buffer_putstr(b
, argv
[i
]->arg
);
10062 buffer_putc(b
, '\0');
10064 str
= buffer_getstr(b
);
10067 lcom
= lcommunity_str2com(str
);
10068 XFREE(MTYPE_TMP
, str
);
10070 vty_out(vty
, "%% Large-community malformed\n");
10071 return CMD_WARNING
;
10074 return bgp_show(vty
, bgp
, afi
, safi
,
10075 (exact
? bgp_show_type_lcommunity_exact
10076 : bgp_show_type_lcommunity
),
10080 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10081 const char *lcom
, bool exact
, afi_t afi
,
10082 safi_t safi
, bool uj
)
10084 struct community_list
*list
;
10086 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10087 LARGE_COMMUNITY_LIST_MASTER
);
10088 if (list
== NULL
) {
10089 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10091 return CMD_WARNING
;
10094 return bgp_show(vty
, bgp
, afi
, safi
,
10095 (exact
? bgp_show_type_lcommunity_list_exact
10096 : bgp_show_type_lcommunity_list
),
10100 DEFUN (show_ip_bgp_large_community_list
,
10101 show_ip_bgp_large_community_list_cmd
,
10102 "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]",
10106 BGP_INSTANCE_HELP_STR
10108 BGP_SAFI_WITH_LABEL_HELP_STR
10109 "Display routes matching the large-community-list\n"
10110 "large-community-list number\n"
10111 "large-community-list name\n"
10112 "Exact match of the large-communities\n"
10116 afi_t afi
= AFI_IP6
;
10117 safi_t safi
= SAFI_UNICAST
;
10119 bool exact_match
= 0;
10121 if (argv_find(argv
, argc
, "ip", &idx
))
10123 if (argv_find(argv
, argc
, "view", &idx
)
10124 || argv_find(argv
, argc
, "vrf", &idx
))
10125 vrf
= argv
[++idx
]->arg
;
10126 if (argv_find(argv
, argc
, "ipv4", &idx
)
10127 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10128 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10129 if (argv_find(argv
, argc
, "unicast", &idx
)
10130 || argv_find(argv
, argc
, "multicast", &idx
))
10131 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10134 bool uj
= use_json(argc
, argv
);
10136 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10138 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10139 return CMD_WARNING
;
10142 argv_find(argv
, argc
, "large-community-list", &idx
);
10144 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10146 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10149 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10150 exact_match
, afi
, safi
, uj
);
10152 DEFUN (show_ip_bgp_large_community
,
10153 show_ip_bgp_large_community_cmd
,
10154 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10158 BGP_INSTANCE_HELP_STR
10160 BGP_SAFI_WITH_LABEL_HELP_STR
10161 "Display routes matching the large-communities\n"
10162 "List of large-community numbers\n"
10163 "Exact match of the large-communities\n"
10167 afi_t afi
= AFI_IP6
;
10168 safi_t safi
= SAFI_UNICAST
;
10170 bool exact_match
= 0;
10172 if (argv_find(argv
, argc
, "ip", &idx
))
10174 if (argv_find(argv
, argc
, "view", &idx
)
10175 || argv_find(argv
, argc
, "vrf", &idx
))
10176 vrf
= argv
[++idx
]->arg
;
10177 if (argv_find(argv
, argc
, "ipv4", &idx
)
10178 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10179 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10180 if (argv_find(argv
, argc
, "unicast", &idx
)
10181 || argv_find(argv
, argc
, "multicast", &idx
))
10182 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10185 bool uj
= use_json(argc
, argv
);
10187 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10189 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10190 return CMD_WARNING
;
10193 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10194 if (argv_find(argv
, argc
, "exact-match", &idx
))
10196 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10197 exact_match
, afi
, safi
, uj
);
10199 return bgp_show(vty
, bgp
, afi
, safi
,
10200 bgp_show_type_lcommunity_all
, NULL
, uj
);
10203 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10207 /* BGP route print out function without JSON */
10208 DEFUN (show_ip_bgp
,
10210 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10211 <dampening <parameters>\
10216 |community-list <(1-500)|WORD> [exact-match]\
10217 |A.B.C.D/M longer-prefixes\
10218 |X:X::X:X/M longer-prefixes\
10223 BGP_INSTANCE_HELP_STR
10225 BGP_SAFI_WITH_LABEL_HELP_STR
10226 "Display detailed information about dampening\n"
10227 "Display detail of configured dampening parameters\n"
10228 "Display routes matching the route-map\n"
10229 "A route-map to match on\n"
10230 "Display routes conforming to the prefix-list\n"
10231 "Prefix-list name\n"
10232 "Display routes conforming to the filter-list\n"
10233 "Regular expression access list name\n"
10234 "BGP RIB advertisement statistics\n"
10235 "Display routes matching the community-list\n"
10236 "community-list number\n"
10237 "community-list name\n"
10238 "Exact match of the communities\n"
10240 "Display route and more specific routes\n"
10242 "Display route and more specific routes\n")
10244 afi_t afi
= AFI_IP6
;
10245 safi_t safi
= SAFI_UNICAST
;
10246 int exact_match
= 0;
10247 struct bgp
*bgp
= NULL
;
10250 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10253 return CMD_WARNING
;
10255 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10256 if (argv_find(argv
, argc
, "parameters", &idx
))
10257 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10260 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10261 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10262 safi
, bgp_show_type_prefix_list
);
10264 if (argv_find(argv
, argc
, "filter-list", &idx
))
10265 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10266 safi
, bgp_show_type_filter_list
);
10268 if (argv_find(argv
, argc
, "statistics", &idx
))
10269 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10271 if (argv_find(argv
, argc
, "route-map", &idx
))
10272 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10273 safi
, bgp_show_type_route_map
);
10275 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10276 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10277 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10279 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10280 exact_match
, afi
, safi
);
10282 /* prefix-longer */
10283 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10284 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10285 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10287 bgp_show_type_prefix_longer
);
10289 return CMD_WARNING
;
10292 /* BGP route print out function with JSON */
10293 DEFUN (show_ip_bgp_json
,
10294 show_ip_bgp_json_cmd
,
10295 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10297 |dampening <flap-statistics|dampened-paths>\
10298 |community [AA:NN|local-AS|no-advertise|no-export\
10299 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10300 |accept-own|accept-own-nexthop|route-filter-v6\
10301 |route-filter-v4|route-filter-translated-v6\
10302 |route-filter-translated-v4] [exact-match]\
10307 BGP_INSTANCE_HELP_STR
10309 BGP_SAFI_WITH_LABEL_HELP_STR
10310 "Display only routes with non-natural netmasks\n"
10311 "Display detailed information about dampening\n"
10312 "Display flap statistics of routes\n"
10313 "Display paths suppressed due to dampening\n"
10314 "Display routes matching the communities\n"
10316 "Do not send outside local AS (well-known community)\n"
10317 "Do not advertise to any peer (well-known community)\n"
10318 "Do not export to next AS (well-known community)\n"
10319 "Graceful shutdown (well-known community)\n"
10320 "Do not export to any peer (well-known community)\n"
10321 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10322 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10323 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10324 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10325 "Should accept VPN route with local nexthop (well-known community)\n"
10326 "RT VPNv6 route filtering (well-known community)\n"
10327 "RT VPNv4 route filtering (well-known community)\n"
10328 "RT translated VPNv6 route filtering (well-known community)\n"
10329 "RT translated VPNv4 route filtering (well-known community)\n"
10330 "Exact match of the communities\n"
10333 afi_t afi
= AFI_IP6
;
10334 safi_t safi
= SAFI_UNICAST
;
10335 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10336 struct bgp
*bgp
= NULL
;
10338 int exact_match
= 0;
10339 bool uj
= use_json(argc
, argv
);
10344 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10347 return CMD_WARNING
;
10349 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10350 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10353 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10354 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10355 return bgp_show(vty
, bgp
, afi
, safi
,
10356 bgp_show_type_dampend_paths
, NULL
, uj
);
10357 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10358 return bgp_show(vty
, bgp
, afi
, safi
,
10359 bgp_show_type_flap_statistics
, NULL
,
10363 if (argv_find(argv
, argc
, "community", &idx
)) {
10364 char *maybecomm
= NULL
;
10365 char *community
= NULL
;
10367 if (idx
+ 1 < argc
) {
10368 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10369 maybecomm
= argv
[idx
+ 1]->arg
;
10371 maybecomm
= argv
[idx
+ 1]->text
;
10374 if (maybecomm
&& !strmatch(maybecomm
, "json")
10375 && !strmatch(maybecomm
, "exact-match"))
10376 community
= maybecomm
;
10378 if (argv_find(argv
, argc
, "exact-match", &idx
))
10382 return bgp_show_community(vty
, bgp
, community
,
10383 exact_match
, afi
, safi
, uj
);
10385 return (bgp_show(vty
, bgp
, afi
, safi
,
10386 bgp_show_type_community_all
, NULL
,
10390 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10393 DEFUN (show_ip_bgp_route
,
10394 show_ip_bgp_route_cmd
,
10395 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10396 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10400 BGP_INSTANCE_HELP_STR
10402 BGP_SAFI_WITH_LABEL_HELP_STR
10403 "Network in the BGP routing table to display\n"
10405 "Network in the BGP routing table to display\n"
10407 "Display only the bestpath\n"
10408 "Display only multipaths\n"
10411 int prefix_check
= 0;
10413 afi_t afi
= AFI_IP6
;
10414 safi_t safi
= SAFI_UNICAST
;
10415 char *prefix
= NULL
;
10416 struct bgp
*bgp
= NULL
;
10417 enum bgp_path_type path_type
;
10418 bool uj
= use_json(argc
, argv
);
10422 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10425 return CMD_WARNING
;
10429 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10430 return CMD_WARNING
;
10433 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10434 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10435 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10437 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10438 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10441 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10442 && afi
!= AFI_IP6
) {
10444 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10445 return CMD_WARNING
;
10447 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10448 && afi
!= AFI_IP
) {
10450 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10451 return CMD_WARNING
;
10454 prefix
= argv
[idx
]->arg
;
10456 /* [<bestpath|multipath>] */
10457 if (argv_find(argv
, argc
, "bestpath", &idx
))
10458 path_type
= BGP_PATH_SHOW_BESTPATH
;
10459 else if (argv_find(argv
, argc
, "multipath", &idx
))
10460 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10462 path_type
= BGP_PATH_SHOW_ALL
;
10464 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10468 DEFUN (show_ip_bgp_regexp
,
10469 show_ip_bgp_regexp_cmd
,
10470 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
10474 BGP_INSTANCE_HELP_STR
10476 BGP_SAFI_WITH_LABEL_HELP_STR
10477 "Display routes matching the AS path regular expression\n"
10478 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10481 afi_t afi
= AFI_IP6
;
10482 safi_t safi
= SAFI_UNICAST
;
10483 struct bgp
*bgp
= NULL
;
10484 bool uj
= use_json(argc
, argv
);
10485 char *regstr
= NULL
;
10488 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10491 return CMD_WARNING
;
10493 // get index of regex
10494 if (argv_find(argv
, argc
, "REGEX", &idx
))
10495 regstr
= argv
[idx
]->arg
;
10497 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10498 bgp_show_type_regexp
, uj
);
10501 DEFUN (show_ip_bgp_instance_all
,
10502 show_ip_bgp_instance_all_cmd
,
10503 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10507 BGP_INSTANCE_ALL_HELP_STR
10509 BGP_SAFI_WITH_LABEL_HELP_STR
10512 afi_t afi
= AFI_IP
;
10513 safi_t safi
= SAFI_UNICAST
;
10514 struct bgp
*bgp
= NULL
;
10516 bool uj
= use_json(argc
, argv
);
10521 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10524 return CMD_WARNING
;
10526 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10527 return CMD_SUCCESS
;
10530 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10531 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10537 if (!config_bgp_aspath_validate(regstr
)) {
10538 vty_out(vty
, "Invalid character in REGEX %s\n",
10540 return CMD_WARNING_CONFIG_FAILED
;
10543 regex
= bgp_regcomp(regstr
);
10545 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10546 return CMD_WARNING
;
10549 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, use_json
);
10550 bgp_regex_free(regex
);
10554 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10555 const char *prefix_list_str
, afi_t afi
,
10556 safi_t safi
, enum bgp_show_type type
)
10558 struct prefix_list
*plist
;
10560 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10561 if (plist
== NULL
) {
10562 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10564 return CMD_WARNING
;
10567 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10570 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10571 const char *filter
, afi_t afi
, safi_t safi
,
10572 enum bgp_show_type type
)
10574 struct as_list
*as_list
;
10576 as_list
= as_list_lookup(filter
);
10577 if (as_list
== NULL
) {
10578 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10580 return CMD_WARNING
;
10583 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10586 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10587 const char *rmap_str
, afi_t afi
, safi_t safi
,
10588 enum bgp_show_type type
)
10590 struct route_map
*rmap
;
10592 rmap
= route_map_lookup_by_name(rmap_str
);
10594 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10595 return CMD_WARNING
;
10598 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10601 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10602 const char *comstr
, int exact
, afi_t afi
,
10603 safi_t safi
, bool use_json
)
10605 struct community
*com
;
10608 com
= community_str2com(comstr
);
10610 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10611 return CMD_WARNING
;
10614 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10615 (exact
? bgp_show_type_community_exact
10616 : bgp_show_type_community
),
10618 community_free(&com
);
10623 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10624 const char *com
, int exact
, afi_t afi
,
10627 struct community_list
*list
;
10629 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10630 if (list
== NULL
) {
10631 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10632 return CMD_WARNING
;
10635 return bgp_show(vty
, bgp
, afi
, safi
,
10636 (exact
? bgp_show_type_community_list_exact
10637 : bgp_show_type_community_list
),
10641 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10642 const char *prefix
, afi_t afi
, safi_t safi
,
10643 enum bgp_show_type type
)
10650 ret
= str2prefix(prefix
, p
);
10652 vty_out(vty
, "%% Malformed Prefix\n");
10653 return CMD_WARNING
;
10656 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10662 BGP_STATS_MAXBITLEN
= 0,
10664 BGP_STATS_PREFIXES
,
10666 BGP_STATS_UNAGGREGATEABLE
,
10667 BGP_STATS_MAX_AGGREGATEABLE
,
10668 BGP_STATS_AGGREGATES
,
10670 BGP_STATS_ASPATH_COUNT
,
10671 BGP_STATS_ASPATH_MAXHOPS
,
10672 BGP_STATS_ASPATH_TOTHOPS
,
10673 BGP_STATS_ASPATH_MAXSIZE
,
10674 BGP_STATS_ASPATH_TOTSIZE
,
10675 BGP_STATS_ASN_HIGHEST
,
10679 static const char *const table_stats_strs
[] = {
10680 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10681 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10682 [BGP_STATS_RIB
] = "Total Advertisements",
10683 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10684 [BGP_STATS_MAX_AGGREGATEABLE
] =
10685 "Maximum aggregateable prefixes",
10686 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10687 [BGP_STATS_SPACE
] = "Address space advertised",
10688 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10689 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10690 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10691 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10692 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10693 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10694 [BGP_STATS_MAX
] = NULL
,
10697 struct bgp_table_stats
{
10698 struct bgp_table
*table
;
10699 unsigned long long counts
[BGP_STATS_MAX
];
10700 double total_space
;
10704 #define TALLY_SIGFIG 100000
10705 static unsigned long
10706 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10708 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10709 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10710 unsigned long ret
= newtot
/ count
;
10712 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10719 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10720 struct bgp_table_stats
*ts
, unsigned int space
)
10722 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10723 struct bgp_path_info
*pi
;
10728 if (!bgp_node_has_bgp_path_info_data(rn
))
10731 ts
->counts
[BGP_STATS_PREFIXES
]++;
10732 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10735 ts
->counts
[BGP_STATS_AVGPLEN
]
10736 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10737 ts
->counts
[BGP_STATS_AVGPLEN
],
10741 /* check if the prefix is included by any other announcements */
10742 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10743 prn
= bgp_node_parent_nolock(prn
);
10745 if (prn
== NULL
|| prn
== top
) {
10746 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10747 /* announced address space */
10749 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10750 } else if (bgp_node_has_bgp_path_info_data(prn
))
10751 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10754 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10755 ts
->counts
[BGP_STATS_RIB
]++;
10757 if (CHECK_FLAG(pi
->attr
->flag
,
10758 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
10759 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10761 /* as-path stats */
10762 if (pi
->attr
->aspath
) {
10763 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10764 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10765 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10767 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10769 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10770 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10772 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10773 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10775 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10776 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10778 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10779 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10780 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10782 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10783 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10784 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10787 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10788 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10793 static int bgp_table_stats_walker(struct thread
*t
)
10795 struct bgp_node
*rn
, *nrn
;
10796 struct bgp_node
*top
;
10797 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10798 unsigned int space
= 0;
10800 if (!(top
= bgp_table_top(ts
->table
)))
10803 switch (ts
->table
->afi
) {
10805 space
= IPV4_MAX_BITLEN
;
10808 space
= IPV6_MAX_BITLEN
;
10814 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10816 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10817 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10818 struct bgp_table
*table
;
10820 table
= bgp_node_get_bgp_table_info(rn
);
10824 top
= bgp_table_top(table
);
10825 for (nrn
= bgp_table_top(table
); nrn
;
10826 nrn
= bgp_route_next(nrn
))
10827 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10829 bgp_table_stats_rn(rn
, top
, ts
, space
);
10836 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10839 struct bgp_table_stats ts
;
10842 if (!bgp
->rib
[afi
][safi
]) {
10843 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10845 return CMD_WARNING
;
10848 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
10850 /* labeled-unicast routes live in the unicast table */
10851 if (safi
== SAFI_LABELED_UNICAST
)
10852 safi
= SAFI_UNICAST
;
10854 memset(&ts
, 0, sizeof(ts
));
10855 ts
.table
= bgp
->rib
[afi
][safi
];
10856 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10858 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10859 if (!table_stats_strs
[i
])
10864 case BGP_STATS_ASPATH_AVGHOPS
:
10865 case BGP_STATS_ASPATH_AVGSIZE
:
10866 case BGP_STATS_AVGPLEN
:
10867 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10868 vty_out (vty
, "%12.2f",
10869 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10872 case BGP_STATS_ASPATH_TOTHOPS
:
10873 case BGP_STATS_ASPATH_TOTSIZE
:
10874 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10875 vty_out(vty
, "%12.2f",
10877 ? (float)ts
.counts
[i
]
10879 [BGP_STATS_ASPATH_COUNT
]
10882 case BGP_STATS_TOTPLEN
:
10883 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10884 vty_out(vty
, "%12.2f",
10886 ? (float)ts
.counts
[i
]
10888 [BGP_STATS_PREFIXES
]
10891 case BGP_STATS_SPACE
:
10892 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10893 vty_out(vty
, "%12g\n", ts
.total_space
);
10895 if (afi
== AFI_IP6
) {
10896 vty_out(vty
, "%30s: ", "/32 equivalent ");
10897 vty_out(vty
, "%12g\n",
10898 ts
.total_space
* pow(2.0, -128 + 32));
10899 vty_out(vty
, "%30s: ", "/48 equivalent ");
10900 vty_out(vty
, "%12g\n",
10901 ts
.total_space
* pow(2.0, -128 + 48));
10903 vty_out(vty
, "%30s: ", "% announced ");
10904 vty_out(vty
, "%12.2f\n",
10905 ts
.total_space
* 100. * pow(2.0, -32));
10906 vty_out(vty
, "%30s: ", "/8 equivalent ");
10907 vty_out(vty
, "%12.2f\n",
10908 ts
.total_space
* pow(2.0, -32 + 8));
10909 vty_out(vty
, "%30s: ", "/24 equivalent ");
10910 vty_out(vty
, "%12.2f\n",
10911 ts
.total_space
* pow(2.0, -32 + 24));
10915 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10916 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10919 vty_out(vty
, "\n");
10921 return CMD_SUCCESS
;
10933 PCOUNT_PFCNT
, /* the figure we display to users */
10937 static const char *const pcount_strs
[] = {
10938 [PCOUNT_ADJ_IN
] = "Adj-in",
10939 [PCOUNT_DAMPED
] = "Damped",
10940 [PCOUNT_REMOVED
] = "Removed",
10941 [PCOUNT_HISTORY
] = "History",
10942 [PCOUNT_STALE
] = "Stale",
10943 [PCOUNT_VALID
] = "Valid",
10944 [PCOUNT_ALL
] = "All RIB",
10945 [PCOUNT_COUNTED
] = "PfxCt counted",
10946 [PCOUNT_PFCNT
] = "Useable",
10947 [PCOUNT_MAX
] = NULL
,
10950 struct peer_pcounts
{
10951 unsigned int count
[PCOUNT_MAX
];
10952 const struct peer
*peer
;
10953 const struct bgp_table
*table
;
10957 static void bgp_peer_count_proc(struct bgp_node
*rn
,
10958 struct peer_pcounts
*pc
)
10960 const struct bgp_adj_in
*ain
;
10961 const struct bgp_path_info
*pi
;
10962 const struct peer
*peer
= pc
->peer
;
10964 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10965 if (ain
->peer
== peer
)
10966 pc
->count
[PCOUNT_ADJ_IN
]++;
10968 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10970 if (pi
->peer
!= peer
)
10973 pc
->count
[PCOUNT_ALL
]++;
10975 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10976 pc
->count
[PCOUNT_DAMPED
]++;
10977 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10978 pc
->count
[PCOUNT_HISTORY
]++;
10979 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10980 pc
->count
[PCOUNT_REMOVED
]++;
10981 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10982 pc
->count
[PCOUNT_STALE
]++;
10983 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10984 pc
->count
[PCOUNT_VALID
]++;
10985 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10986 pc
->count
[PCOUNT_PFCNT
]++;
10988 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10989 pc
->count
[PCOUNT_COUNTED
]++;
10990 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10992 EC_LIB_DEVELOPMENT
,
10993 "Attempting to count but flags say it is unusable");
10995 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10997 EC_LIB_DEVELOPMENT
,
10998 "Not counted but flags say we should");
11003 static int bgp_peer_count_walker(struct thread
*t
)
11005 struct bgp_node
*rn
, *rm
;
11006 const struct bgp_table
*table
;
11007 struct peer_pcounts
*pc
= THREAD_ARG(t
);
11009 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
11010 || pc
->safi
== SAFI_EVPN
) {
11011 /* Special handling for 2-level routing tables. */
11012 for (rn
= bgp_table_top(pc
->table
); rn
;
11013 rn
= bgp_route_next(rn
)) {
11014 table
= bgp_node_get_bgp_table_info(rn
);
11016 for (rm
= bgp_table_top(table
); rm
;
11017 rm
= bgp_route_next(rm
))
11018 bgp_peer_count_proc(rm
, pc
);
11021 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
11022 bgp_peer_count_proc(rn
, pc
);
11027 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11028 safi_t safi
, bool use_json
)
11030 struct peer_pcounts pcounts
= {.peer
= peer
};
11032 json_object
*json
= NULL
;
11033 json_object
*json_loop
= NULL
;
11036 json
= json_object_new_object();
11037 json_loop
= json_object_new_object();
11040 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
11041 || !peer
->bgp
->rib
[afi
][safi
]) {
11043 json_object_string_add(
11045 "No such neighbor or address family");
11046 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11047 json_object_free(json
);
11049 vty_out(vty
, "%% No such neighbor or address family\n");
11051 return CMD_WARNING
;
11054 memset(&pcounts
, 0, sizeof(pcounts
));
11055 pcounts
.peer
= peer
;
11056 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11057 pcounts
.safi
= safi
;
11059 /* in-place call via thread subsystem so as to record execution time
11060 * stats for the thread-walk (i.e. ensure this can't be blamed on
11061 * on just vty_read()).
11063 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11066 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11067 json_object_string_add(json
, "multiProtocol",
11068 get_afi_safi_str(afi
, safi
, true));
11069 json_object_int_add(json
, "pfxCounter",
11070 peer
->pcount
[afi
][safi
]);
11072 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11073 json_object_int_add(json_loop
, pcount_strs
[i
],
11076 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
11078 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11079 json_object_string_add(json
, "pfxctDriftFor",
11081 json_object_string_add(
11082 json
, "recommended",
11083 "Please report this bug, with the above command output");
11085 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11086 json
, JSON_C_TO_STRING_PRETTY
));
11087 json_object_free(json
);
11091 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
11092 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
11093 peer
->hostname
, peer
->host
,
11094 get_afi_safi_str(afi
, safi
, false));
11096 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11097 get_afi_safi_str(afi
, safi
, false));
11100 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
11101 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11103 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11104 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
11107 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11108 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
11110 "Please report this bug, with the above command output\n");
11114 return CMD_SUCCESS
;
11117 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11118 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11119 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11120 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11124 BGP_INSTANCE_HELP_STR
11127 "Detailed information on TCP and BGP neighbor connections\n"
11128 "Neighbor to display information about\n"
11129 "Neighbor to display information about\n"
11130 "Neighbor on BGP configured interface\n"
11131 "Display detailed prefix count information\n"
11134 afi_t afi
= AFI_IP6
;
11135 safi_t safi
= SAFI_UNICAST
;
11138 struct bgp
*bgp
= NULL
;
11139 bool uj
= use_json(argc
, argv
);
11144 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11147 return CMD_WARNING
;
11149 argv_find(argv
, argc
, "neighbors", &idx
);
11150 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11152 return CMD_WARNING
;
11154 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11157 #ifdef KEEP_OLD_VPN_COMMANDS
11158 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11159 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11160 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11165 "Display information about all VPNv4 NLRIs\n"
11166 "Detailed information on TCP and BGP neighbor connections\n"
11167 "Neighbor to display information about\n"
11168 "Neighbor to display information about\n"
11169 "Neighbor on BGP configured interface\n"
11170 "Display detailed prefix count information\n"
11175 bool uj
= use_json(argc
, argv
);
11177 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11179 return CMD_WARNING
;
11181 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11184 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11185 show_ip_bgp_vpn_all_route_prefix_cmd
,
11186 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11191 "Display information about all VPNv4 NLRIs\n"
11192 "Network in the BGP routing table to display\n"
11193 "Network in the BGP routing table to display\n"
11197 char *network
= NULL
;
11198 struct bgp
*bgp
= bgp_get_default();
11200 vty_out(vty
, "Can't find default instance\n");
11201 return CMD_WARNING
;
11204 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11205 network
= argv
[idx
]->arg
;
11206 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11207 network
= argv
[idx
]->arg
;
11209 vty_out(vty
, "Unable to figure out Network\n");
11210 return CMD_WARNING
;
11213 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11214 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11216 #endif /* KEEP_OLD_VPN_COMMANDS */
11218 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11219 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11220 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11225 "Network in the BGP routing table to display\n"
11226 "Network in the BGP routing table to display\n"
11227 "Network in the BGP routing table to display\n"
11228 "Network in the BGP routing table to display\n"
11232 char *network
= NULL
;
11233 int prefix_check
= 0;
11235 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11236 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11237 network
= argv
[idx
]->arg
;
11238 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11239 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11240 network
= argv
[idx
]->arg
;
11243 vty_out(vty
, "Unable to figure out Network\n");
11244 return CMD_WARNING
;
11246 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11247 prefix_check
, BGP_PATH_SHOW_ALL
,
11248 use_json(argc
, argv
));
11251 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11252 safi_t safi
, enum bgp_show_adj_route_type type
,
11253 const char *rmap_name
, bool use_json
,
11256 struct bgp_table
*table
;
11257 struct bgp_adj_in
*ain
;
11258 struct bgp_adj_out
*adj
;
11259 unsigned long output_count
;
11260 unsigned long filtered_count
;
11261 struct bgp_node
*rn
;
11267 struct update_subgroup
*subgrp
;
11268 json_object
*json_scode
= NULL
;
11269 json_object
*json_ocode
= NULL
;
11270 json_object
*json_ar
= NULL
;
11271 struct peer_af
*paf
;
11272 bool route_filtered
;
11275 json_scode
= json_object_new_object();
11276 json_ocode
= json_object_new_object();
11277 json_ar
= json_object_new_object();
11279 json_object_string_add(json_scode
, "suppressed", "s");
11280 json_object_string_add(json_scode
, "damped", "d");
11281 json_object_string_add(json_scode
, "history", "h");
11282 json_object_string_add(json_scode
, "valid", "*");
11283 json_object_string_add(json_scode
, "best", ">");
11284 json_object_string_add(json_scode
, "multipath", "=");
11285 json_object_string_add(json_scode
, "internal", "i");
11286 json_object_string_add(json_scode
, "ribFailure", "r");
11287 json_object_string_add(json_scode
, "stale", "S");
11288 json_object_string_add(json_scode
, "removed", "R");
11290 json_object_string_add(json_ocode
, "igp", "i");
11291 json_object_string_add(json_ocode
, "egp", "e");
11292 json_object_string_add(json_ocode
, "incomplete", "?");
11299 json_object_string_add(json
, "alert", "no BGP");
11300 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11301 json_object_free(json
);
11303 vty_out(vty
, "%% No bgp\n");
11307 /* labeled-unicast routes live in the unicast table */
11308 if (safi
== SAFI_LABELED_UNICAST
)
11309 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11311 table
= bgp
->rib
[afi
][safi
];
11313 output_count
= filtered_count
= 0;
11314 subgrp
= peer_subgroup(peer
, afi
, safi
);
11316 if (type
== bgp_show_adj_route_advertised
&& subgrp
11317 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11319 json_object_int_add(json
, "bgpTableVersion",
11321 json_object_string_add(json
, "bgpLocalRouterId",
11322 inet_ntoa(bgp
->router_id
));
11323 json_object_int_add(json
, "defaultLocPrf",
11324 bgp
->default_local_pref
);
11325 json_object_int_add(json
, "localAS", bgp
->as
);
11326 json_object_object_add(json
, "bgpStatusCodes",
11328 json_object_object_add(json
, "bgpOriginCodes",
11330 json_object_string_add(
11331 json
, "bgpOriginatingDefaultNetwork",
11332 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11334 vty_out(vty
, "BGP table version is %" PRIu64
11335 ", local router ID is %s, vrf id ",
11336 table
->version
, inet_ntoa(bgp
->router_id
));
11337 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11338 vty_out(vty
, "%s", VRFID_NONE_STR
);
11340 vty_out(vty
, "%u", bgp
->vrf_id
);
11341 vty_out(vty
, "\n");
11342 vty_out(vty
, "Default local pref %u, ",
11343 bgp
->default_local_pref
);
11344 vty_out(vty
, "local AS %u\n", bgp
->as
);
11345 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11346 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11347 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11349 vty_out(vty
, "Originating default network %s\n\n",
11350 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11355 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11356 if (type
== bgp_show_adj_route_received
11357 || type
== bgp_show_adj_route_filtered
) {
11358 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11359 if (ain
->peer
!= peer
)
11364 json_object_int_add(
11365 json
, "bgpTableVersion",
11367 json_object_string_add(
11369 "bgpLocalRouterId",
11372 json_object_int_add(json
,
11374 bgp
->default_local_pref
);
11375 json_object_int_add(json
,
11376 "localAS", bgp
->as
);
11377 json_object_object_add(
11378 json
, "bgpStatusCodes",
11380 json_object_object_add(
11381 json
, "bgpOriginCodes",
11385 "BGP table version is 0, local router ID is %s, vrf id ",
11388 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11394 vty_out(vty
, "\n");
11396 "Default local pref %u, ",
11397 bgp
->default_local_pref
);
11398 vty_out(vty
, "local AS %u\n",
11401 BGP_SHOW_SCODE_HEADER
);
11403 BGP_SHOW_NCODE_HEADER
);
11405 BGP_SHOW_OCODE_HEADER
);
11411 vty_out(vty
, BGP_SHOW_HEADER
);
11416 route_filtered
= false;
11418 /* Filter prefix using distribute list,
11419 * filter list or prefix list
11421 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11422 safi
)) == FILTER_DENY
)
11423 route_filtered
= true;
11425 /* Filter prefix using route-map */
11426 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11427 afi
, safi
, rmap_name
, NULL
, 0,
11430 if (type
== bgp_show_adj_route_filtered
&&
11431 !route_filtered
&& ret
!= RMAP_DENY
) {
11432 bgp_attr_undup(&attr
, ain
->attr
);
11436 if (type
== bgp_show_adj_route_received
&&
11437 (route_filtered
|| ret
== RMAP_DENY
))
11440 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11441 use_json
, json_ar
);
11442 bgp_attr_undup(&attr
, ain
->attr
);
11445 } else if (type
== bgp_show_adj_route_advertised
) {
11446 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11447 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11448 if (paf
->peer
!= peer
|| !adj
->attr
)
11453 json_object_int_add(
11457 json_object_string_add(
11459 "bgpLocalRouterId",
11462 json_object_int_add(
11463 json
, "defaultLocPrf",
11464 bgp
->default_local_pref
11466 json_object_int_add(
11469 json_object_object_add(
11473 json_object_object_add(
11479 "BGP table version is %" PRIu64
11480 ", local router ID is %s, vrf id ",
11493 vty_out(vty
, "\n");
11495 "Default local pref %u, ",
11496 bgp
->default_local_pref
11502 BGP_SHOW_SCODE_HEADER
);
11504 BGP_SHOW_NCODE_HEADER
);
11506 BGP_SHOW_OCODE_HEADER
);
11518 ret
= bgp_output_modifier(
11519 peer
, &rn
->p
, &attr
, afi
, safi
,
11522 if (ret
!= RMAP_DENY
) {
11523 route_vty_out_tmp(vty
, &rn
->p
,
11532 bgp_attr_undup(&attr
, adj
->attr
);
11538 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11539 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11540 json_object_int_add(json
, "filteredPrefixCounter",
11543 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11544 json
, JSON_C_TO_STRING_PRETTY
));
11545 json_object_free(json
);
11546 } else if (output_count
> 0) {
11547 if (filtered_count
> 0)
11549 "\nTotal number of prefixes %ld (%ld filtered)\n",
11550 output_count
, filtered_count
);
11552 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11557 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11558 safi_t safi
, enum bgp_show_adj_route_type type
,
11559 const char *rmap_name
, bool use_json
)
11561 json_object
*json
= NULL
;
11564 json
= json_object_new_object();
11566 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11568 json_object_string_add(
11570 "No such neighbor or address family");
11571 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11572 json_object_free(json
);
11574 vty_out(vty
, "%% No such neighbor or address family\n");
11576 return CMD_WARNING
;
11579 if ((type
== bgp_show_adj_route_received
11580 || type
== bgp_show_adj_route_filtered
)
11581 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11582 PEER_FLAG_SOFT_RECONFIG
)) {
11584 json_object_string_add(
11586 "Inbound soft reconfiguration not enabled");
11587 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11588 json_object_free(json
);
11591 "%% Inbound soft reconfiguration not enabled\n");
11593 return CMD_WARNING
;
11596 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11598 return CMD_SUCCESS
;
11601 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11602 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11603 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11604 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11608 BGP_INSTANCE_HELP_STR
11610 BGP_SAFI_WITH_LABEL_HELP_STR
11611 "Detailed information on TCP and BGP neighbor connections\n"
11612 "Neighbor to display information about\n"
11613 "Neighbor to display information about\n"
11614 "Neighbor on BGP configured interface\n"
11615 "Display the routes advertised to a BGP neighbor\n"
11616 "Display the received routes from neighbor\n"
11617 "Display the filtered routes received from neighbor\n"
11618 "Route-map to modify the attributes\n"
11619 "Name of the route map\n"
11622 afi_t afi
= AFI_IP6
;
11623 safi_t safi
= SAFI_UNICAST
;
11624 char *rmap_name
= NULL
;
11625 char *peerstr
= NULL
;
11626 struct bgp
*bgp
= NULL
;
11628 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11630 bool uj
= use_json(argc
, argv
);
11635 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11638 return CMD_WARNING
;
11640 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11641 argv_find(argv
, argc
, "neighbors", &idx
);
11642 peerstr
= argv
[++idx
]->arg
;
11644 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11646 return CMD_WARNING
;
11648 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11649 type
= bgp_show_adj_route_advertised
;
11650 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11651 type
= bgp_show_adj_route_received
;
11652 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11653 type
= bgp_show_adj_route_filtered
;
11655 if (argv_find(argv
, argc
, "route-map", &idx
))
11656 rmap_name
= argv
[++idx
]->arg
;
11658 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11661 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11662 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11663 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11669 "Address Family modifier\n"
11670 "Detailed information on TCP and BGP neighbor connections\n"
11671 "Neighbor to display information about\n"
11672 "Neighbor to display information about\n"
11673 "Neighbor on BGP configured interface\n"
11674 "Display information received from a BGP neighbor\n"
11675 "Display the prefixlist filter\n"
11678 afi_t afi
= AFI_IP6
;
11679 safi_t safi
= SAFI_UNICAST
;
11680 char *peerstr
= NULL
;
11683 union sockunion su
;
11689 /* show [ip] bgp */
11690 if (argv_find(argv
, argc
, "ip", &idx
))
11692 /* [<ipv4|ipv6> [unicast]] */
11693 if (argv_find(argv
, argc
, "ipv4", &idx
))
11695 if (argv_find(argv
, argc
, "ipv6", &idx
))
11697 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11698 argv_find(argv
, argc
, "neighbors", &idx
);
11699 peerstr
= argv
[++idx
]->arg
;
11701 bool uj
= use_json(argc
, argv
);
11703 ret
= str2sockunion(peerstr
, &su
);
11705 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11708 vty_out(vty
, "{}\n");
11711 "%% Malformed address or name: %s\n",
11713 return CMD_WARNING
;
11716 peer
= peer_lookup(NULL
, &su
);
11719 vty_out(vty
, "{}\n");
11721 vty_out(vty
, "No peer\n");
11722 return CMD_WARNING
;
11726 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11727 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11730 vty_out(vty
, "Address Family: %s\n",
11731 get_afi_safi_str(afi
, safi
, false));
11732 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11735 vty_out(vty
, "{}\n");
11737 vty_out(vty
, "No functional output\n");
11740 return CMD_SUCCESS
;
11743 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11744 afi_t afi
, safi_t safi
,
11745 enum bgp_show_type type
, bool use_json
)
11747 /* labeled-unicast routes live in the unicast table */
11748 if (safi
== SAFI_LABELED_UNICAST
)
11749 safi
= SAFI_UNICAST
;
11751 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11753 json_object
*json_no
= NULL
;
11754 json_no
= json_object_new_object();
11755 json_object_string_add(
11756 json_no
, "warning",
11757 "No such neighbor or address family");
11758 vty_out(vty
, "%s\n",
11759 json_object_to_json_string(json_no
));
11760 json_object_free(json_no
);
11762 vty_out(vty
, "%% No such neighbor or address family\n");
11763 return CMD_WARNING
;
11766 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11769 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11770 show_ip_bgp_flowspec_routes_detailed_cmd
,
11771 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11775 BGP_INSTANCE_HELP_STR
11778 "Detailed information on flowspec entries\n"
11781 afi_t afi
= AFI_IP
;
11782 safi_t safi
= SAFI_UNICAST
;
11783 struct bgp
*bgp
= NULL
;
11785 bool uj
= use_json(argc
, argv
);
11790 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11793 return CMD_WARNING
;
11795 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11798 DEFUN (show_ip_bgp_neighbor_routes
,
11799 show_ip_bgp_neighbor_routes_cmd
,
11800 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11801 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11805 BGP_INSTANCE_HELP_STR
11807 BGP_SAFI_WITH_LABEL_HELP_STR
11808 "Detailed information on TCP and BGP neighbor connections\n"
11809 "Neighbor to display information about\n"
11810 "Neighbor to display information about\n"
11811 "Neighbor on BGP configured interface\n"
11812 "Display flap statistics of the routes learned from neighbor\n"
11813 "Display the dampened routes received from neighbor\n"
11814 "Display routes learned from neighbor\n"
11817 char *peerstr
= NULL
;
11818 struct bgp
*bgp
= NULL
;
11819 afi_t afi
= AFI_IP6
;
11820 safi_t safi
= SAFI_UNICAST
;
11822 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11824 bool uj
= use_json(argc
, argv
);
11829 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11832 return CMD_WARNING
;
11834 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11835 argv_find(argv
, argc
, "neighbors", &idx
);
11836 peerstr
= argv
[++idx
]->arg
;
11838 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11840 return CMD_WARNING
;
11842 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11843 sh_type
= bgp_show_type_flap_neighbor
;
11844 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11845 sh_type
= bgp_show_type_damp_neighbor
;
11846 else if (argv_find(argv
, argc
, "routes", &idx
))
11847 sh_type
= bgp_show_type_neighbor
;
11849 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11852 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11854 struct bgp_distance
{
11855 /* Distance value for the IP source prefix. */
11858 /* Name of the access-list to be matched. */
11862 DEFUN (show_bgp_afi_vpn_rd_route
,
11863 show_bgp_afi_vpn_rd_route_cmd
,
11864 "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]",
11868 "Address Family modifier\n"
11869 "Display information for a route distinguisher\n"
11870 "Route Distinguisher\n"
11871 "Network in the BGP routing table to display\n"
11872 "Network in the BGP routing table to display\n"
11876 struct prefix_rd prd
;
11877 afi_t afi
= AFI_MAX
;
11880 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11881 vty_out(vty
, "%% Malformed Address Family\n");
11882 return CMD_WARNING
;
11885 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11887 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11888 return CMD_WARNING
;
11891 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11892 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11895 static struct bgp_distance
*bgp_distance_new(void)
11897 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11900 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11902 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11905 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11906 const char *ip_str
, const char *access_list_str
)
11913 struct bgp_node
*rn
;
11914 struct bgp_distance
*bdistance
;
11916 afi
= bgp_node_afi(vty
);
11917 safi
= bgp_node_safi(vty
);
11919 ret
= str2prefix(ip_str
, &p
);
11921 vty_out(vty
, "Malformed prefix\n");
11922 return CMD_WARNING_CONFIG_FAILED
;
11925 distance
= atoi(distance_str
);
11927 /* Get BGP distance node. */
11928 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11929 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11931 bgp_unlock_node(rn
);
11933 bdistance
= bgp_distance_new();
11934 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11937 /* Set distance value. */
11938 bdistance
->distance
= distance
;
11940 /* Reset access-list configuration. */
11941 if (bdistance
->access_list
) {
11942 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11943 bdistance
->access_list
= NULL
;
11945 if (access_list_str
)
11946 bdistance
->access_list
=
11947 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11949 return CMD_SUCCESS
;
11952 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11953 const char *ip_str
, const char *access_list_str
)
11960 struct bgp_node
*rn
;
11961 struct bgp_distance
*bdistance
;
11963 afi
= bgp_node_afi(vty
);
11964 safi
= bgp_node_safi(vty
);
11966 ret
= str2prefix(ip_str
, &p
);
11968 vty_out(vty
, "Malformed prefix\n");
11969 return CMD_WARNING_CONFIG_FAILED
;
11972 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11973 (struct prefix
*)&p
);
11975 vty_out(vty
, "Can't find specified prefix\n");
11976 return CMD_WARNING_CONFIG_FAILED
;
11979 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11980 distance
= atoi(distance_str
);
11982 if (bdistance
->distance
!= distance
) {
11983 vty_out(vty
, "Distance does not match configured\n");
11984 return CMD_WARNING_CONFIG_FAILED
;
11987 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11988 bgp_distance_free(bdistance
);
11990 bgp_node_set_bgp_path_info(rn
, NULL
);
11991 bgp_unlock_node(rn
);
11992 bgp_unlock_node(rn
);
11994 return CMD_SUCCESS
;
11997 /* Apply BGP information to distance method. */
11998 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11999 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
12001 struct bgp_node
*rn
;
12004 struct bgp_distance
*bdistance
;
12005 struct access_list
*alist
;
12006 struct bgp_static
*bgp_static
;
12011 peer
= pinfo
->peer
;
12013 if (pinfo
->attr
->distance
)
12014 return pinfo
->attr
->distance
;
12016 /* Check source address. */
12017 sockunion2hostprefix(&peer
->su
, &q
);
12018 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
12020 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12021 bgp_unlock_node(rn
);
12023 if (bdistance
->access_list
) {
12024 alist
= access_list_lookup(afi
, bdistance
->access_list
);
12026 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
12027 return bdistance
->distance
;
12029 return bdistance
->distance
;
12032 /* Backdoor check. */
12033 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
12035 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12036 bgp_unlock_node(rn
);
12038 if (bgp_static
->backdoor
) {
12039 if (bgp
->distance_local
[afi
][safi
])
12040 return bgp
->distance_local
[afi
][safi
];
12042 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12046 if (peer
->sort
== BGP_PEER_EBGP
) {
12047 if (bgp
->distance_ebgp
[afi
][safi
])
12048 return bgp
->distance_ebgp
[afi
][safi
];
12049 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
12051 if (bgp
->distance_ibgp
[afi
][safi
])
12052 return bgp
->distance_ibgp
[afi
][safi
];
12053 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12057 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12058 * we should tell ZEBRA update the routes for a specific
12059 * AFI/SAFI to reflect changes in RIB.
12061 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
12063 safi_t update_safi
)
12068 FOREACH_AFI_SAFI (afi
, safi
) {
12069 if (!bgp_fibupd_safi(safi
))
12072 if (afi
!= update_afi
&& safi
!= update_safi
)
12075 if (BGP_DEBUG(zebra
, ZEBRA
))
12077 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12078 __func__
, afi
, safi
);
12079 bgp_zebra_announce_table(bgp
, afi
, safi
);
12083 DEFUN (bgp_distance
,
12085 "distance bgp (1-255) (1-255) (1-255)",
12086 "Define an administrative distance\n"
12088 "Distance for routes external to the AS\n"
12089 "Distance for routes internal to the AS\n"
12090 "Distance for local routes\n")
12092 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12093 int idx_number
= 2;
12094 int idx_number_2
= 3;
12095 int idx_number_3
= 4;
12096 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
12097 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
12098 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
12102 afi
= bgp_node_afi(vty
);
12103 safi
= bgp_node_safi(vty
);
12105 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
12106 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
12107 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
12108 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
12109 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
12110 bgp
->distance_local
[afi
][safi
] = distance_local
;
12111 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12113 return CMD_SUCCESS
;
12116 DEFUN (no_bgp_distance
,
12117 no_bgp_distance_cmd
,
12118 "no distance bgp [(1-255) (1-255) (1-255)]",
12120 "Define an administrative distance\n"
12122 "Distance for routes external to the AS\n"
12123 "Distance for routes internal to the AS\n"
12124 "Distance for local routes\n")
12126 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12130 afi
= bgp_node_afi(vty
);
12131 safi
= bgp_node_safi(vty
);
12133 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12134 || bgp
->distance_ibgp
[afi
][safi
] != 0
12135 || bgp
->distance_local
[afi
][safi
] != 0) {
12136 bgp
->distance_ebgp
[afi
][safi
] = 0;
12137 bgp
->distance_ibgp
[afi
][safi
] = 0;
12138 bgp
->distance_local
[afi
][safi
] = 0;
12139 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12141 return CMD_SUCCESS
;
12145 DEFUN (bgp_distance_source
,
12146 bgp_distance_source_cmd
,
12147 "distance (1-255) A.B.C.D/M",
12148 "Define an administrative distance\n"
12149 "Administrative distance\n"
12150 "IP source prefix\n")
12152 int idx_number
= 1;
12153 int idx_ipv4_prefixlen
= 2;
12154 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12155 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12156 return CMD_SUCCESS
;
12159 DEFUN (no_bgp_distance_source
,
12160 no_bgp_distance_source_cmd
,
12161 "no distance (1-255) A.B.C.D/M",
12163 "Define an administrative distance\n"
12164 "Administrative distance\n"
12165 "IP source prefix\n")
12167 int idx_number
= 2;
12168 int idx_ipv4_prefixlen
= 3;
12169 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12170 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12171 return CMD_SUCCESS
;
12174 DEFUN (bgp_distance_source_access_list
,
12175 bgp_distance_source_access_list_cmd
,
12176 "distance (1-255) A.B.C.D/M WORD",
12177 "Define an administrative distance\n"
12178 "Administrative distance\n"
12179 "IP source prefix\n"
12180 "Access list name\n")
12182 int idx_number
= 1;
12183 int idx_ipv4_prefixlen
= 2;
12185 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12186 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12187 return CMD_SUCCESS
;
12190 DEFUN (no_bgp_distance_source_access_list
,
12191 no_bgp_distance_source_access_list_cmd
,
12192 "no distance (1-255) A.B.C.D/M WORD",
12194 "Define an administrative distance\n"
12195 "Administrative distance\n"
12196 "IP source prefix\n"
12197 "Access list name\n")
12199 int idx_number
= 2;
12200 int idx_ipv4_prefixlen
= 3;
12202 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12203 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12204 return CMD_SUCCESS
;
12207 DEFUN (ipv6_bgp_distance_source
,
12208 ipv6_bgp_distance_source_cmd
,
12209 "distance (1-255) X:X::X:X/M",
12210 "Define an administrative distance\n"
12211 "Administrative distance\n"
12212 "IP source prefix\n")
12214 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12215 return CMD_SUCCESS
;
12218 DEFUN (no_ipv6_bgp_distance_source
,
12219 no_ipv6_bgp_distance_source_cmd
,
12220 "no distance (1-255) X:X::X:X/M",
12222 "Define an administrative distance\n"
12223 "Administrative distance\n"
12224 "IP source prefix\n")
12226 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12227 return CMD_SUCCESS
;
12230 DEFUN (ipv6_bgp_distance_source_access_list
,
12231 ipv6_bgp_distance_source_access_list_cmd
,
12232 "distance (1-255) X:X::X:X/M WORD",
12233 "Define an administrative distance\n"
12234 "Administrative distance\n"
12235 "IP source prefix\n"
12236 "Access list name\n")
12238 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12239 return CMD_SUCCESS
;
12242 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12243 no_ipv6_bgp_distance_source_access_list_cmd
,
12244 "no distance (1-255) X:X::X:X/M WORD",
12246 "Define an administrative distance\n"
12247 "Administrative distance\n"
12248 "IP source prefix\n"
12249 "Access list name\n")
12251 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12252 return CMD_SUCCESS
;
12255 DEFUN (bgp_damp_set
,
12257 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12258 "BGP Specific commands\n"
12259 "Enable route-flap dampening\n"
12260 "Half-life time for the penalty\n"
12261 "Value to start reusing a route\n"
12262 "Value to start suppressing a route\n"
12263 "Maximum duration to suppress a stable route\n")
12265 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12266 int idx_half_life
= 2;
12268 int idx_suppress
= 4;
12269 int idx_max_suppress
= 5;
12270 int half
= DEFAULT_HALF_LIFE
* 60;
12271 int reuse
= DEFAULT_REUSE
;
12272 int suppress
= DEFAULT_SUPPRESS
;
12273 int max
= 4 * half
;
12276 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12277 reuse
= atoi(argv
[idx_reuse
]->arg
);
12278 suppress
= atoi(argv
[idx_suppress
]->arg
);
12279 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12280 } else if (argc
== 3) {
12281 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12286 * These can't be 0 but our SA doesn't understand the
12287 * way our cli is constructed
12291 if (suppress
< reuse
) {
12293 "Suppress value cannot be less than reuse value \n");
12297 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12298 reuse
, suppress
, max
);
12301 DEFUN (bgp_damp_unset
,
12302 bgp_damp_unset_cmd
,
12303 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12305 "BGP Specific commands\n"
12306 "Enable route-flap dampening\n"
12307 "Half-life time for the penalty\n"
12308 "Value to start reusing a route\n"
12309 "Value to start suppressing a route\n"
12310 "Maximum duration to suppress a stable route\n")
12312 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12313 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12316 /* Display specified route of BGP table. */
12317 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12318 const char *ip_str
, afi_t afi
, safi_t safi
,
12319 struct prefix_rd
*prd
, int prefix_check
)
12322 struct prefix match
;
12323 struct bgp_node
*rn
;
12324 struct bgp_node
*rm
;
12325 struct bgp_path_info
*pi
;
12326 struct bgp_path_info
*pi_temp
;
12328 struct bgp_table
*table
;
12330 /* BGP structure lookup. */
12332 bgp
= bgp_lookup_by_name(view_name
);
12334 vty_out(vty
, "%% Can't find BGP instance %s\n",
12336 return CMD_WARNING
;
12339 bgp
= bgp_get_default();
12341 vty_out(vty
, "%% No BGP process is configured\n");
12342 return CMD_WARNING
;
12346 /* Check IP address argument. */
12347 ret
= str2prefix(ip_str
, &match
);
12349 vty_out(vty
, "%% address is malformed\n");
12350 return CMD_WARNING
;
12353 match
.family
= afi2family(afi
);
12355 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12356 || (safi
== SAFI_EVPN
)) {
12357 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12358 rn
= bgp_route_next(rn
)) {
12359 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12361 table
= bgp_node_get_bgp_table_info(rn
);
12364 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12368 || rm
->p
.prefixlen
== match
.prefixlen
) {
12369 pi
= bgp_node_get_bgp_path_info(rm
);
12371 if (pi
->extra
&& pi
->extra
->damp_info
) {
12372 pi_temp
= pi
->next
;
12373 bgp_damp_info_free(
12374 pi
->extra
->damp_info
,
12382 bgp_unlock_node(rm
);
12385 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12388 || rn
->p
.prefixlen
== match
.prefixlen
) {
12389 pi
= bgp_node_get_bgp_path_info(rn
);
12391 if (pi
->extra
&& pi
->extra
->damp_info
) {
12392 pi_temp
= pi
->next
;
12393 bgp_damp_info_free(
12394 pi
->extra
->damp_info
,
12402 bgp_unlock_node(rn
);
12406 return CMD_SUCCESS
;
12409 DEFUN (clear_ip_bgp_dampening
,
12410 clear_ip_bgp_dampening_cmd
,
12411 "clear ip bgp dampening",
12415 "Clear route flap dampening information\n")
12417 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
12418 return CMD_SUCCESS
;
12421 DEFUN (clear_ip_bgp_dampening_prefix
,
12422 clear_ip_bgp_dampening_prefix_cmd
,
12423 "clear ip bgp dampening A.B.C.D/M",
12427 "Clear route flap dampening information\n"
12430 int idx_ipv4_prefixlen
= 4;
12431 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12432 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12435 DEFUN (clear_ip_bgp_dampening_address
,
12436 clear_ip_bgp_dampening_address_cmd
,
12437 "clear ip bgp dampening A.B.C.D",
12441 "Clear route flap dampening information\n"
12442 "Network to clear damping information\n")
12445 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12446 SAFI_UNICAST
, NULL
, 0);
12449 DEFUN (clear_ip_bgp_dampening_address_mask
,
12450 clear_ip_bgp_dampening_address_mask_cmd
,
12451 "clear ip bgp dampening A.B.C.D A.B.C.D",
12455 "Clear route flap dampening information\n"
12456 "Network to clear damping information\n"
12460 int idx_ipv4_2
= 5;
12462 char prefix_str
[BUFSIZ
];
12464 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12467 vty_out(vty
, "%% Inconsistent address and mask\n");
12468 return CMD_WARNING
;
12471 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12475 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12477 struct vty
*vty
= arg
;
12478 struct peer
*peer
= bucket
->data
;
12479 char buf
[SU_ADDRSTRLEN
];
12481 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12482 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12485 DEFUN (show_bgp_peerhash
,
12486 show_bgp_peerhash_cmd
,
12487 "show bgp peerhash",
12490 "Display information about the BGP peerhash\n")
12492 struct list
*instances
= bm
->bgp
;
12493 struct listnode
*node
;
12496 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12497 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12498 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12502 return CMD_SUCCESS
;
12505 /* also used for encap safi */
12506 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12507 afi_t afi
, safi_t safi
)
12509 struct bgp_node
*prn
;
12510 struct bgp_node
*rn
;
12511 struct bgp_table
*table
;
12513 struct prefix_rd
*prd
;
12514 struct bgp_static
*bgp_static
;
12515 mpls_label_t label
;
12516 char buf
[SU_ADDRSTRLEN
];
12517 char rdbuf
[RD_ADDRSTRLEN
];
12519 /* Network configuration. */
12520 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12521 prn
= bgp_route_next(prn
)) {
12522 table
= bgp_node_get_bgp_table_info(prn
);
12526 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12527 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12528 if (bgp_static
== NULL
)
12532 prd
= (struct prefix_rd
*)&prn
->p
;
12534 /* "network" configuration display. */
12535 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12536 label
= decode_label(&bgp_static
->label
);
12538 vty_out(vty
, " network %s/%d rd %s",
12539 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12541 p
->prefixlen
, rdbuf
);
12542 if (safi
== SAFI_MPLS_VPN
)
12543 vty_out(vty
, " label %u", label
);
12545 if (bgp_static
->rmap
.name
)
12546 vty_out(vty
, " route-map %s",
12547 bgp_static
->rmap
.name
);
12549 if (bgp_static
->backdoor
)
12550 vty_out(vty
, " backdoor");
12552 vty_out(vty
, "\n");
12557 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12558 afi_t afi
, safi_t safi
)
12560 struct bgp_node
*prn
;
12561 struct bgp_node
*rn
;
12562 struct bgp_table
*table
;
12564 struct prefix_rd
*prd
;
12565 struct bgp_static
*bgp_static
;
12566 char buf
[PREFIX_STRLEN
* 2];
12567 char buf2
[SU_ADDRSTRLEN
];
12568 char rdbuf
[RD_ADDRSTRLEN
];
12570 /* Network configuration. */
12571 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12572 prn
= bgp_route_next(prn
)) {
12573 table
= bgp_node_get_bgp_table_info(prn
);
12577 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12578 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12579 if (bgp_static
== NULL
)
12582 char *macrouter
= NULL
;
12585 if (bgp_static
->router_mac
)
12586 macrouter
= prefix_mac2str(
12587 bgp_static
->router_mac
, NULL
, 0);
12588 if (bgp_static
->eth_s_id
)
12589 esi
= esi2str(bgp_static
->eth_s_id
);
12591 prd
= (struct prefix_rd
*)&prn
->p
;
12593 /* "network" configuration display. */
12594 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12595 if (p
->u
.prefix_evpn
.route_type
== 5) {
12596 char local_buf
[PREFIX_STRLEN
];
12597 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12598 struct prefix_evpn
*)p
)
12602 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12603 local_buf
, PREFIX_STRLEN
);
12604 sprintf(buf
, "%s/%u", local_buf
,
12605 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12607 prefix2str(p
, buf
, sizeof(buf
));
12610 if (bgp_static
->gatewayIp
.family
== AF_INET
12611 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12612 inet_ntop(bgp_static
->gatewayIp
.family
,
12613 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12616 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12618 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12619 decode_label(&bgp_static
->label
), esi
, buf2
,
12622 XFREE(MTYPE_TMP
, macrouter
);
12623 XFREE(MTYPE_TMP
, esi
);
12628 /* Configuration of static route announcement and aggregate
12630 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12633 struct bgp_node
*rn
;
12635 struct bgp_static
*bgp_static
;
12636 struct bgp_aggregate
*bgp_aggregate
;
12637 char buf
[SU_ADDRSTRLEN
];
12639 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12640 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12644 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12645 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12649 /* Network configuration. */
12650 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12651 rn
= bgp_route_next(rn
)) {
12652 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12653 if (bgp_static
== NULL
)
12658 vty_out(vty
, " network %s/%d",
12659 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12662 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12663 vty_out(vty
, " label-index %u",
12664 bgp_static
->label_index
);
12666 if (bgp_static
->rmap
.name
)
12667 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12669 if (bgp_static
->backdoor
)
12670 vty_out(vty
, " backdoor");
12672 vty_out(vty
, "\n");
12675 /* Aggregate-address configuration. */
12676 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12677 rn
= bgp_route_next(rn
)) {
12678 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12679 if (bgp_aggregate
== NULL
)
12684 vty_out(vty
, " aggregate-address %s/%d",
12685 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12688 if (bgp_aggregate
->as_set
)
12689 vty_out(vty
, " as-set");
12691 if (bgp_aggregate
->summary_only
)
12692 vty_out(vty
, " summary-only");
12694 if (bgp_aggregate
->rmap
.name
)
12695 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12697 vty_out(vty
, "\n");
12701 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12704 struct bgp_node
*rn
;
12705 struct bgp_distance
*bdistance
;
12707 /* Distance configuration. */
12708 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12709 && bgp
->distance_local
[afi
][safi
]
12710 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12711 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12712 || bgp
->distance_local
[afi
][safi
]
12713 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12714 vty_out(vty
, " distance bgp %d %d %d\n",
12715 bgp
->distance_ebgp
[afi
][safi
],
12716 bgp
->distance_ibgp
[afi
][safi
],
12717 bgp
->distance_local
[afi
][safi
]);
12720 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12721 rn
= bgp_route_next(rn
)) {
12722 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12723 if (bdistance
!= NULL
) {
12724 char buf
[PREFIX_STRLEN
];
12726 vty_out(vty
, " distance %d %s %s\n",
12727 bdistance
->distance
,
12728 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12729 bdistance
->access_list
? bdistance
->access_list
12735 /* Allocate routing table structure and install commands. */
12736 void bgp_route_init(void)
12741 /* Init BGP distance table. */
12742 FOREACH_AFI_SAFI (afi
, safi
)
12743 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12745 /* IPv4 BGP commands. */
12746 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12747 install_element(BGP_NODE
, &bgp_network_cmd
);
12748 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12750 install_element(BGP_NODE
, &aggregate_address_cmd
);
12751 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12752 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12753 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12755 /* IPv4 unicast configuration. */
12756 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12757 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12758 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12760 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12761 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12762 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12763 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12765 /* IPv4 multicast configuration. */
12766 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12767 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12768 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12769 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12770 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12771 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12772 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12774 /* IPv4 labeled-unicast configuration. */
12775 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12776 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12777 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12778 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12779 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12781 install_element(VIEW_NODE
,
12782 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12783 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12784 install_element(VIEW_NODE
,
12785 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12786 #ifdef KEEP_OLD_VPN_COMMANDS
12787 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12788 #endif /* KEEP_OLD_VPN_COMMANDS */
12789 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12790 install_element(VIEW_NODE
,
12791 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
12793 /* BGP dampening clear commands */
12794 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12795 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12797 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12798 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12801 install_element(ENABLE_NODE
,
12802 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12803 #ifdef KEEP_OLD_VPN_COMMANDS
12804 install_element(ENABLE_NODE
,
12805 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12806 #endif /* KEEP_OLD_VPN_COMMANDS */
12808 /* New config IPv6 BGP commands. */
12809 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12810 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12811 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12813 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12814 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12816 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12818 install_element(BGP_NODE
, &bgp_distance_cmd
);
12819 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12820 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12821 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12822 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12823 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12824 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12825 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12826 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12827 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12828 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12829 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12830 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12831 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12832 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12833 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12834 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12835 install_element(BGP_IPV4M_NODE
,
12836 &no_bgp_distance_source_access_list_cmd
);
12837 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12838 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12839 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12840 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12841 install_element(BGP_IPV6_NODE
,
12842 &ipv6_bgp_distance_source_access_list_cmd
);
12843 install_element(BGP_IPV6_NODE
,
12844 &no_ipv6_bgp_distance_source_access_list_cmd
);
12845 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12846 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12847 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12848 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12849 install_element(BGP_IPV6M_NODE
,
12850 &ipv6_bgp_distance_source_access_list_cmd
);
12851 install_element(BGP_IPV6M_NODE
,
12852 &no_ipv6_bgp_distance_source_access_list_cmd
);
12854 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12855 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12856 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12857 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12859 /* IPv4 Multicast Mode */
12860 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12861 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12863 /* Large Communities */
12864 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12865 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12867 /* show bgp ipv4 flowspec detailed */
12868 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12870 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12873 void bgp_route_finish(void)
12878 FOREACH_AFI_SAFI (afi
, safi
) {
12879 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12880 bgp_distance_table
[afi
][safi
] = NULL
;