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. */
1698 bgp_attr_dup(attr
, piattr
);
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
)) {
1818 bgp_attr_dup(&dummy_attr
, attr
);
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 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1858 if (peer
->sort
== BGP_PEER_IBGP
1859 || peer
->sort
== BGP_PEER_CONFED
) {
1860 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1861 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1863 bgp_attr_add_gshut_community(attr
);
1867 /* After route-map has been applied, we check to see if the nexthop to
1868 * be carried in the attribute (that is used for the announcement) can
1869 * be cleared off or not. We do this in all cases where we would be
1870 * setting the nexthop to "ourselves". For IPv6, we only need to
1872 * the global nexthop here; the link-local nexthop would have been
1874 * already, and if not, it is required by the update formation code.
1875 * Also see earlier comments in this function.
1878 * If route-map has performed some operation on the nexthop or the peer
1879 * configuration says to pass it unchanged, we cannot reset the nexthop
1880 * here, so only attempt to do it if these aren't true. Note that the
1881 * route-map handler itself might have cleared the nexthop, if for
1883 * it is configured as 'peer-address'.
1885 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1886 piattr
->rmap_change_flags
)
1888 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1889 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1890 /* We can reset the nexthop, if setting (or forcing) it to
1892 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1893 PEER_FLAG_NEXTHOP_SELF
)
1894 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1895 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1897 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1898 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1899 subgroup_announce_reset_nhop(
1900 (peer_cap_enhe(peer
, afi
, safi
)
1904 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1905 /* Can also reset the nexthop if announcing to EBGP, but
1907 * no peer in the subgroup is on a shared subnet.
1908 * Note: 3rd party nexthop currently implemented for
1911 if ((p
->family
== AF_INET
) &&
1912 (!bgp_subgrp_multiaccess_check_v4(
1915 subgroup_announce_reset_nhop(
1916 (peer_cap_enhe(peer
, afi
, safi
)
1921 if ((p
->family
== AF_INET6
) &&
1922 (!bgp_subgrp_multiaccess_check_v6(
1923 piattr
->mp_nexthop_global
,
1925 subgroup_announce_reset_nhop(
1926 (peer_cap_enhe(peer
, afi
, safi
)
1933 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1935 * This flag is used for leaked vpn-vrf routes
1937 int family
= p
->family
;
1939 if (peer_cap_enhe(peer
, afi
, safi
))
1942 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1944 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1945 __func__
, family2str(family
));
1946 subgroup_announce_reset_nhop(family
, attr
);
1950 /* If IPv6/MP and nexthop does not have any override and happens
1952 * be a link-local address, reset it so that we don't pass along
1954 * source's link-local IPv6 address to recipients who may not be
1956 * the same interface.
1958 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1959 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1960 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1966 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1967 struct bgp_maxpaths_cfg
*mpath_cfg
,
1968 struct bgp_path_info_pair
*result
, afi_t afi
,
1971 struct bgp_path_info
*new_select
;
1972 struct bgp_path_info
*old_select
;
1973 struct bgp_path_info
*pi
;
1974 struct bgp_path_info
*pi1
;
1975 struct bgp_path_info
*pi2
;
1976 struct bgp_path_info
*nextpi
= NULL
;
1977 int paths_eq
, do_mpath
, debug
;
1978 struct list mp_list
;
1979 char pfx_buf
[PREFIX2STR_BUFFER
];
1980 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1982 bgp_mp_list_init(&mp_list
);
1984 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1986 debug
= bgp_debug_bestpath(&rn
->p
);
1989 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1991 /* bgp deterministic-med */
1993 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1995 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1996 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1998 bgp_path_info_unset_flag(rn
, pi1
,
1999 BGP_PATH_DMED_SELECTED
);
2001 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2003 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2005 if (BGP_PATH_HOLDDOWN(pi1
))
2007 if (pi1
->peer
!= bgp
->peer_self
)
2008 if (pi1
->peer
->status
!= Established
)
2013 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2014 if (CHECK_FLAG(pi2
->flags
,
2015 BGP_PATH_DMED_CHECK
))
2017 if (BGP_PATH_HOLDDOWN(pi2
))
2019 if (pi2
->peer
!= bgp
->peer_self
2022 PEER_STATUS_NSF_WAIT
))
2023 if (pi2
->peer
->status
2027 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2029 && !aspath_cmp_left_confed(
2034 if (bgp_path_info_cmp(
2035 bgp
, pi2
, new_select
,
2036 &paths_eq
, mpath_cfg
, debug
,
2039 bgp_path_info_unset_flag(
2041 BGP_PATH_DMED_SELECTED
);
2045 bgp_path_info_set_flag(
2046 rn
, pi2
, BGP_PATH_DMED_CHECK
);
2049 bgp_path_info_set_flag(rn
, new_select
,
2050 BGP_PATH_DMED_CHECK
);
2051 bgp_path_info_set_flag(rn
, new_select
,
2052 BGP_PATH_DMED_SELECTED
);
2055 bgp_path_info_path_with_addpath_rx_str(
2056 new_select
, path_buf
);
2057 zlog_debug("%s: %s is the bestpath from AS %u",
2059 aspath_get_first_as(
2060 new_select
->attr
->aspath
));
2065 /* Check old selected route and new selected route. */
2068 for (pi
= bgp_node_get_bgp_path_info(rn
);
2069 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2070 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2073 if (BGP_PATH_HOLDDOWN(pi
)) {
2074 /* reap REMOVED routes, if needs be
2075 * selected route must stay for a while longer though
2077 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2078 && (pi
!= old_select
))
2079 bgp_path_info_reap(rn
, pi
);
2082 zlog_debug("%s: pi %p in holddown", __func__
,
2088 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2089 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2090 if (pi
->peer
->status
!= Established
) {
2094 "%s: pi %p non self peer %s not estab state",
2095 __func__
, pi
, pi
->peer
->host
);
2100 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2101 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2102 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2104 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2108 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2110 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2111 debug
, pfx_buf
, afi
, safi
, &rn
->reason
)) {
2116 /* Now that we know which path is the bestpath see if any of the other
2118 * qualify as multipaths
2122 bgp_path_info_path_with_addpath_rx_str(new_select
,
2125 sprintf(path_buf
, "NONE");
2127 "%s: After path selection, newbest is %s oldbest was %s",
2129 old_select
? old_select
->peer
->host
: "NONE");
2132 if (do_mpath
&& new_select
) {
2133 for (pi
= bgp_node_get_bgp_path_info(rn
);
2134 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2137 bgp_path_info_path_with_addpath_rx_str(
2140 if (pi
== new_select
) {
2143 "%s: %s is the bestpath, add to the multipath list",
2145 bgp_mp_list_add(&mp_list
, pi
);
2149 if (BGP_PATH_HOLDDOWN(pi
))
2152 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2153 && !CHECK_FLAG(pi
->peer
->sflags
,
2154 PEER_STATUS_NSF_WAIT
))
2155 if (pi
->peer
->status
!= Established
)
2158 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2161 "%s: %s has the same nexthop as the bestpath, skip it",
2166 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2167 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2173 "%s: %s is equivalent to the bestpath, add to the multipath list",
2175 bgp_mp_list_add(&mp_list
, pi
);
2180 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2182 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2183 bgp_mp_list_clear(&mp_list
);
2185 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2187 result
->old
= old_select
;
2188 result
->new = new_select
;
2194 * A new route/change in bestpath of an existing route. Evaluate the path
2195 * for advertisement to the subgroup.
2197 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2198 struct bgp_path_info
*selected
,
2199 struct bgp_node
*rn
,
2200 uint32_t addpath_tx_id
)
2203 struct peer
*onlypeer
;
2209 afi
= SUBGRP_AFI(subgrp
);
2210 safi
= SUBGRP_SAFI(subgrp
);
2211 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2214 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2215 char buf_prefix
[PREFIX_STRLEN
];
2216 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2217 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2221 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2222 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2223 PEER_STATUS_ORF_WAIT_REFRESH
))
2226 memset(&attr
, 0, sizeof(struct attr
));
2227 /* It's initialized in bgp_announce_check() */
2229 /* Announcement to the subgroup. If the route is filtered withdraw it.
2232 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2233 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2235 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2239 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2241 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2248 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2249 * This is called at the end of route processing.
2251 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2253 struct bgp_path_info
*pi
;
2255 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2256 if (BGP_PATH_HOLDDOWN(pi
))
2258 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2259 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2264 * Has the route changed from the RIB's perspective? This is invoked only
2265 * if the route selection returns the same best route as earlier - to
2266 * determine if we need to update zebra or not.
2268 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2269 struct bgp_path_info
*selected
)
2271 struct bgp_path_info
*mpinfo
;
2273 /* If this is multipath, check all selected paths for any nexthop
2274 * change or attribute change. Some attribute changes (e.g., community)
2275 * aren't of relevance to the RIB, but we'll update zebra to ensure
2276 * we handle the case of BGP nexthop change. This is the behavior
2277 * when the best path has an attribute change anyway.
2279 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2280 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2284 * If this is multipath, check all selected paths for any nexthop change
2286 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2287 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2288 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2289 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2293 /* Nothing has changed from the RIB's perspective. */
2297 struct bgp_process_queue
{
2299 STAILQ_HEAD(, bgp_node
) pqueue
;
2300 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2302 unsigned int queued
;
2306 * old_select = The old best path
2307 * new_select = the new best path
2309 * if (!old_select && new_select)
2310 * We are sending new information on.
2312 * if (old_select && new_select) {
2313 * if (new_select != old_select)
2314 * We have a new best path send a change
2316 * We've received a update with new attributes that needs
2320 * if (old_select && !new_select)
2321 * We have no eligible route that we can announce or the rn
2324 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2325 afi_t afi
, safi_t safi
)
2327 struct bgp_path_info
*new_select
;
2328 struct bgp_path_info
*old_select
;
2329 struct bgp_path_info_pair old_and_new
;
2330 char pfx_buf
[PREFIX2STR_BUFFER
];
2333 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2335 debug
= bgp_debug_bestpath(&rn
->p
);
2337 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2339 "%s: bgp delete in progress, ignoring event, p=%s",
2344 /* Is it end of initial update? (after startup) */
2346 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2347 sizeof(bgp
->update_delay_zebra_resume_time
));
2349 bgp
->main_zebra_update_hold
= 0;
2350 FOREACH_AFI_SAFI (afi
, safi
) {
2351 if (bgp_fibupd_safi(safi
))
2352 bgp_zebra_announce_table(bgp
, afi
, safi
);
2354 bgp
->main_peers_update_hold
= 0;
2356 bgp_start_routeadv(bgp
);
2360 struct prefix
*p
= &rn
->p
;
2362 debug
= bgp_debug_bestpath(&rn
->p
);
2364 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2365 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2366 afi2str(afi
), safi2str(safi
));
2369 /* Best path selection. */
2370 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2372 old_select
= old_and_new
.old
;
2373 new_select
= old_and_new
.new;
2375 /* Do we need to allocate or free labels?
2376 * Right now, since we only deal with per-prefix labels, it is not
2377 * necessary to do this upon changes to best path. Exceptions:
2378 * - label index has changed -> recalculate resulting label
2379 * - path_info sub_type changed -> switch to/from implicit-null
2380 * - no valid label (due to removed static label binding) -> get new one
2382 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2385 || bgp_label_index_differs(new_select
, old_select
)
2386 || new_select
->sub_type
!= old_select
->sub_type
2387 || !bgp_is_valid_label(&rn
->local_label
)) {
2388 /* Enforced penultimate hop popping:
2389 * implicit-null for local routes, aggregate
2390 * and redistributed routes
2392 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2393 || new_select
->sub_type
2394 == BGP_ROUTE_AGGREGATE
2395 || new_select
->sub_type
2396 == BGP_ROUTE_REDISTRIBUTE
) {
2399 BGP_NODE_REGISTERED_FOR_LABEL
))
2400 bgp_unregister_for_label(rn
);
2401 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2403 bgp_set_valid_label(&rn
->local_label
);
2405 bgp_register_for_label(rn
, new_select
);
2407 } else if (CHECK_FLAG(rn
->flags
,
2408 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2409 bgp_unregister_for_label(rn
);
2411 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2412 bgp_unregister_for_label(rn
);
2416 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2418 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2419 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2420 old_select
, new_select
);
2423 /* If best route remains the same and this is not due to user-initiated
2424 * clear, see exactly what needs to be done.
2426 if (old_select
&& old_select
== new_select
2427 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2428 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2429 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2430 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2432 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2433 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2435 if (bgp_fibupd_safi(safi
)
2436 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2438 if (new_select
->type
== ZEBRA_ROUTE_BGP
2439 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2440 || new_select
->sub_type
2441 == BGP_ROUTE_IMPORTED
))
2443 bgp_zebra_announce(rn
, p
, old_select
,
2447 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2448 bgp_zebra_clear_route_change_flags(rn
);
2450 /* If there is a change of interest to peers, reannounce the
2452 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2453 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2454 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2456 /* unicast routes must also be annouced to
2457 * labeled-unicast update-groups */
2458 if (safi
== SAFI_UNICAST
)
2459 group_announce_route(bgp
, afi
,
2460 SAFI_LABELED_UNICAST
, rn
,
2463 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2464 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2467 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2471 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2473 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2475 /* bestpath has changed; bump version */
2476 if (old_select
|| new_select
) {
2477 bgp_bump_version(rn
);
2479 if (!bgp
->t_rmap_def_originate_eval
) {
2483 update_group_refresh_default_originate_route_map
,
2484 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2485 &bgp
->t_rmap_def_originate_eval
);
2490 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2493 zlog_debug("%s: setting SELECTED flag", __func__
);
2494 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2495 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2496 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2500 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2501 if (old_select
!= new_select
) {
2503 vnc_import_bgp_exterior_del_route(bgp
, p
,
2505 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2508 vnc_import_bgp_exterior_add_route(bgp
, p
,
2510 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2516 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2518 /* unicast routes must also be annouced to labeled-unicast update-groups
2520 if (safi
== SAFI_UNICAST
)
2521 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2525 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2526 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2527 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2528 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2529 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2530 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2532 /* if this is an evpn imported type-5 prefix,
2533 * we need to withdraw the route first to clear
2534 * the nh neigh and the RMAC entry.
2537 is_route_parent_evpn(old_select
))
2538 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2540 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2542 /* Withdraw the route from the kernel. */
2543 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2544 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2545 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2546 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2548 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2552 /* advertise/withdraw type-5 routes */
2553 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2554 if (advertise_type5_routes(bgp
, afi
) &&
2556 is_route_injectable_into_evpn(new_select
)) {
2558 /* apply the route-map */
2559 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2560 route_map_result_t ret
;
2562 ret
= route_map_apply(
2563 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2564 &rn
->p
, RMAP_BGP
, new_select
);
2565 if (ret
== RMAP_PERMITMATCH
)
2566 bgp_evpn_advertise_type5_route(
2567 bgp
, &rn
->p
, new_select
->attr
,
2570 bgp_evpn_withdraw_type5_route(
2571 bgp
, &rn
->p
, afi
, safi
);
2573 bgp_evpn_advertise_type5_route(bgp
,
2579 } else if (advertise_type5_routes(bgp
, afi
) &&
2581 is_route_injectable_into_evpn(old_select
))
2582 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2585 /* Clear any route change flags. */
2586 bgp_zebra_clear_route_change_flags(rn
);
2588 /* Reap old select bgp_path_info, if it has been removed */
2589 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2590 bgp_path_info_reap(rn
, old_select
);
2592 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2596 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2598 struct bgp_process_queue
*pqnode
= data
;
2599 struct bgp
*bgp
= pqnode
->bgp
;
2600 struct bgp_table
*table
;
2601 struct bgp_node
*rn
;
2604 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2605 bgp_process_main_one(bgp
, NULL
, 0, 0);
2606 /* should always have dedicated wq call */
2607 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2611 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2612 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2613 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2614 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2615 table
= bgp_node_table(rn
);
2616 /* note, new RNs may be added as part of processing */
2617 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2619 bgp_unlock_node(rn
);
2620 bgp_table_unlock(table
);
2626 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2628 struct bgp_process_queue
*pqnode
= data
;
2630 bgp_unlock(pqnode
->bgp
);
2632 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2635 void bgp_process_queue_init(void)
2637 if (!bm
->process_main_queue
)
2638 bm
->process_main_queue
=
2639 work_queue_new(bm
->master
, "process_main_queue");
2641 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2642 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2643 bm
->process_main_queue
->spec
.max_retries
= 0;
2644 bm
->process_main_queue
->spec
.hold
= 50;
2645 /* Use a higher yield value of 50ms for main queue processing */
2646 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2649 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2651 struct bgp_process_queue
*pqnode
;
2653 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2654 sizeof(struct bgp_process_queue
));
2656 /* unlocked in bgp_processq_del */
2657 pqnode
->bgp
= bgp_lock(bgp
);
2658 STAILQ_INIT(&pqnode
->pqueue
);
2663 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2665 #define ARBITRARY_PROCESS_QLEN 10000
2666 struct work_queue
*wq
= bm
->process_main_queue
;
2667 struct bgp_process_queue
*pqnode
;
2668 int pqnode_reuse
= 0;
2670 /* already scheduled for processing? */
2671 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2677 /* Add route nodes to an existing work queue item until reaching the
2678 limit only if is from the same BGP view and it's not an EOIU marker
2680 if (work_queue_item_count(wq
)) {
2681 struct work_queue_item
*item
= work_queue_last_item(wq
);
2682 pqnode
= item
->data
;
2684 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2685 || pqnode
->bgp
!= bgp
2686 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2687 pqnode
= bgp_processq_alloc(bgp
);
2691 pqnode
= bgp_processq_alloc(bgp
);
2692 /* all unlocked in bgp_process_wq */
2693 bgp_table_lock(bgp_node_table(rn
));
2695 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2698 /* can't be enqueued twice */
2699 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2700 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2704 work_queue_add(wq
, pqnode
);
2709 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2711 struct bgp_process_queue
*pqnode
;
2713 if (bm
->process_main_queue
== NULL
)
2716 pqnode
= bgp_processq_alloc(bgp
);
2718 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2719 work_queue_add(bm
->process_main_queue
, pqnode
);
2722 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2726 peer
= THREAD_ARG(thread
);
2727 peer
->t_pmax_restart
= NULL
;
2729 if (bgp_debug_neighbor_events(peer
))
2731 "%s Maximum-prefix restart timer expired, restore peering",
2734 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2735 zlog_debug("%s: %s peer_clear failed",
2736 __PRETTY_FUNCTION__
, peer
->host
);
2741 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2745 iana_safi_t pkt_safi
;
2747 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2750 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2751 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2752 PEER_STATUS_PREFIX_LIMIT
)
2757 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2758 " exceed, limit %" PRIu32
,
2759 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2760 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2761 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2763 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2764 PEER_FLAG_MAX_PREFIX_WARNING
))
2767 /* Convert AFI, SAFI to values for packet. */
2768 pkt_afi
= afi_int2iana(afi
);
2769 pkt_safi
= safi_int2iana(safi
);
2773 ndata
[0] = (pkt_afi
>> 8);
2775 ndata
[2] = pkt_safi
;
2776 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2777 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2778 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2779 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2781 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2782 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2783 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2787 /* Dynamic peers will just close their connection. */
2788 if (peer_dynamic_neighbor(peer
))
2791 /* restart timer start */
2792 if (peer
->pmax_restart
[afi
][safi
]) {
2793 peer
->v_pmax_restart
=
2794 peer
->pmax_restart
[afi
][safi
] * 60;
2796 if (bgp_debug_neighbor_events(peer
))
2798 "%s Maximum-prefix restart timer started for %d secs",
2799 peer
->host
, peer
->v_pmax_restart
);
2801 BGP_TIMER_ON(peer
->t_pmax_restart
,
2802 bgp_maximum_prefix_restart_timer
,
2803 peer
->v_pmax_restart
);
2808 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2809 PEER_STATUS_PREFIX_LIMIT
);
2811 if (peer
->pcount
[afi
][safi
]
2812 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2813 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2814 PEER_STATUS_PREFIX_THRESHOLD
)
2819 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
2821 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2822 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2823 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2824 PEER_STATUS_PREFIX_THRESHOLD
);
2826 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2827 PEER_STATUS_PREFIX_THRESHOLD
);
2831 /* Unconditionally remove the route from the RIB, without taking
2832 * damping into consideration (eg, because the session went down)
2834 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2835 struct peer
*peer
, afi_t afi
, safi_t safi
)
2837 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2839 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2840 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2842 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, rn
, peer
, true);
2844 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2847 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2848 struct peer
*peer
, afi_t afi
, safi_t safi
,
2849 struct prefix_rd
*prd
)
2851 /* apply dampening, if result is suppressed, we'll be retaining
2852 * the bgp_path_info in the RIB for historical reference.
2854 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2855 && peer
->sort
== BGP_PEER_EBGP
)
2856 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2857 == BGP_DAMP_SUPPRESSED
) {
2858 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2864 if (safi
== SAFI_MPLS_VPN
) {
2865 struct bgp_node
*prn
= NULL
;
2866 struct bgp_table
*table
= NULL
;
2868 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2869 (struct prefix
*)prd
);
2870 if (bgp_node_has_bgp_path_info_data(prn
)) {
2871 table
= bgp_node_get_bgp_table_info(prn
);
2873 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2874 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2876 bgp_unlock_node(prn
);
2878 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2879 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2881 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2882 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2888 /* If this is an EVPN route, process for un-import. */
2889 if (safi
== SAFI_EVPN
)
2890 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2892 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2895 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2896 struct peer
*peer
, struct attr
*attr
,
2897 struct bgp_node
*rn
)
2899 struct bgp_path_info
*new;
2901 /* Make new BGP info. */
2902 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2904 new->instance
= instance
;
2905 new->sub_type
= sub_type
;
2908 new->uptime
= bgp_clock();
2913 static void overlay_index_update(struct attr
*attr
,
2914 struct eth_segment_id
*eth_s_id
,
2915 union gw_addr
*gw_ip
)
2920 if (eth_s_id
== NULL
) {
2921 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2922 sizeof(struct eth_segment_id
));
2924 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2925 sizeof(struct eth_segment_id
));
2927 if (gw_ip
== NULL
) {
2928 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2930 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2931 sizeof(union gw_addr
));
2935 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2936 struct eth_segment_id
*eth_s_id
,
2937 union gw_addr
*gw_ip
)
2939 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2940 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2942 struct eth_segment_id esi
;
2946 if (afi
!= AFI_L2VPN
)
2949 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2950 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2952 if (gw_ip
== NULL
) {
2953 memset(&temp
, 0, sizeof(temp
));
2954 path_gw_ip_remote
= &temp
.ip
;
2956 path_gw_ip_remote
= gw_ip
;
2958 if (eth_s_id
== NULL
) {
2959 memset(&temp
, 0, sizeof(temp
));
2960 path_eth_s_id_remote
= &temp
.esi
;
2962 path_eth_s_id_remote
= eth_s_id
;
2964 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2967 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2968 sizeof(struct eth_segment_id
));
2971 /* Check if received nexthop is valid or not. */
2972 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2977 /* Only validated for unicast and multicast currently. */
2978 /* Also valid for EVPN where the nexthop is an IP address. */
2979 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2982 /* If NEXT_HOP is present, validate it. */
2983 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2984 if (attr
->nexthop
.s_addr
== 0
2985 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2986 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2990 /* If MP_NEXTHOP is present, validate it. */
2991 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2992 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2993 * it is not an IPv6 link-local address.
2995 if (attr
->mp_nexthop_len
) {
2996 switch (attr
->mp_nexthop_len
) {
2997 case BGP_ATTR_NHLEN_IPV4
:
2998 case BGP_ATTR_NHLEN_VPNV4
:
2999 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
3000 || IPV4_CLASS_DE(ntohl(
3001 attr
->mp_nexthop_global_in
.s_addr
))
3002 || bgp_nexthop_self(bgp
,
3003 attr
->mp_nexthop_global_in
));
3006 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3007 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3008 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3009 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
3010 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3011 || IN6_IS_ADDR_MULTICAST(
3012 &attr
->mp_nexthop_global
));
3024 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3025 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3026 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3027 uint32_t num_labels
, int soft_reconfig
,
3028 struct bgp_route_evpn
*evpn
)
3031 int aspath_loop_count
= 0;
3032 struct bgp_node
*rn
;
3034 struct attr new_attr
;
3035 struct attr
*attr_new
;
3036 struct bgp_path_info
*pi
;
3037 struct bgp_path_info
*new;
3038 struct bgp_path_info_extra
*extra
;
3040 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3042 int do_loop_check
= 1;
3043 int has_valid_label
= 0;
3046 int vnc_implicit_withdraw
= 0;
3050 memset(&new_attr
, 0, sizeof(struct attr
));
3051 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3052 new_attr
.label
= MPLS_INVALID_LABEL
;
3055 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3056 /* TODO: Check to see if we can get rid of "is_valid_label" */
3057 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3058 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3060 has_valid_label
= bgp_is_valid_label(label
);
3062 /* When peer's soft reconfiguration enabled. Record input packet in
3065 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3066 && peer
!= bgp
->peer_self
)
3067 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3069 /* Check previously received route. */
3070 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3071 if (pi
->peer
== peer
&& pi
->type
== type
3072 && pi
->sub_type
== sub_type
3073 && pi
->addpath_rx_id
== addpath_id
)
3076 /* AS path local-as loop check. */
3077 if (peer
->change_local_as
) {
3078 if (peer
->allowas_in
[afi
][safi
])
3079 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3080 else if (!CHECK_FLAG(peer
->flags
,
3081 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3082 aspath_loop_count
= 1;
3084 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3085 > aspath_loop_count
) {
3086 peer
->stat_pfx_aspath_loop
++;
3087 reason
= "as-path contains our own AS;";
3092 /* If the peer is configured for "allowas-in origin" and the last ASN in
3094 * as-path is our ASN then we do not need to call aspath_loop_check
3096 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3097 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3100 /* AS path loop check. */
3101 if (do_loop_check
) {
3102 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3103 > peer
->allowas_in
[afi
][safi
]
3104 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3105 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3106 > peer
->allowas_in
[afi
][safi
])) {
3107 peer
->stat_pfx_aspath_loop
++;
3108 reason
= "as-path contains our own AS;";
3113 /* Route reflector originator ID check. */
3114 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3115 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3116 peer
->stat_pfx_originator_loop
++;
3117 reason
= "originator is us;";
3121 /* Route reflector cluster ID check. */
3122 if (bgp_cluster_filter(peer
, attr
)) {
3123 peer
->stat_pfx_cluster_loop
++;
3124 reason
= "reflected from the same cluster;";
3128 /* Apply incoming filter. */
3129 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3130 peer
->stat_pfx_filter
++;
3135 /* RFC 8212 to prevent route leaks.
3136 * This specification intends to improve this situation by requiring the
3137 * explicit configuration of both BGP Import and Export Policies for any
3138 * External BGP (EBGP) session such as customers, peers, or
3139 * confederation boundaries for all enabled address families. Through
3140 * codification of the aforementioned requirement, operators will
3141 * benefit from consistent behavior across different BGP
3144 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3145 if (!bgp_inbound_policy_exists(peer
,
3146 &peer
->filter
[afi
][safi
])) {
3147 reason
= "inbound policy missing";
3151 bgp_attr_dup(&new_attr
, attr
);
3153 /* Apply incoming route-map.
3154 * NB: new_attr may now contain newly allocated values from route-map
3156 * commands, so we need bgp_attr_flush in the error paths, until we
3158 * the attr (which takes over the memory references) */
3159 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
,
3160 label
, num_labels
, rn
) == RMAP_DENY
) {
3161 peer
->stat_pfx_filter
++;
3162 reason
= "route-map;";
3163 bgp_attr_flush(&new_attr
);
3167 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3168 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3169 /* remove from RIB previous entry */
3170 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3173 if (peer
->sort
== BGP_PEER_EBGP
) {
3175 /* If we receive the graceful-shutdown community from an eBGP
3176 * peer we must lower local-preference */
3177 if (new_attr
.community
3178 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3179 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3180 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3182 /* If graceful-shutdown is configured then add the GSHUT
3183 * community to all paths received from eBGP peers */
3184 } else if (bgp_flag_check(peer
->bgp
,
3185 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3186 bgp_attr_add_gshut_community(&new_attr
);
3190 /* next hop check. */
3191 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3192 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3193 peer
->stat_pfx_nh_invalid
++;
3194 reason
= "martian or self next-hop;";
3195 bgp_attr_flush(&new_attr
);
3199 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3200 peer
->stat_pfx_nh_invalid
++;
3201 reason
= "self mac;";
3205 attr_new
= bgp_attr_intern(&new_attr
);
3207 /* If the update is implicit withdraw. */
3209 pi
->uptime
= bgp_clock();
3210 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3212 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3214 /* Same attribute comes in. */
3215 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3216 && attrhash_cmp(pi
->attr
, attr_new
)
3217 && (!has_valid_label
3218 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3219 num_labels
* sizeof(mpls_label_t
))
3221 && (overlay_index_equal(
3222 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3223 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3224 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3225 BGP_CONFIG_DAMPENING
)
3226 && peer
->sort
== BGP_PEER_EBGP
3227 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3228 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3229 bgp_debug_rdpfxpath2str(
3230 afi
, safi
, prd
, p
, label
,
3231 num_labels
, addpath_id
? 1 : 0,
3232 addpath_id
, pfx_buf
,
3234 zlog_debug("%s rcvd %s", peer
->host
,
3238 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3239 != BGP_DAMP_SUPPRESSED
) {
3240 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3242 bgp_process(bgp
, rn
, afi
, safi
);
3244 } else /* Duplicate - odd */
3246 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3247 if (!peer
->rcvd_attr_printed
) {
3249 "%s rcvd UPDATE w/ attr: %s",
3251 peer
->rcvd_attr_str
);
3252 peer
->rcvd_attr_printed
= 1;
3255 bgp_debug_rdpfxpath2str(
3256 afi
, safi
, prd
, p
, label
,
3257 num_labels
, addpath_id
? 1 : 0,
3258 addpath_id
, pfx_buf
,
3261 "%s rcvd %s...duplicate ignored",
3262 peer
->host
, pfx_buf
);
3265 /* graceful restart STALE flag unset. */
3266 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3267 bgp_path_info_unset_flag(
3268 rn
, pi
, BGP_PATH_STALE
);
3269 bgp_process(bgp
, rn
, afi
, safi
);
3273 bgp_unlock_node(rn
);
3274 bgp_attr_unintern(&attr_new
);
3279 /* Withdraw/Announce before we fully processed the withdraw */
3280 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3281 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3282 bgp_debug_rdpfxpath2str(
3283 afi
, safi
, prd
, p
, label
, num_labels
,
3284 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3287 "%s rcvd %s, flapped quicker than processing",
3288 peer
->host
, pfx_buf
);
3291 bgp_path_info_restore(rn
, pi
);
3294 /* Received Logging. */
3295 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3296 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3297 num_labels
, addpath_id
? 1 : 0,
3298 addpath_id
, pfx_buf
,
3300 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3303 /* graceful restart STALE flag unset. */
3304 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3305 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3307 /* The attribute is changed. */
3308 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3310 /* implicit withdraw, decrement aggregate and pcount here.
3311 * only if update is accepted, they'll increment below.
3313 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3315 /* Update bgp route dampening information. */
3316 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3317 && peer
->sort
== BGP_PEER_EBGP
) {
3318 /* This is implicit withdraw so we should update
3321 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3322 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3325 if (safi
== SAFI_MPLS_VPN
) {
3326 struct bgp_node
*prn
= NULL
;
3327 struct bgp_table
*table
= NULL
;
3329 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3330 (struct prefix
*)prd
);
3331 if (bgp_node_has_bgp_path_info_data(prn
)) {
3332 table
= bgp_node_get_bgp_table_info(prn
);
3334 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3335 bgp
, prd
, table
, p
, pi
);
3337 bgp_unlock_node(prn
);
3339 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3340 && (safi
== SAFI_UNICAST
)) {
3341 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3343 * Implicit withdraw case.
3345 ++vnc_implicit_withdraw
;
3346 vnc_import_bgp_del_route(bgp
, p
, pi
);
3347 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3352 /* Special handling for EVPN update of an existing route. If the
3353 * extended community attribute has changed, we need to
3355 * the route using its existing extended community. It will be
3356 * subsequently processed for import with the new extended
3359 if (safi
== SAFI_EVPN
&& !same_attr
) {
3361 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3363 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3366 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3367 attr_new
->ecommunity
);
3369 if (bgp_debug_update(peer
, p
, NULL
, 1))
3371 "Change in EXT-COMM, existing %s new %s",
3373 pi
->attr
->ecommunity
),
3375 attr_new
->ecommunity
));
3376 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3382 /* Update to new attribute. */
3383 bgp_attr_unintern(&pi
->attr
);
3384 pi
->attr
= attr_new
;
3386 /* Update MPLS label */
3387 if (has_valid_label
) {
3388 extra
= bgp_path_info_extra_get(pi
);
3389 if (extra
->label
!= label
) {
3390 memcpy(&extra
->label
, label
,
3391 num_labels
* sizeof(mpls_label_t
));
3392 extra
->num_labels
= num_labels
;
3394 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3395 bgp_set_valid_label(&extra
->label
[0]);
3399 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3400 && (safi
== SAFI_UNICAST
)) {
3401 if (vnc_implicit_withdraw
) {
3403 * Add back the route with its new attributes
3405 * The route is still selected, until the route
3407 * queued by bgp_process actually runs. We have
3409 * update to the VNC side immediately to avoid
3411 * configuration changes (e.g., route-map
3413 * trigger re-importation of the entire RIB.
3415 vnc_import_bgp_add_route(bgp
, p
, pi
);
3416 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3420 /* Update Overlay Index */
3421 if (afi
== AFI_L2VPN
) {
3422 overlay_index_update(
3423 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3424 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3427 /* Update bgp route dampening information. */
3428 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3429 && peer
->sort
== BGP_PEER_EBGP
) {
3430 /* Now we do normal update dampening. */
3431 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3432 if (ret
== BGP_DAMP_SUPPRESSED
) {
3433 bgp_unlock_node(rn
);
3438 /* Nexthop reachability check - for unicast and
3439 * labeled-unicast.. */
3440 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3441 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3442 || (safi
== SAFI_EVPN
&&
3443 bgp_evpn_is_prefix_nht_supported(p
))) {
3444 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3445 && !CHECK_FLAG(peer
->flags
,
3446 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3448 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3453 struct bgp
*bgp_nexthop
= bgp
;
3455 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3456 bgp_nexthop
= pi
->extra
->bgp_orig
;
3458 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3460 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3461 pi
, NULL
, connected
)
3462 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3463 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3465 if (BGP_DEBUG(nht
, NHT
)) {
3466 char buf1
[INET6_ADDRSTRLEN
];
3468 (const void *)&attr_new
3470 buf1
, INET6_ADDRSTRLEN
);
3471 zlog_debug("%s(%s): NH unresolved",
3472 __FUNCTION__
, buf1
);
3474 bgp_path_info_unset_flag(rn
, pi
,
3478 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3481 if (safi
== SAFI_MPLS_VPN
) {
3482 struct bgp_node
*prn
= NULL
;
3483 struct bgp_table
*table
= NULL
;
3485 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3486 (struct prefix
*)prd
);
3487 if (bgp_node_has_bgp_path_info_data(prn
)) {
3488 table
= bgp_node_get_bgp_table_info(prn
);
3490 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3491 bgp
, prd
, table
, p
, pi
);
3493 bgp_unlock_node(prn
);
3497 /* If this is an EVPN route and some attribute has changed,
3499 * route for import. If the extended community has changed, we
3501 * have done the un-import earlier and the import would result
3503 * route getting injected into appropriate L2 VNIs. If it is
3505 * some other attribute change, the import will result in
3507 * the attributes for the route in the VNI(s).
3509 if (safi
== SAFI_EVPN
&& !same_attr
&&
3510 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3511 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3513 /* Process change. */
3514 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3516 bgp_process(bgp
, rn
, afi
, safi
);
3517 bgp_unlock_node(rn
);
3519 if (SAFI_UNICAST
== safi
3520 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3521 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3523 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3525 if ((SAFI_MPLS_VPN
== safi
)
3526 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3528 vpn_leak_to_vrf_update(bgp
, pi
);
3532 if (SAFI_MPLS_VPN
== safi
) {
3533 mpls_label_t label_decoded
= decode_label(label
);
3535 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3536 type
, sub_type
, &label_decoded
);
3538 if (SAFI_ENCAP
== safi
) {
3539 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3540 type
, sub_type
, NULL
);
3545 } // End of implicit withdraw
3547 /* Received Logging. */
3548 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3549 if (!peer
->rcvd_attr_printed
) {
3550 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3551 peer
->rcvd_attr_str
);
3552 peer
->rcvd_attr_printed
= 1;
3555 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3556 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3558 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3561 /* Make new BGP info. */
3562 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3564 /* Update MPLS label */
3565 if (has_valid_label
) {
3566 extra
= bgp_path_info_extra_get(new);
3567 if (extra
->label
!= label
) {
3568 memcpy(&extra
->label
, label
,
3569 num_labels
* sizeof(mpls_label_t
));
3570 extra
->num_labels
= num_labels
;
3572 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3573 bgp_set_valid_label(&extra
->label
[0]);
3576 /* Update Overlay Index */
3577 if (afi
== AFI_L2VPN
) {
3578 overlay_index_update(new->attr
,
3579 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3580 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3582 /* Nexthop reachability check. */
3583 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3584 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3585 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
3586 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3587 && !CHECK_FLAG(peer
->flags
,
3588 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3589 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3594 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
3596 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
3598 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3599 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3601 if (BGP_DEBUG(nht
, NHT
)) {
3602 char buf1
[INET6_ADDRSTRLEN
];
3604 (const void *)&attr_new
->nexthop
,
3605 buf1
, INET6_ADDRSTRLEN
);
3606 zlog_debug("%s(%s): NH unresolved",
3607 __FUNCTION__
, buf1
);
3609 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3612 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3615 new->addpath_rx_id
= addpath_id
;
3617 /* Increment prefix */
3618 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3620 /* Register new BGP information. */
3621 bgp_path_info_add(rn
, new);
3623 /* route_node_get lock */
3624 bgp_unlock_node(rn
);
3627 if (safi
== SAFI_MPLS_VPN
) {
3628 struct bgp_node
*prn
= NULL
;
3629 struct bgp_table
*table
= NULL
;
3631 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3632 if (bgp_node_has_bgp_path_info_data(prn
)) {
3633 table
= bgp_node_get_bgp_table_info(prn
);
3635 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3636 bgp
, prd
, table
, p
, new);
3638 bgp_unlock_node(prn
);
3642 /* If maximum prefix count is configured and current prefix
3644 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3647 /* If this is an EVPN route, process for import. */
3648 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
3649 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3651 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3653 /* Process change. */
3654 bgp_process(bgp
, rn
, afi
, safi
);
3656 if (SAFI_UNICAST
== safi
3657 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3658 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3659 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3661 if ((SAFI_MPLS_VPN
== safi
)
3662 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3664 vpn_leak_to_vrf_update(bgp
, new);
3667 if (SAFI_MPLS_VPN
== safi
) {
3668 mpls_label_t label_decoded
= decode_label(label
);
3670 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3671 sub_type
, &label_decoded
);
3673 if (SAFI_ENCAP
== safi
) {
3674 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3681 /* This BGP update is filtered. Log the reason then update BGP
3684 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3686 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3687 if (!peer
->rcvd_attr_printed
) {
3688 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3689 peer
->rcvd_attr_str
);
3690 peer
->rcvd_attr_printed
= 1;
3693 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3694 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3696 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3697 peer
->host
, pfx_buf
, reason
);
3701 /* If this is an EVPN route, un-import it as it is now filtered.
3703 if (safi
== SAFI_EVPN
)
3704 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3706 if (SAFI_UNICAST
== safi
3707 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3708 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3710 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3712 if ((SAFI_MPLS_VPN
== safi
)
3713 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3715 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3718 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3721 bgp_unlock_node(rn
);
3725 * Filtered update is treated as an implicit withdrawal (see
3727 * a few lines above)
3729 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3730 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3738 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3739 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3740 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3741 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3744 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3745 struct bgp_node
*rn
;
3746 struct bgp_path_info
*pi
;
3749 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3750 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3758 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3760 /* If peer is soft reconfiguration enabled. Record input packet for
3761 * further calculation.
3763 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3764 * routes that are filtered. This tanks out Quagga RS pretty badly due
3766 * the iteration over all RS clients.
3767 * Since we need to remove the entry from adj_in anyway, do that first
3769 * if there was no entry, we don't need to do anything more.
3771 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3772 && peer
!= bgp
->peer_self
)
3773 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3774 peer
->stat_pfx_dup_withdraw
++;
3776 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3777 bgp_debug_rdpfxpath2str(
3778 afi
, safi
, prd
, p
, label
, num_labels
,
3779 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3782 "%s withdrawing route %s not in adj-in",
3783 peer
->host
, pfx_buf
);
3785 bgp_unlock_node(rn
);
3789 /* Lookup withdrawn route. */
3790 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3791 if (pi
->peer
== peer
&& pi
->type
== type
3792 && pi
->sub_type
== sub_type
3793 && pi
->addpath_rx_id
== addpath_id
)
3797 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3798 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3799 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3801 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3805 /* Withdraw specified route from routing table. */
3806 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3807 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3808 if (SAFI_UNICAST
== safi
3809 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3810 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3811 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3813 if ((SAFI_MPLS_VPN
== safi
)
3814 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3816 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3818 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3819 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3820 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3822 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3825 /* Unlock bgp_node_get() lock. */
3826 bgp_unlock_node(rn
);
3831 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3834 struct update_subgroup
*subgrp
;
3835 subgrp
= peer_subgroup(peer
, afi
, safi
);
3836 subgroup_default_originate(subgrp
, withdraw
);
3841 * bgp_stop_announce_route_timer
3843 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3845 if (!paf
->t_announce_route
)
3848 THREAD_TIMER_OFF(paf
->t_announce_route
);
3852 * bgp_announce_route_timer_expired
3854 * Callback that is invoked when the route announcement timer for a
3857 static int bgp_announce_route_timer_expired(struct thread
*t
)
3859 struct peer_af
*paf
;
3862 paf
= THREAD_ARG(t
);
3865 if (peer
->status
!= Established
)
3868 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3871 peer_af_announce_route(paf
, 1);
3876 * bgp_announce_route
3878 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3880 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3882 struct peer_af
*paf
;
3883 struct update_subgroup
*subgrp
;
3885 paf
= peer_af_find(peer
, afi
, safi
);
3888 subgrp
= PAF_SUBGRP(paf
);
3891 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3892 * or a refresh has already been triggered.
3894 if (!subgrp
|| paf
->t_announce_route
)
3898 * Start a timer to stagger/delay the announce. This serves
3899 * two purposes - announcement can potentially be combined for
3900 * multiple peers and the announcement doesn't happen in the
3903 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3904 (subgrp
->peer_count
== 1)
3905 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3906 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3907 &paf
->t_announce_route
);
3911 * Announce routes from all AF tables to a peer.
3913 * This should ONLY be called when there is a need to refresh the
3914 * routes to the peer based on a policy change for this peer alone
3915 * or a route refresh request received from the peer.
3916 * The operation will result in splitting the peer from its existing
3917 * subgroups and putting it in new subgroups.
3919 void bgp_announce_route_all(struct peer
*peer
)
3924 FOREACH_AFI_SAFI (afi
, safi
)
3925 bgp_announce_route(peer
, afi
, safi
);
3928 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3929 struct bgp_table
*table
,
3930 struct prefix_rd
*prd
)
3933 struct bgp_node
*rn
;
3934 struct bgp_adj_in
*ain
;
3937 table
= peer
->bgp
->rib
[afi
][safi
];
3939 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3940 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3941 if (ain
->peer
!= peer
)
3944 struct bgp_path_info
*pi
;
3945 uint32_t num_labels
= 0;
3946 mpls_label_t
*label_pnt
= NULL
;
3947 struct bgp_route_evpn evpn
;
3949 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
3951 if (pi
->peer
== peer
)
3954 if (pi
&& pi
->extra
)
3955 num_labels
= pi
->extra
->num_labels
;
3957 label_pnt
= &pi
->extra
->label
[0];
3959 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3962 memset(&evpn
, 0, sizeof(evpn
));
3964 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3965 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3966 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3967 num_labels
, 1, &evpn
);
3970 bgp_unlock_node(rn
);
3976 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3978 struct bgp_node
*rn
;
3979 struct bgp_table
*table
;
3981 if (peer
->status
!= Established
)
3984 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3985 && (safi
!= SAFI_EVPN
))
3986 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3988 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3989 rn
= bgp_route_next(rn
)) {
3990 table
= bgp_node_get_bgp_table_info(rn
);
3991 if (table
!= NULL
) {
3992 struct prefix_rd prd
;
3994 prd
.family
= AF_UNSPEC
;
3996 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3998 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
4005 struct bgp_clear_node_queue
{
4006 struct bgp_node
*rn
;
4009 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4011 struct bgp_clear_node_queue
*cnq
= data
;
4012 struct bgp_node
*rn
= cnq
->rn
;
4013 struct peer
*peer
= wq
->spec
.data
;
4014 struct bgp_path_info
*pi
;
4016 afi_t afi
= bgp_node_table(rn
)->afi
;
4017 safi_t safi
= bgp_node_table(rn
)->safi
;
4022 /* It is possible that we have multiple paths for a prefix from a peer
4023 * if that peer is using AddPath.
4025 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4026 if (pi
->peer
!= peer
)
4029 /* graceful restart STALE flag set. */
4030 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4031 && peer
->nsf
[afi
][safi
]
4032 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4033 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4034 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4036 /* If this is an EVPN route, process for
4038 if (safi
== SAFI_EVPN
)
4039 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
4041 /* Handle withdraw for VRF route-leaking and L3VPN */
4042 if (SAFI_UNICAST
== safi
4043 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4044 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4045 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4048 if (SAFI_MPLS_VPN
== safi
&&
4049 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4050 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4053 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4059 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4061 struct bgp_clear_node_queue
*cnq
= data
;
4062 struct bgp_node
*rn
= cnq
->rn
;
4063 struct bgp_table
*table
= bgp_node_table(rn
);
4065 bgp_unlock_node(rn
);
4066 bgp_table_unlock(table
);
4067 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4070 static void bgp_clear_node_complete(struct work_queue
*wq
)
4072 struct peer
*peer
= wq
->spec
.data
;
4074 /* Tickle FSM to start moving again */
4075 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4077 peer_unlock(peer
); /* bgp_clear_route */
4080 static void bgp_clear_node_queue_init(struct peer
*peer
)
4082 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4084 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4085 #undef CLEAR_QUEUE_NAME_LEN
4087 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4088 peer
->clear_node_queue
->spec
.hold
= 10;
4089 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4090 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4091 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4092 peer
->clear_node_queue
->spec
.max_retries
= 0;
4094 /* we only 'lock' this peer reference when the queue is actually active
4096 peer
->clear_node_queue
->spec
.data
= peer
;
4099 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4100 struct bgp_table
*table
)
4102 struct bgp_node
*rn
;
4103 int force
= bm
->process_main_queue
? 0 : 1;
4106 table
= peer
->bgp
->rib
[afi
][safi
];
4108 /* If still no table => afi/safi isn't configured at all or smth. */
4112 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4113 struct bgp_path_info
*pi
, *next
;
4114 struct bgp_adj_in
*ain
;
4115 struct bgp_adj_in
*ain_next
;
4117 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4118 * queued for every clearing peer, regardless of whether it is
4119 * relevant to the peer at hand.
4121 * Overview: There are 3 different indices which need to be
4122 * scrubbed, potentially, when a peer is removed:
4124 * 1 peer's routes visible via the RIB (ie accepted routes)
4125 * 2 peer's routes visible by the (optional) peer's adj-in index
4126 * 3 other routes visible by the peer's adj-out index
4128 * 3 there is no hurry in scrubbing, once the struct peer is
4129 * removed from bgp->peer, we could just GC such deleted peer's
4130 * adj-outs at our leisure.
4132 * 1 and 2 must be 'scrubbed' in some way, at least made
4133 * invisible via RIB index before peer session is allowed to be
4134 * brought back up. So one needs to know when such a 'search' is
4139 * - there'd be a single global queue or a single RIB walker
4140 * - rather than tracking which route_nodes still need to be
4141 * examined on a peer basis, we'd track which peers still
4144 * Given that our per-peer prefix-counts now should be reliable,
4145 * this may actually be achievable. It doesn't seem to be a huge
4146 * problem at this time,
4148 * It is possible that we have multiple paths for a prefix from
4150 * if that peer is using AddPath.
4154 ain_next
= ain
->next
;
4156 if (ain
->peer
== peer
) {
4157 bgp_adj_in_remove(rn
, ain
);
4158 bgp_unlock_node(rn
);
4164 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4166 if (pi
->peer
!= peer
)
4170 bgp_path_info_reap(rn
, pi
);
4172 struct bgp_clear_node_queue
*cnq
;
4174 /* both unlocked in bgp_clear_node_queue_del */
4175 bgp_table_lock(bgp_node_table(rn
));
4178 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4179 sizeof(struct bgp_clear_node_queue
));
4181 work_queue_add(peer
->clear_node_queue
, cnq
);
4189 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4191 struct bgp_node
*rn
;
4192 struct bgp_table
*table
;
4194 if (peer
->clear_node_queue
== NULL
)
4195 bgp_clear_node_queue_init(peer
);
4197 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4198 * Idle until it receives a Clearing_Completed event. This protects
4199 * against peers which flap faster than we can we clear, which could
4202 * a) race with routes from the new session being installed before
4203 * clear_route_node visits the node (to delete the route of that
4205 * b) resource exhaustion, clear_route_node likely leads to an entry
4206 * on the process_main queue. Fast-flapping could cause that queue
4210 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4211 * the unlock will happen upon work-queue completion; other wise, the
4212 * unlock happens at the end of this function.
4214 if (!peer
->clear_node_queue
->thread
)
4217 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4218 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4220 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4221 rn
= bgp_route_next(rn
)) {
4222 table
= bgp_node_get_bgp_table_info(rn
);
4226 bgp_clear_route_table(peer
, afi
, safi
, table
);
4229 /* unlock if no nodes got added to the clear-node-queue. */
4230 if (!peer
->clear_node_queue
->thread
)
4234 void bgp_clear_route_all(struct peer
*peer
)
4239 FOREACH_AFI_SAFI (afi
, safi
)
4240 bgp_clear_route(peer
, afi
, safi
);
4243 rfapiProcessPeerDown(peer
);
4247 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4249 struct bgp_table
*table
;
4250 struct bgp_node
*rn
;
4251 struct bgp_adj_in
*ain
;
4252 struct bgp_adj_in
*ain_next
;
4254 table
= peer
->bgp
->rib
[afi
][safi
];
4256 /* It is possible that we have multiple paths for a prefix from a peer
4257 * if that peer is using AddPath.
4259 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4263 ain_next
= ain
->next
;
4265 if (ain
->peer
== peer
) {
4266 bgp_adj_in_remove(rn
, ain
);
4267 bgp_unlock_node(rn
);
4275 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4277 struct bgp_node
*rn
;
4278 struct bgp_path_info
*pi
;
4279 struct bgp_table
*table
;
4281 if (safi
== SAFI_MPLS_VPN
) {
4282 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4283 rn
= bgp_route_next(rn
)) {
4284 struct bgp_node
*rm
;
4286 /* look for neighbor in tables */
4287 table
= bgp_node_get_bgp_table_info(rn
);
4291 for (rm
= bgp_table_top(table
); rm
;
4292 rm
= bgp_route_next(rm
))
4293 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4295 if (pi
->peer
!= peer
)
4297 if (!CHECK_FLAG(pi
->flags
,
4301 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4306 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4307 rn
= bgp_route_next(rn
))
4308 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4310 if (pi
->peer
!= peer
)
4312 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4314 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4320 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4322 if (peer
->sort
== BGP_PEER_EBGP
4323 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4324 || FILTER_LIST_OUT_NAME(filter
)
4325 || DISTRIBUTE_OUT_NAME(filter
)))
4330 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4332 if (peer
->sort
== BGP_PEER_EBGP
4333 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4334 || FILTER_LIST_IN_NAME(filter
)
4335 || DISTRIBUTE_IN_NAME(filter
)))
4340 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4343 struct bgp_node
*rn
;
4344 struct bgp_path_info
*pi
;
4345 struct bgp_path_info
*next
;
4347 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4348 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4351 /* Unimport EVPN routes from VRFs */
4352 if (safi
== SAFI_EVPN
)
4353 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4357 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4358 && pi
->type
== ZEBRA_ROUTE_BGP
4359 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4360 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4361 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4363 if (bgp_fibupd_safi(safi
))
4364 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4366 bgp_path_info_reap(rn
, pi
);
4371 /* Delete all kernel routes. */
4372 void bgp_cleanup_routes(struct bgp
*bgp
)
4375 struct bgp_node
*rn
;
4376 struct bgp_table
*table
;
4378 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4379 if (afi
== AFI_L2VPN
)
4381 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4384 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4386 if (afi
!= AFI_L2VPN
) {
4388 safi
= SAFI_MPLS_VPN
;
4389 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4390 rn
= bgp_route_next(rn
)) {
4391 table
= bgp_node_get_bgp_table_info(rn
);
4392 if (table
!= NULL
) {
4393 bgp_cleanup_table(bgp
, table
, safi
);
4394 bgp_table_finish(&table
);
4395 bgp_node_set_bgp_table_info(rn
, NULL
);
4396 bgp_unlock_node(rn
);
4400 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4401 rn
= bgp_route_next(rn
)) {
4402 table
= bgp_node_get_bgp_table_info(rn
);
4403 if (table
!= NULL
) {
4404 bgp_cleanup_table(bgp
, table
, safi
);
4405 bgp_table_finish(&table
);
4406 bgp_node_set_bgp_table_info(rn
, NULL
);
4407 bgp_unlock_node(rn
);
4412 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4413 rn
= bgp_route_next(rn
)) {
4414 table
= bgp_node_get_bgp_table_info(rn
);
4415 if (table
!= NULL
) {
4416 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4417 bgp_table_finish(&table
);
4418 bgp_node_set_bgp_table_info(rn
, NULL
);
4419 bgp_unlock_node(rn
);
4424 void bgp_reset(void)
4427 bgp_zclient_reset();
4428 access_list_reset();
4429 prefix_list_reset();
4432 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4434 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4435 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4436 PEER_CAP_ADDPATH_AF_TX_RCV
));
4439 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4441 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4442 struct bgp_nlri
*packet
)
4451 int addpath_encoded
;
4452 uint32_t addpath_id
;
4455 lim
= pnt
+ packet
->length
;
4457 safi
= packet
->safi
;
4459 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4461 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4462 syntactic validity. If the field is syntactically incorrect,
4463 then the Error Subcode is set to Invalid Network Field. */
4464 for (; pnt
< lim
; pnt
+= psize
) {
4465 /* Clear prefix structure. */
4466 memset(&p
, 0, sizeof(struct prefix
));
4468 if (addpath_encoded
) {
4470 /* When packet overflow occurs return immediately. */
4471 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4472 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4474 addpath_id
= ntohl(*((uint32_t *)pnt
));
4475 pnt
+= BGP_ADDPATH_ID_LEN
;
4478 /* Fetch prefix length. */
4479 p
.prefixlen
= *pnt
++;
4480 /* afi/safi validity already verified by caller,
4481 * bgp_update_receive */
4482 p
.family
= afi2family(afi
);
4484 /* Prefix length check. */
4485 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4488 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4489 peer
->host
, p
.prefixlen
, packet
->afi
);
4490 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4493 /* Packet size overflow check. */
4494 psize
= PSIZE(p
.prefixlen
);
4496 /* When packet overflow occur return immediately. */
4497 if (pnt
+ psize
> lim
) {
4500 "%s [Error] Update packet error (prefix length %d overflows packet)",
4501 peer
->host
, p
.prefixlen
);
4502 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4505 /* Defensive coding, double-check the psize fits in a struct
4507 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4510 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4511 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4512 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4515 /* Fetch prefix from NLRI packet. */
4516 memcpy(p
.u
.val
, pnt
, psize
);
4518 /* Check address. */
4519 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4520 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4521 /* From RFC4271 Section 6.3:
4523 * If a prefix in the NLRI field is semantically
4525 * (e.g., an unexpected multicast IP address),
4527 * be logged locally, and the prefix SHOULD be
4532 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4533 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4538 /* Check address. */
4539 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4540 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4545 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4547 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4552 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4557 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4559 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4566 /* Normal process. */
4568 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4569 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4570 NULL
, NULL
, 0, 0, NULL
);
4572 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4573 safi
, ZEBRA_ROUTE_BGP
,
4574 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4577 /* Do not send BGP notification twice when maximum-prefix count
4579 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4580 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4582 /* Address family configuration mismatch. */
4584 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4587 /* Packet length consistency check. */
4591 "%s [Error] Update packet error (prefix length mismatch with total length)",
4593 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4596 return BGP_NLRI_PARSE_OK
;
4599 static struct bgp_static
*bgp_static_new(void)
4601 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4604 static void bgp_static_free(struct bgp_static
*bgp_static
)
4606 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4607 route_map_counter_decrement(bgp_static
->rmap
.map
);
4609 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4610 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4613 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4614 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4616 struct bgp_node
*rn
;
4617 struct bgp_path_info
*pi
;
4618 struct bgp_path_info
*new;
4619 struct bgp_path_info rmap_path
;
4621 struct attr
*attr_new
;
4622 route_map_result_t ret
;
4624 int vnc_implicit_withdraw
= 0;
4631 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4633 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4635 attr
.nexthop
= bgp_static
->igpnexthop
;
4636 attr
.med
= bgp_static
->igpmetric
;
4637 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4639 if (bgp_static
->atomic
)
4640 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4642 /* Store label index, if required. */
4643 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4644 attr
.label_index
= bgp_static
->label_index
;
4645 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4648 /* Apply route-map. */
4649 if (bgp_static
->rmap
.name
) {
4650 struct attr attr_tmp
= attr
;
4652 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4653 rmap_path
.peer
= bgp
->peer_self
;
4654 rmap_path
.attr
= &attr_tmp
;
4656 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4658 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4661 bgp
->peer_self
->rmap_type
= 0;
4663 if (ret
== RMAP_DENYMATCH
) {
4664 /* Free uninterned attribute. */
4665 bgp_attr_flush(&attr_tmp
);
4667 /* Unintern original. */
4668 aspath_unintern(&attr
.aspath
);
4669 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4673 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4674 bgp_attr_add_gshut_community(&attr_tmp
);
4676 attr_new
= bgp_attr_intern(&attr_tmp
);
4679 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4680 bgp_attr_add_gshut_community(&attr
);
4682 attr_new
= bgp_attr_intern(&attr
);
4685 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4686 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4687 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4691 if (attrhash_cmp(pi
->attr
, attr_new
)
4692 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4693 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4694 bgp_unlock_node(rn
);
4695 bgp_attr_unintern(&attr_new
);
4696 aspath_unintern(&attr
.aspath
);
4699 /* The attribute is changed. */
4700 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4702 /* Rewrite BGP route information. */
4703 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4704 bgp_path_info_restore(rn
, pi
);
4706 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4708 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4709 && (safi
== SAFI_UNICAST
)) {
4710 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4712 * Implicit withdraw case.
4713 * We have to do this before pi is
4716 ++vnc_implicit_withdraw
;
4717 vnc_import_bgp_del_route(bgp
, p
, pi
);
4718 vnc_import_bgp_exterior_del_route(
4723 bgp_attr_unintern(&pi
->attr
);
4724 pi
->attr
= attr_new
;
4725 pi
->uptime
= bgp_clock();
4727 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4728 && (safi
== SAFI_UNICAST
)) {
4729 if (vnc_implicit_withdraw
) {
4730 vnc_import_bgp_add_route(bgp
, p
, pi
);
4731 vnc_import_bgp_exterior_add_route(
4737 /* Nexthop reachability check. */
4738 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4739 && (safi
== SAFI_UNICAST
4740 || safi
== SAFI_LABELED_UNICAST
)) {
4742 struct bgp
*bgp_nexthop
= bgp
;
4744 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4745 bgp_nexthop
= pi
->extra
->bgp_orig
;
4747 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4749 bgp_path_info_set_flag(rn
, pi
,
4752 if (BGP_DEBUG(nht
, NHT
)) {
4753 char buf1
[INET6_ADDRSTRLEN
];
4754 inet_ntop(p
->family
,
4758 "%s(%s): Route not in table, not advertising",
4759 __FUNCTION__
, buf1
);
4761 bgp_path_info_unset_flag(
4762 rn
, pi
, BGP_PATH_VALID
);
4765 /* Delete the NHT structure if any, if we're
4767 * enabling/disabling import check. We
4768 * deregister the route
4769 * from NHT to avoid overloading NHT and the
4770 * process interaction
4772 bgp_unlink_nexthop(pi
);
4773 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4775 /* Process change. */
4776 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4777 bgp_process(bgp
, rn
, afi
, safi
);
4779 if (SAFI_UNICAST
== safi
4780 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4782 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4783 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4787 bgp_unlock_node(rn
);
4788 aspath_unintern(&attr
.aspath
);
4793 /* Make new BGP info. */
4794 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4796 /* Nexthop reachability check. */
4797 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4798 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4799 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4800 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4802 if (BGP_DEBUG(nht
, NHT
)) {
4803 char buf1
[INET6_ADDRSTRLEN
];
4804 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4807 "%s(%s): Route not in table, not advertising",
4808 __FUNCTION__
, buf1
);
4810 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4813 /* Delete the NHT structure if any, if we're toggling between
4814 * enabling/disabling import check. We deregister the route
4815 * from NHT to avoid overloading NHT and the process interaction
4817 bgp_unlink_nexthop(new);
4819 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4822 /* Aggregate address increment. */
4823 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4825 /* Register new BGP information. */
4826 bgp_path_info_add(rn
, new);
4828 /* route_node_get lock */
4829 bgp_unlock_node(rn
);
4831 /* Process change. */
4832 bgp_process(bgp
, rn
, afi
, safi
);
4834 if (SAFI_UNICAST
== safi
4835 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4836 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4837 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4840 /* Unintern original. */
4841 aspath_unintern(&attr
.aspath
);
4844 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4847 struct bgp_node
*rn
;
4848 struct bgp_path_info
*pi
;
4850 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4852 /* Check selected route and self inserted route. */
4853 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4854 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4855 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4858 /* Withdraw static BGP route from routing table. */
4860 if (SAFI_UNICAST
== safi
4861 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4862 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4863 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4865 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4866 bgp_unlink_nexthop(pi
);
4867 bgp_path_info_delete(rn
, pi
);
4868 bgp_process(bgp
, rn
, afi
, safi
);
4871 /* Unlock bgp_node_lookup. */
4872 bgp_unlock_node(rn
);
4876 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4878 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4879 afi_t afi
, safi_t safi
,
4880 struct prefix_rd
*prd
)
4882 struct bgp_node
*rn
;
4883 struct bgp_path_info
*pi
;
4885 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4887 /* Check selected route and self inserted route. */
4888 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4889 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4890 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4893 /* Withdraw static BGP route from routing table. */
4896 rfapiProcessWithdraw(
4897 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4898 1); /* Kill, since it is an administrative change */
4900 if (SAFI_MPLS_VPN
== safi
4901 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4902 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4904 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4905 bgp_path_info_delete(rn
, pi
);
4906 bgp_process(bgp
, rn
, afi
, safi
);
4909 /* Unlock bgp_node_lookup. */
4910 bgp_unlock_node(rn
);
4913 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4914 struct bgp_static
*bgp_static
, afi_t afi
,
4917 struct bgp_node
*rn
;
4918 struct bgp_path_info
*new;
4919 struct attr
*attr_new
;
4920 struct attr attr
= {0};
4921 struct bgp_path_info
*pi
;
4923 mpls_label_t label
= 0;
4925 uint32_t num_labels
= 0;
4930 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4932 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4935 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4937 attr
.nexthop
= bgp_static
->igpnexthop
;
4938 attr
.med
= bgp_static
->igpmetric
;
4939 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4941 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4942 || (safi
== SAFI_ENCAP
)) {
4943 if (afi
== AFI_IP
) {
4944 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4945 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4948 if (afi
== AFI_L2VPN
) {
4949 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4951 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4952 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4953 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4954 sizeof(struct in6_addr
));
4955 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4956 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4957 struct bgp_encap_type_vxlan bet
;
4958 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4959 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4960 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4962 if (bgp_static
->router_mac
) {
4963 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4966 /* Apply route-map. */
4967 if (bgp_static
->rmap
.name
) {
4968 struct attr attr_tmp
= attr
;
4969 struct bgp_path_info rmap_path
;
4970 route_map_result_t ret
;
4972 rmap_path
.peer
= bgp
->peer_self
;
4973 rmap_path
.attr
= &attr_tmp
;
4975 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4977 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4980 bgp
->peer_self
->rmap_type
= 0;
4982 if (ret
== RMAP_DENYMATCH
) {
4983 /* Free uninterned attribute. */
4984 bgp_attr_flush(&attr_tmp
);
4986 /* Unintern original. */
4987 aspath_unintern(&attr
.aspath
);
4988 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4993 attr_new
= bgp_attr_intern(&attr_tmp
);
4995 attr_new
= bgp_attr_intern(&attr
);
4998 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4999 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5000 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5004 memset(&add
, 0, sizeof(union gw_addr
));
5005 if (attrhash_cmp(pi
->attr
, attr_new
)
5006 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
5007 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5008 bgp_unlock_node(rn
);
5009 bgp_attr_unintern(&attr_new
);
5010 aspath_unintern(&attr
.aspath
);
5013 /* The attribute is changed. */
5014 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5016 /* Rewrite BGP route information. */
5017 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5018 bgp_path_info_restore(rn
, pi
);
5020 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5021 bgp_attr_unintern(&pi
->attr
);
5022 pi
->attr
= attr_new
;
5023 pi
->uptime
= bgp_clock();
5026 label
= decode_label(&pi
->extra
->label
[0]);
5029 /* Process change. */
5030 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5031 bgp_process(bgp
, rn
, afi
, safi
);
5033 if (SAFI_MPLS_VPN
== safi
5034 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5035 vpn_leak_to_vrf_update(bgp
, pi
);
5038 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5039 pi
->attr
, afi
, safi
, pi
->type
,
5040 pi
->sub_type
, &label
);
5042 bgp_unlock_node(rn
);
5043 aspath_unintern(&attr
.aspath
);
5049 /* Make new BGP info. */
5050 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5052 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5053 new->extra
= bgp_path_info_extra_new();
5055 new->extra
->label
[0] = bgp_static
->label
;
5056 new->extra
->num_labels
= num_labels
;
5059 label
= decode_label(&bgp_static
->label
);
5062 /* Aggregate address increment. */
5063 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5065 /* Register new BGP information. */
5066 bgp_path_info_add(rn
, new);
5067 /* route_node_get lock */
5068 bgp_unlock_node(rn
);
5070 /* Process change. */
5071 bgp_process(bgp
, rn
, afi
, safi
);
5073 if (SAFI_MPLS_VPN
== safi
5074 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5075 vpn_leak_to_vrf_update(bgp
, new);
5078 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5079 safi
, new->type
, new->sub_type
, &label
);
5082 /* Unintern original. */
5083 aspath_unintern(&attr
.aspath
);
5086 /* Configure static BGP network. When user don't run zebra, static
5087 route should be installed as valid. */
5088 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5089 const char *ip_str
, afi_t afi
, safi_t safi
,
5090 const char *rmap
, int backdoor
, uint32_t label_index
)
5092 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5095 struct bgp_static
*bgp_static
;
5096 struct bgp_node
*rn
;
5097 uint8_t need_update
= 0;
5099 /* Convert IP prefix string to struct prefix. */
5100 ret
= str2prefix(ip_str
, &p
);
5102 vty_out(vty
, "%% Malformed prefix\n");
5103 return CMD_WARNING_CONFIG_FAILED
;
5105 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5106 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5107 return CMD_WARNING_CONFIG_FAILED
;
5114 /* Set BGP static route configuration. */
5115 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5118 vty_out(vty
, "%% Can't find static route specified\n");
5119 return CMD_WARNING_CONFIG_FAILED
;
5122 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5124 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5125 && (label_index
!= bgp_static
->label_index
)) {
5127 "%% label-index doesn't match static route\n");
5128 return CMD_WARNING_CONFIG_FAILED
;
5131 if ((rmap
&& bgp_static
->rmap
.name
)
5132 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5134 "%% route-map name doesn't match static route\n");
5135 return CMD_WARNING_CONFIG_FAILED
;
5138 /* Update BGP RIB. */
5139 if (!bgp_static
->backdoor
)
5140 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5142 /* Clear configuration. */
5143 bgp_static_free(bgp_static
);
5144 bgp_node_set_bgp_static_info(rn
, NULL
);
5145 bgp_unlock_node(rn
);
5146 bgp_unlock_node(rn
);
5149 /* Set BGP static route configuration. */
5150 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5152 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5154 /* Configuration change. */
5155 /* Label index cannot be changed. */
5156 if (bgp_static
->label_index
!= label_index
) {
5157 vty_out(vty
, "%% cannot change label-index\n");
5158 return CMD_WARNING_CONFIG_FAILED
;
5161 /* Check previous routes are installed into BGP. */
5162 if (bgp_static
->valid
5163 && bgp_static
->backdoor
!= backdoor
)
5166 bgp_static
->backdoor
= backdoor
;
5169 XFREE(MTYPE_ROUTE_MAP_NAME
,
5170 bgp_static
->rmap
.name
);
5171 route_map_counter_decrement(
5172 bgp_static
->rmap
.map
);
5173 bgp_static
->rmap
.name
=
5174 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5175 bgp_static
->rmap
.map
=
5176 route_map_lookup_by_name(rmap
);
5177 route_map_counter_increment(
5178 bgp_static
->rmap
.map
);
5180 XFREE(MTYPE_ROUTE_MAP_NAME
,
5181 bgp_static
->rmap
.name
);
5182 route_map_counter_decrement(
5183 bgp_static
->rmap
.map
);
5184 bgp_static
->rmap
.name
= NULL
;
5185 bgp_static
->rmap
.map
= NULL
;
5186 bgp_static
->valid
= 0;
5188 bgp_unlock_node(rn
);
5190 /* New configuration. */
5191 bgp_static
= bgp_static_new();
5192 bgp_static
->backdoor
= backdoor
;
5193 bgp_static
->valid
= 0;
5194 bgp_static
->igpmetric
= 0;
5195 bgp_static
->igpnexthop
.s_addr
= 0;
5196 bgp_static
->label_index
= label_index
;
5199 XFREE(MTYPE_ROUTE_MAP_NAME
,
5200 bgp_static
->rmap
.name
);
5201 route_map_counter_decrement(
5202 bgp_static
->rmap
.map
);
5203 bgp_static
->rmap
.name
=
5204 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5205 bgp_static
->rmap
.map
=
5206 route_map_lookup_by_name(rmap
);
5207 route_map_counter_increment(
5208 bgp_static
->rmap
.map
);
5210 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5213 bgp_static
->valid
= 1;
5215 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5217 if (!bgp_static
->backdoor
)
5218 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5224 void bgp_static_add(struct bgp
*bgp
)
5228 struct bgp_node
*rn
;
5229 struct bgp_node
*rm
;
5230 struct bgp_table
*table
;
5231 struct bgp_static
*bgp_static
;
5233 FOREACH_AFI_SAFI (afi
, safi
)
5234 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5235 rn
= bgp_route_next(rn
)) {
5236 if (!bgp_node_has_bgp_path_info_data(rn
))
5239 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5240 || (safi
== SAFI_EVPN
)) {
5241 table
= bgp_node_get_bgp_table_info(rn
);
5243 for (rm
= bgp_table_top(table
); rm
;
5244 rm
= bgp_route_next(rm
)) {
5246 bgp_node_get_bgp_static_info(
5248 bgp_static_update_safi(bgp
, &rm
->p
,
5255 bgp_node_get_bgp_static_info(rn
), afi
,
5261 /* Called from bgp_delete(). Delete all static routes from the BGP
5263 void bgp_static_delete(struct bgp
*bgp
)
5267 struct bgp_node
*rn
;
5268 struct bgp_node
*rm
;
5269 struct bgp_table
*table
;
5270 struct bgp_static
*bgp_static
;
5272 FOREACH_AFI_SAFI (afi
, safi
)
5273 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5274 rn
= bgp_route_next(rn
)) {
5275 if (!bgp_node_has_bgp_path_info_data(rn
))
5278 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5279 || (safi
== SAFI_EVPN
)) {
5280 table
= bgp_node_get_bgp_table_info(rn
);
5282 for (rm
= bgp_table_top(table
); rm
;
5283 rm
= bgp_route_next(rm
)) {
5285 bgp_node_get_bgp_static_info(
5290 bgp_static_withdraw_safi(
5291 bgp
, &rm
->p
, AFI_IP
, safi
,
5292 (struct prefix_rd
*)&rn
->p
);
5293 bgp_static_free(bgp_static
);
5294 bgp_node_set_bgp_static_info(rn
, NULL
);
5295 bgp_unlock_node(rn
);
5298 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5299 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5300 bgp_static_free(bgp_static
);
5301 bgp_node_set_bgp_static_info(rn
, NULL
);
5302 bgp_unlock_node(rn
);
5307 void bgp_static_redo_import_check(struct bgp
*bgp
)
5311 struct bgp_node
*rn
;
5312 struct bgp_node
*rm
;
5313 struct bgp_table
*table
;
5314 struct bgp_static
*bgp_static
;
5316 /* Use this flag to force reprocessing of the route */
5317 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5318 FOREACH_AFI_SAFI (afi
, safi
) {
5319 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5320 rn
= bgp_route_next(rn
)) {
5321 if (!bgp_node_has_bgp_path_info_data(rn
))
5324 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5325 || (safi
== SAFI_EVPN
)) {
5326 table
= bgp_node_get_bgp_table_info(rn
);
5328 for (rm
= bgp_table_top(table
); rm
;
5329 rm
= bgp_route_next(rm
)) {
5331 bgp_node_get_bgp_static_info(
5333 bgp_static_update_safi(bgp
, &rm
->p
,
5338 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5339 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5344 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5347 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5350 struct bgp_table
*table
;
5351 struct bgp_node
*rn
;
5352 struct bgp_path_info
*pi
;
5354 /* Do not install the aggregate route if BGP is in the
5355 * process of termination.
5357 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5358 (bgp
->peer_self
== NULL
))
5361 table
= bgp
->rib
[afi
][safi
];
5362 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5363 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5364 if (pi
->peer
== bgp
->peer_self
5365 && ((pi
->type
== ZEBRA_ROUTE_BGP
5366 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5367 || (pi
->type
!= ZEBRA_ROUTE_BGP
5369 == BGP_ROUTE_REDISTRIBUTE
))) {
5370 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5372 bgp_unlink_nexthop(pi
);
5373 bgp_path_info_delete(rn
, pi
);
5374 bgp_process(bgp
, rn
, afi
, safi
);
5381 * Purge all networks and redistributed routes from routing table.
5382 * Invoked upon the instance going down.
5384 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5389 FOREACH_AFI_SAFI (afi
, safi
)
5390 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5395 * Currently this is used to set static routes for VPN and ENCAP.
5396 * I think it can probably be factored with bgp_static_set.
5398 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5399 const char *ip_str
, const char *rd_str
,
5400 const char *label_str
, const char *rmap_str
,
5401 int evpn_type
, const char *esi
, const char *gwip
,
5402 const char *ethtag
, const char *routermac
)
5404 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5407 struct prefix_rd prd
;
5408 struct bgp_node
*prn
;
5409 struct bgp_node
*rn
;
5410 struct bgp_table
*table
;
5411 struct bgp_static
*bgp_static
;
5412 mpls_label_t label
= MPLS_INVALID_LABEL
;
5413 struct prefix gw_ip
;
5415 /* validate ip prefix */
5416 ret
= str2prefix(ip_str
, &p
);
5418 vty_out(vty
, "%% Malformed prefix\n");
5419 return CMD_WARNING_CONFIG_FAILED
;
5422 if ((afi
== AFI_L2VPN
)
5423 && (bgp_build_evpn_prefix(evpn_type
,
5424 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5425 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5426 return CMD_WARNING_CONFIG_FAILED
;
5429 ret
= str2prefix_rd(rd_str
, &prd
);
5431 vty_out(vty
, "%% Malformed rd\n");
5432 return CMD_WARNING_CONFIG_FAILED
;
5436 unsigned long label_val
;
5437 label_val
= strtoul(label_str
, NULL
, 10);
5438 encode_label(label_val
, &label
);
5441 if (safi
== SAFI_EVPN
) {
5442 if (esi
&& str2esi(esi
, NULL
) == 0) {
5443 vty_out(vty
, "%% Malformed ESI\n");
5444 return CMD_WARNING_CONFIG_FAILED
;
5446 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5447 vty_out(vty
, "%% Malformed Router MAC\n");
5448 return CMD_WARNING_CONFIG_FAILED
;
5451 memset(&gw_ip
, 0, sizeof(struct prefix
));
5452 ret
= str2prefix(gwip
, &gw_ip
);
5454 vty_out(vty
, "%% Malformed GatewayIp\n");
5455 return CMD_WARNING_CONFIG_FAILED
;
5457 if ((gw_ip
.family
== AF_INET
5458 && is_evpn_prefix_ipaddr_v6(
5459 (struct prefix_evpn
*)&p
))
5460 || (gw_ip
.family
== AF_INET6
5461 && is_evpn_prefix_ipaddr_v4(
5462 (struct prefix_evpn
*)&p
))) {
5464 "%% GatewayIp family differs with IP prefix\n");
5465 return CMD_WARNING_CONFIG_FAILED
;
5469 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5470 if (!bgp_node_has_bgp_path_info_data(prn
))
5471 bgp_node_set_bgp_table_info(prn
,
5472 bgp_table_init(bgp
, afi
, safi
));
5473 table
= bgp_node_get_bgp_table_info(prn
);
5475 rn
= bgp_node_get(table
, &p
);
5477 if (bgp_node_has_bgp_path_info_data(rn
)) {
5478 vty_out(vty
, "%% Same network configuration exists\n");
5479 bgp_unlock_node(rn
);
5481 /* New configuration. */
5482 bgp_static
= bgp_static_new();
5483 bgp_static
->backdoor
= 0;
5484 bgp_static
->valid
= 0;
5485 bgp_static
->igpmetric
= 0;
5486 bgp_static
->igpnexthop
.s_addr
= 0;
5487 bgp_static
->label
= label
;
5488 bgp_static
->prd
= prd
;
5491 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5492 route_map_counter_decrement(bgp_static
->rmap
.map
);
5493 bgp_static
->rmap
.name
=
5494 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5495 bgp_static
->rmap
.map
=
5496 route_map_lookup_by_name(rmap_str
);
5497 route_map_counter_increment(bgp_static
->rmap
.map
);
5500 if (safi
== SAFI_EVPN
) {
5502 bgp_static
->eth_s_id
=
5504 sizeof(struct eth_segment_id
));
5505 str2esi(esi
, bgp_static
->eth_s_id
);
5508 bgp_static
->router_mac
=
5509 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5510 (void)prefix_str2mac(routermac
,
5511 bgp_static
->router_mac
);
5514 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5516 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5518 bgp_static
->valid
= 1;
5519 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5525 /* Configure static BGP network. */
5526 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5527 const char *ip_str
, const char *rd_str
,
5528 const char *label_str
, int evpn_type
, const char *esi
,
5529 const char *gwip
, const char *ethtag
)
5531 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5534 struct prefix_rd prd
;
5535 struct bgp_node
*prn
;
5536 struct bgp_node
*rn
;
5537 struct bgp_table
*table
;
5538 struct bgp_static
*bgp_static
;
5539 mpls_label_t label
= MPLS_INVALID_LABEL
;
5541 /* Convert IP prefix string to struct prefix. */
5542 ret
= str2prefix(ip_str
, &p
);
5544 vty_out(vty
, "%% Malformed prefix\n");
5545 return CMD_WARNING_CONFIG_FAILED
;
5548 if ((afi
== AFI_L2VPN
)
5549 && (bgp_build_evpn_prefix(evpn_type
,
5550 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5551 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5552 return CMD_WARNING_CONFIG_FAILED
;
5554 ret
= str2prefix_rd(rd_str
, &prd
);
5556 vty_out(vty
, "%% Malformed rd\n");
5557 return CMD_WARNING_CONFIG_FAILED
;
5561 unsigned long label_val
;
5562 label_val
= strtoul(label_str
, NULL
, 10);
5563 encode_label(label_val
, &label
);
5566 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5567 if (!bgp_node_has_bgp_path_info_data(prn
))
5568 bgp_node_set_bgp_table_info(prn
,
5569 bgp_table_init(bgp
, afi
, safi
));
5571 bgp_unlock_node(prn
);
5572 table
= bgp_node_get_bgp_table_info(prn
);
5574 rn
= bgp_node_lookup(table
, &p
);
5577 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5579 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5580 bgp_static_free(bgp_static
);
5581 bgp_node_set_bgp_static_info(rn
, NULL
);
5582 bgp_unlock_node(rn
);
5583 bgp_unlock_node(rn
);
5585 vty_out(vty
, "%% Can't find the route\n");
5590 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5591 const char *rmap_name
)
5593 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5594 struct bgp_rmap
*rmap
;
5596 rmap
= &bgp
->table_map
[afi
][safi
];
5598 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5599 route_map_counter_decrement(rmap
->map
);
5600 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5601 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5602 route_map_counter_increment(rmap
->map
);
5604 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5605 route_map_counter_decrement(rmap
->map
);
5610 if (bgp_fibupd_safi(safi
))
5611 bgp_zebra_announce_table(bgp
, afi
, safi
);
5616 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5617 const char *rmap_name
)
5619 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5620 struct bgp_rmap
*rmap
;
5622 rmap
= &bgp
->table_map
[afi
][safi
];
5623 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5624 route_map_counter_decrement(rmap
->map
);
5628 if (bgp_fibupd_safi(safi
))
5629 bgp_zebra_announce_table(bgp
, afi
, safi
);
5634 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5637 if (bgp
->table_map
[afi
][safi
].name
) {
5638 vty_out(vty
, " table-map %s\n",
5639 bgp
->table_map
[afi
][safi
].name
);
5643 DEFUN (bgp_table_map
,
5646 "BGP table to RIB route download filter\n"
5647 "Name of the route map\n")
5650 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5651 argv
[idx_word
]->arg
);
5653 DEFUN (no_bgp_table_map
,
5654 no_bgp_table_map_cmd
,
5655 "no table-map WORD",
5657 "BGP table to RIB route download filter\n"
5658 "Name of the route map\n")
5661 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5662 argv
[idx_word
]->arg
);
5668 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5669 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5670 backdoor$backdoor}]",
5672 "Specify a network to announce via BGP\n"
5677 "Route-map to modify the attributes\n"
5678 "Name of the route map\n"
5679 "Label index to associate with the prefix\n"
5680 "Label index value\n"
5681 "Specify a BGP backdoor route\n")
5683 char addr_prefix_str
[BUFSIZ
];
5688 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5691 vty_out(vty
, "%% Inconsistent address and mask\n");
5692 return CMD_WARNING_CONFIG_FAILED
;
5696 return bgp_static_set(
5697 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5698 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5699 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5702 DEFPY(ipv6_bgp_network
,
5703 ipv6_bgp_network_cmd
,
5704 "[no] network X:X::X:X/M$prefix \
5705 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5707 "Specify a network to announce via BGP\n"
5709 "Route-map to modify the attributes\n"
5710 "Name of the route map\n"
5711 "Label index to associate with the prefix\n"
5712 "Label index value\n")
5714 return bgp_static_set(
5715 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5716 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5719 static struct bgp_aggregate
*bgp_aggregate_new(void)
5721 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5724 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5726 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
5727 route_map_counter_decrement(aggregate
->rmap
.map
);
5728 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5731 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5732 struct aspath
*aspath
,
5733 struct community
*comm
,
5734 struct ecommunity
*ecomm
,
5735 struct lcommunity
*lcomm
)
5737 static struct aspath
*ae
= NULL
;
5740 ae
= aspath_empty();
5745 if (origin
!= pi
->attr
->origin
)
5748 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5751 if (!community_cmp(pi
->attr
->community
, comm
))
5754 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5757 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5760 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5766 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5767 struct prefix
*p
, uint8_t origin
,
5768 struct aspath
*aspath
,
5769 struct community
*community
,
5770 struct ecommunity
*ecommunity
,
5771 struct lcommunity
*lcommunity
,
5772 uint8_t atomic_aggregate
,
5773 struct bgp_aggregate
*aggregate
)
5775 struct bgp_node
*rn
;
5776 struct bgp_table
*table
;
5777 struct bgp_path_info
*pi
, *orig
, *new;
5780 table
= bgp
->rib
[afi
][safi
];
5782 rn
= bgp_node_get(table
, p
);
5784 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5785 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5786 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5789 if (aggregate
->count
> 0) {
5791 * If the aggregate information has not changed
5792 * no need to re-install it again.
5794 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5795 ecommunity
, lcommunity
)) {
5796 bgp_unlock_node(rn
);
5799 aspath_free(aspath
);
5801 community_free(&community
);
5803 ecommunity_free(&ecommunity
);
5805 lcommunity_free(&lcommunity
);
5811 * Mark the old as unusable
5814 bgp_path_info_delete(rn
, pi
);
5816 attr
= bgp_attr_aggregate_intern(
5817 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
5818 aggregate
, atomic_aggregate
, p
);
5821 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
5825 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5826 bgp
->peer_self
, attr
, rn
);
5828 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5830 bgp_path_info_add(rn
, new);
5831 bgp_process(bgp
, rn
, afi
, safi
);
5833 for (pi
= orig
; pi
; pi
= pi
->next
)
5834 if (pi
->peer
== bgp
->peer_self
5835 && pi
->type
== ZEBRA_ROUTE_BGP
5836 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5839 /* Withdraw static BGP route from routing table. */
5841 bgp_path_info_delete(rn
, pi
);
5842 bgp_process(bgp
, rn
, afi
, safi
);
5846 bgp_unlock_node(rn
);
5849 /* Update an aggregate as routes are added/removed from the BGP table */
5850 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5851 afi_t afi
, safi_t safi
,
5852 struct bgp_aggregate
*aggregate
)
5854 struct bgp_table
*table
;
5855 struct bgp_node
*top
;
5856 struct bgp_node
*rn
;
5858 struct aspath
*aspath
= NULL
;
5859 struct community
*community
= NULL
;
5860 struct ecommunity
*ecommunity
= NULL
;
5861 struct lcommunity
*lcommunity
= NULL
;
5862 struct bgp_path_info
*pi
;
5863 unsigned long match
= 0;
5864 uint8_t atomic_aggregate
= 0;
5866 /* If the bgp instance is being deleted or self peer is deleted
5867 * then do not create aggregate route
5869 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5870 (bgp
->peer_self
== NULL
))
5873 /* ORIGIN attribute: If at least one route among routes that are
5874 aggregated has ORIGIN with the value INCOMPLETE, then the
5875 aggregated route must have the ORIGIN attribute with the value
5876 INCOMPLETE. Otherwise, if at least one route among routes that
5877 are aggregated has ORIGIN with the value EGP, then the aggregated
5878 route must have the origin attribute with the value EGP. In all
5879 other case the value of the ORIGIN attribute of the aggregated
5880 route is INTERNAL. */
5881 origin
= BGP_ORIGIN_IGP
;
5883 table
= bgp
->rib
[afi
][safi
];
5885 top
= bgp_node_get(table
, p
);
5886 for (rn
= bgp_node_get(table
, p
); rn
;
5887 rn
= bgp_route_next_until(rn
, top
)) {
5888 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5893 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5894 if (BGP_PATH_HOLDDOWN(pi
))
5898 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5899 atomic_aggregate
= 1;
5901 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5905 * summary-only aggregate route suppress
5906 * aggregated route announcements.
5908 if (aggregate
->summary_only
) {
5909 (bgp_path_info_extra_get(pi
))->suppress
++;
5910 bgp_path_info_set_flag(rn
, pi
,
5911 BGP_PATH_ATTR_CHANGED
);
5918 * If at least one route among routes that are
5919 * aggregated has ORIGIN with the value INCOMPLETE,
5920 * then the aggregated route MUST have the ORIGIN
5921 * attribute with the value INCOMPLETE. Otherwise, if
5922 * at least one route among routes that are aggregated
5923 * has ORIGIN with the value EGP, then the aggregated
5924 * route MUST have the ORIGIN attribute with the value
5927 switch (pi
->attr
->origin
) {
5928 case BGP_ORIGIN_INCOMPLETE
:
5929 aggregate
->incomplete_origin_count
++;
5931 case BGP_ORIGIN_EGP
:
5932 aggregate
->egp_origin_count
++;
5940 if (!aggregate
->as_set
)
5944 * as-set aggregate route generate origin, as path,
5945 * and community aggregation.
5947 /* Compute aggregate route's as-path.
5949 bgp_compute_aggregate_aspath_hash(aggregate
,
5952 /* Compute aggregate route's community.
5954 if (pi
->attr
->community
)
5955 bgp_compute_aggregate_community_hash(
5957 pi
->attr
->community
);
5959 /* Compute aggregate route's extended community.
5961 if (pi
->attr
->ecommunity
)
5962 bgp_compute_aggregate_ecommunity_hash(
5964 pi
->attr
->ecommunity
);
5966 /* Compute aggregate route's large community.
5968 if (pi
->attr
->lcommunity
)
5969 bgp_compute_aggregate_lcommunity_hash(
5971 pi
->attr
->lcommunity
);
5974 bgp_process(bgp
, rn
, afi
, safi
);
5976 if (aggregate
->as_set
) {
5977 bgp_compute_aggregate_aspath_val(aggregate
);
5978 bgp_compute_aggregate_community_val(aggregate
);
5979 bgp_compute_aggregate_ecommunity_val(aggregate
);
5980 bgp_compute_aggregate_lcommunity_val(aggregate
);
5984 bgp_unlock_node(top
);
5987 if (aggregate
->incomplete_origin_count
> 0)
5988 origin
= BGP_ORIGIN_INCOMPLETE
;
5989 else if (aggregate
->egp_origin_count
> 0)
5990 origin
= BGP_ORIGIN_EGP
;
5992 if (aggregate
->as_set
) {
5993 if (aggregate
->aspath
)
5994 /* Retrieve aggregate route's as-path.
5996 aspath
= aspath_dup(aggregate
->aspath
);
5998 if (aggregate
->community
)
5999 /* Retrieve aggregate route's community.
6001 community
= community_dup(aggregate
->community
);
6003 if (aggregate
->ecommunity
)
6004 /* Retrieve aggregate route's ecommunity.
6006 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6008 if (aggregate
->lcommunity
)
6009 /* Retrieve aggregate route's lcommunity.
6011 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6014 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6015 ecommunity
, lcommunity
, atomic_aggregate
,
6019 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6020 safi_t safi
, struct bgp_aggregate
*aggregate
)
6022 struct bgp_table
*table
;
6023 struct bgp_node
*top
;
6024 struct bgp_node
*rn
;
6025 struct bgp_path_info
*pi
;
6026 unsigned long match
;
6028 table
= bgp
->rib
[afi
][safi
];
6030 /* If routes exists below this node, generate aggregate routes. */
6031 top
= bgp_node_get(table
, p
);
6032 for (rn
= bgp_node_get(table
, p
); rn
;
6033 rn
= bgp_route_next_until(rn
, top
)) {
6034 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6038 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6039 if (BGP_PATH_HOLDDOWN(pi
))
6042 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6045 if (aggregate
->summary_only
&& pi
->extra
) {
6046 pi
->extra
->suppress
--;
6048 if (pi
->extra
->suppress
== 0) {
6049 bgp_path_info_set_flag(
6050 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6056 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6057 aggregate
->incomplete_origin_count
--;
6058 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6059 aggregate
->egp_origin_count
--;
6061 if (aggregate
->as_set
) {
6062 /* Remove as-path from aggregate.
6064 bgp_remove_aspath_from_aggregate_hash(
6068 if (pi
->attr
->community
)
6069 /* Remove community from aggregate.
6071 bgp_remove_comm_from_aggregate_hash(
6073 pi
->attr
->community
);
6075 if (pi
->attr
->ecommunity
)
6076 /* Remove ecommunity from aggregate.
6078 bgp_remove_ecomm_from_aggregate_hash(
6080 pi
->attr
->ecommunity
);
6082 if (pi
->attr
->lcommunity
)
6083 /* Remove lcommunity from aggregate.
6085 bgp_remove_lcomm_from_aggregate_hash(
6087 pi
->attr
->lcommunity
);
6092 /* If this node was suppressed, process the change. */
6094 bgp_process(bgp
, rn
, afi
, safi
);
6096 if (aggregate
->as_set
) {
6097 aspath_free(aggregate
->aspath
);
6098 aggregate
->aspath
= NULL
;
6099 if (aggregate
->community
)
6100 community_free(&aggregate
->community
);
6101 if (aggregate
->ecommunity
)
6102 ecommunity_free(&aggregate
->ecommunity
);
6103 if (aggregate
->lcommunity
)
6104 lcommunity_free(&aggregate
->lcommunity
);
6107 bgp_unlock_node(top
);
6110 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6111 struct bgp_path_info
*pinew
, afi_t afi
,
6113 struct bgp_aggregate
*aggregate
)
6116 struct aspath
*aspath
= NULL
;
6117 uint8_t atomic_aggregate
= 0;
6118 struct community
*community
= NULL
;
6119 struct ecommunity
*ecommunity
= NULL
;
6120 struct lcommunity
*lcommunity
= NULL
;
6122 /* ORIGIN attribute: If at least one route among routes that are
6123 * aggregated has ORIGIN with the value INCOMPLETE, then the
6124 * aggregated route must have the ORIGIN attribute with the value
6125 * INCOMPLETE. Otherwise, if at least one route among routes that
6126 * are aggregated has ORIGIN with the value EGP, then the aggregated
6127 * route must have the origin attribute with the value EGP. In all
6128 * other case the value of the ORIGIN attribute of the aggregated
6129 * route is INTERNAL.
6131 origin
= BGP_ORIGIN_IGP
;
6135 if (aggregate
->summary_only
)
6136 (bgp_path_info_extra_get(pinew
))->suppress
++;
6138 switch (pinew
->attr
->origin
) {
6139 case BGP_ORIGIN_INCOMPLETE
:
6140 aggregate
->incomplete_origin_count
++;
6142 case BGP_ORIGIN_EGP
:
6143 aggregate
->egp_origin_count
++;
6151 if (aggregate
->incomplete_origin_count
> 0)
6152 origin
= BGP_ORIGIN_INCOMPLETE
;
6153 else if (aggregate
->egp_origin_count
> 0)
6154 origin
= BGP_ORIGIN_EGP
;
6156 if (aggregate
->as_set
) {
6157 /* Compute aggregate route's as-path.
6159 bgp_compute_aggregate_aspath(aggregate
,
6160 pinew
->attr
->aspath
);
6162 /* Compute aggregate route's community.
6164 if (pinew
->attr
->community
)
6165 bgp_compute_aggregate_community(
6167 pinew
->attr
->community
);
6169 /* Compute aggregate route's extended community.
6171 if (pinew
->attr
->ecommunity
)
6172 bgp_compute_aggregate_ecommunity(
6174 pinew
->attr
->ecommunity
);
6176 /* Compute aggregate route's large community.
6178 if (pinew
->attr
->lcommunity
)
6179 bgp_compute_aggregate_lcommunity(
6181 pinew
->attr
->lcommunity
);
6183 /* Retrieve aggregate route's as-path.
6185 if (aggregate
->aspath
)
6186 aspath
= aspath_dup(aggregate
->aspath
);
6188 /* Retrieve aggregate route's community.
6190 if (aggregate
->community
)
6191 community
= community_dup(aggregate
->community
);
6193 /* Retrieve aggregate route's ecommunity.
6195 if (aggregate
->ecommunity
)
6196 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6198 /* Retrieve aggregate route's lcommunity.
6200 if (aggregate
->lcommunity
)
6201 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6204 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6205 aspath
, community
, ecommunity
,
6206 lcommunity
, atomic_aggregate
, aggregate
);
6209 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6211 struct bgp_path_info
*pi
,
6212 struct bgp_aggregate
*aggregate
,
6213 struct prefix
*aggr_p
)
6216 struct aspath
*aspath
= NULL
;
6217 uint8_t atomic_aggregate
= 0;
6218 struct community
*community
= NULL
;
6219 struct ecommunity
*ecommunity
= NULL
;
6220 struct lcommunity
*lcommunity
= NULL
;
6221 unsigned long match
= 0;
6223 if (BGP_PATH_HOLDDOWN(pi
))
6226 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6229 if (aggregate
->summary_only
6231 && pi
->extra
->suppress
> 0) {
6232 pi
->extra
->suppress
--;
6234 if (pi
->extra
->suppress
== 0) {
6235 bgp_path_info_set_flag(pi
->net
, pi
,
6236 BGP_PATH_ATTR_CHANGED
);
6241 if (aggregate
->count
> 0)
6244 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6245 aggregate
->incomplete_origin_count
--;
6246 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6247 aggregate
->egp_origin_count
--;
6249 if (aggregate
->as_set
) {
6250 /* Remove as-path from aggregate.
6252 bgp_remove_aspath_from_aggregate(aggregate
,
6255 if (pi
->attr
->community
)
6256 /* Remove community from aggregate.
6258 bgp_remove_community_from_aggregate(
6260 pi
->attr
->community
);
6262 if (pi
->attr
->ecommunity
)
6263 /* Remove ecommunity from aggregate.
6265 bgp_remove_ecommunity_from_aggregate(
6267 pi
->attr
->ecommunity
);
6269 if (pi
->attr
->lcommunity
)
6270 /* Remove lcommunity from aggregate.
6272 bgp_remove_lcommunity_from_aggregate(
6274 pi
->attr
->lcommunity
);
6277 /* If this node was suppressed, process the change. */
6279 bgp_process(bgp
, pi
->net
, afi
, safi
);
6281 origin
= BGP_ORIGIN_IGP
;
6282 if (aggregate
->incomplete_origin_count
> 0)
6283 origin
= BGP_ORIGIN_INCOMPLETE
;
6284 else if (aggregate
->egp_origin_count
> 0)
6285 origin
= BGP_ORIGIN_EGP
;
6287 if (aggregate
->as_set
) {
6288 /* Retrieve aggregate route's as-path.
6290 if (aggregate
->aspath
)
6291 aspath
= aspath_dup(aggregate
->aspath
);
6293 /* Retrieve aggregate route's community.
6295 if (aggregate
->community
)
6296 community
= community_dup(aggregate
->community
);
6298 /* Retrieve aggregate route's ecommunity.
6300 if (aggregate
->ecommunity
)
6301 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6303 /* Retrieve aggregate route's lcommunity.
6305 if (aggregate
->lcommunity
)
6306 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6309 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6310 aspath
, community
, ecommunity
,
6311 lcommunity
, atomic_aggregate
, aggregate
);
6314 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6315 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6317 struct bgp_node
*child
;
6318 struct bgp_node
*rn
;
6319 struct bgp_aggregate
*aggregate
;
6320 struct bgp_table
*table
;
6322 table
= bgp
->aggregate
[afi
][safi
];
6324 /* No aggregates configured. */
6325 if (bgp_table_top_nolock(table
) == NULL
)
6328 if (p
->prefixlen
== 0)
6331 if (BGP_PATH_HOLDDOWN(pi
))
6334 child
= bgp_node_get(table
, p
);
6336 /* Aggregate address configuration check. */
6337 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6338 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6339 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6340 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6344 bgp_unlock_node(child
);
6347 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6348 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6350 struct bgp_node
*child
;
6351 struct bgp_node
*rn
;
6352 struct bgp_aggregate
*aggregate
;
6353 struct bgp_table
*table
;
6355 table
= bgp
->aggregate
[afi
][safi
];
6357 /* No aggregates configured. */
6358 if (bgp_table_top_nolock(table
) == NULL
)
6361 if (p
->prefixlen
== 0)
6364 child
= bgp_node_get(table
, p
);
6366 /* Aggregate address configuration check. */
6367 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6368 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6369 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6370 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6371 del
, aggregate
, &rn
->p
);
6374 bgp_unlock_node(child
);
6377 /* Aggregate route attribute. */
6378 #define AGGREGATE_SUMMARY_ONLY 1
6379 #define AGGREGATE_AS_SET 1
6381 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6382 afi_t afi
, safi_t safi
)
6384 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6387 struct bgp_node
*rn
;
6388 struct bgp_aggregate
*aggregate
;
6390 /* Convert string to prefix structure. */
6391 ret
= str2prefix(prefix_str
, &p
);
6393 vty_out(vty
, "Malformed prefix\n");
6394 return CMD_WARNING_CONFIG_FAILED
;
6398 /* Old configuration check. */
6399 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6402 "%% There is no aggregate-address configuration.\n");
6403 return CMD_WARNING_CONFIG_FAILED
;
6406 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6407 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6408 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6409 NULL
, NULL
, 0, aggregate
);
6411 /* Unlock aggregate address configuration. */
6412 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6414 if (aggregate
->community
)
6415 community_free(&aggregate
->community
);
6417 if (aggregate
->community_hash
) {
6418 /* Delete all communities in the hash.
6420 hash_clean(aggregate
->community_hash
,
6421 bgp_aggr_community_remove
);
6422 /* Free up the community_hash.
6424 hash_free(aggregate
->community_hash
);
6427 if (aggregate
->ecommunity
)
6428 ecommunity_free(&aggregate
->ecommunity
);
6430 if (aggregate
->ecommunity_hash
) {
6431 /* Delete all ecommunities in the hash.
6433 hash_clean(aggregate
->ecommunity_hash
,
6434 bgp_aggr_ecommunity_remove
);
6435 /* Free up the ecommunity_hash.
6437 hash_free(aggregate
->ecommunity_hash
);
6440 if (aggregate
->lcommunity
)
6441 lcommunity_free(&aggregate
->lcommunity
);
6443 if (aggregate
->lcommunity_hash
) {
6444 /* Delete all lcommunities in the hash.
6446 hash_clean(aggregate
->lcommunity_hash
,
6447 bgp_aggr_lcommunity_remove
);
6448 /* Free up the lcommunity_hash.
6450 hash_free(aggregate
->lcommunity_hash
);
6453 if (aggregate
->aspath
)
6454 aspath_free(aggregate
->aspath
);
6456 if (aggregate
->aspath_hash
) {
6457 /* Delete all as-paths in the hash.
6459 hash_clean(aggregate
->aspath_hash
,
6460 bgp_aggr_aspath_remove
);
6461 /* Free up the aspath_hash.
6463 hash_free(aggregate
->aspath_hash
);
6466 bgp_aggregate_free(aggregate
);
6467 bgp_unlock_node(rn
);
6468 bgp_unlock_node(rn
);
6473 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6474 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6477 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6480 struct bgp_node
*rn
;
6481 struct bgp_aggregate
*aggregate
;
6483 /* Convert string to prefix structure. */
6484 ret
= str2prefix(prefix_str
, &p
);
6486 vty_out(vty
, "Malformed prefix\n");
6487 return CMD_WARNING_CONFIG_FAILED
;
6491 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6492 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6493 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6495 return CMD_WARNING_CONFIG_FAILED
;
6498 /* Old configuration check. */
6499 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6500 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6503 vty_out(vty
, "There is already same aggregate network.\n");
6504 /* try to remove the old entry */
6505 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6507 vty_out(vty
, "Error deleting aggregate.\n");
6508 bgp_unlock_node(rn
);
6509 return CMD_WARNING_CONFIG_FAILED
;
6513 /* Make aggregate address structure. */
6514 aggregate
= bgp_aggregate_new();
6515 aggregate
->summary_only
= summary_only
;
6516 aggregate
->as_set
= as_set
;
6517 aggregate
->safi
= safi
;
6520 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6521 route_map_counter_decrement(aggregate
->rmap
.map
);
6522 aggregate
->rmap
.name
=
6523 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6524 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6525 route_map_counter_increment(aggregate
->rmap
.map
);
6527 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6529 /* Aggregate address insert into BGP routing table. */
6530 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6535 DEFUN (aggregate_address
,
6536 aggregate_address_cmd
,
6537 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6538 "Configure BGP aggregate entries\n"
6539 "Aggregate prefix\n"
6540 "Generate AS set path information\n"
6541 "Filter more specific routes from updates\n"
6542 "Filter more specific routes from updates\n"
6543 "Generate AS set path information\n"
6544 "Apply route map to aggregate network\n"
6545 "Name of route map\n")
6548 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6549 char *prefix
= argv
[idx
]->arg
;
6552 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6554 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6555 ? AGGREGATE_SUMMARY_ONLY
6559 argv_find(argv
, argc
, "WORD", &idx
);
6561 rmap
= argv
[idx
]->arg
;
6563 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6564 rmap
, summary_only
, as_set
);
6567 DEFUN (aggregate_address_mask
,
6568 aggregate_address_mask_cmd
,
6569 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6570 "Configure BGP aggregate entries\n"
6571 "Aggregate address\n"
6573 "Generate AS set path information\n"
6574 "Filter more specific routes from updates\n"
6575 "Filter more specific routes from updates\n"
6576 "Generate AS set path information\n"
6577 "Apply route map to aggregate network\n"
6578 "Name of route map\n")
6581 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6582 char *prefix
= argv
[idx
]->arg
;
6583 char *mask
= argv
[idx
+ 1]->arg
;
6587 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6589 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6590 ? AGGREGATE_SUMMARY_ONLY
6593 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6595 rmap
= argv
[idx
]->arg
;
6597 char prefix_str
[BUFSIZ
];
6598 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6601 vty_out(vty
, "%% Inconsistent address and mask\n");
6602 return CMD_WARNING_CONFIG_FAILED
;
6605 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6606 rmap
, summary_only
, as_set
);
6609 DEFUN (no_aggregate_address
,
6610 no_aggregate_address_cmd
,
6611 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6613 "Configure BGP aggregate entries\n"
6614 "Aggregate prefix\n"
6615 "Generate AS set path information\n"
6616 "Filter more specific routes from updates\n"
6617 "Filter more specific routes from updates\n"
6618 "Generate AS set path information\n"
6619 "Apply route map to aggregate network\n"
6620 "Name of route map\n")
6623 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6624 char *prefix
= argv
[idx
]->arg
;
6625 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6628 DEFUN (no_aggregate_address_mask
,
6629 no_aggregate_address_mask_cmd
,
6630 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6632 "Configure BGP aggregate entries\n"
6633 "Aggregate address\n"
6635 "Generate AS set path information\n"
6636 "Filter more specific routes from updates\n"
6637 "Filter more specific routes from updates\n"
6638 "Generate AS set path information\n"
6639 "Apply route map to aggregate network\n"
6640 "Name of route map\n")
6643 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6644 char *prefix
= argv
[idx
]->arg
;
6645 char *mask
= argv
[idx
+ 1]->arg
;
6647 char prefix_str
[BUFSIZ
];
6648 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6651 vty_out(vty
, "%% Inconsistent address and mask\n");
6652 return CMD_WARNING_CONFIG_FAILED
;
6655 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6658 DEFUN (ipv6_aggregate_address
,
6659 ipv6_aggregate_address_cmd
,
6660 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6661 "Configure BGP aggregate entries\n"
6662 "Aggregate prefix\n"
6663 "Generate AS set path information\n"
6664 "Filter more specific routes from updates\n"
6665 "Filter more specific routes from updates\n"
6666 "Generate AS set path information\n"
6667 "Apply route map to aggregate network\n"
6668 "Name of route map\n")
6671 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6672 char *prefix
= argv
[idx
]->arg
;
6676 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6679 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6680 ? AGGREGATE_SUMMARY_ONLY
6683 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6685 rmap
= argv
[idx
]->arg
;
6687 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6691 DEFUN (no_ipv6_aggregate_address
,
6692 no_ipv6_aggregate_address_cmd
,
6693 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6695 "Configure BGP aggregate entries\n"
6696 "Aggregate prefix\n"
6697 "Generate AS set path information\n"
6698 "Filter more specific routes from updates\n"
6699 "Filter more specific routes from updates\n"
6700 "Generate AS set path information\n"
6701 "Apply route map to aggregate network\n"
6702 "Name of route map\n")
6705 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6706 char *prefix
= argv
[idx
]->arg
;
6707 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6710 /* Redistribute route treatment. */
6711 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6712 const union g_addr
*nexthop
, ifindex_t ifindex
,
6713 enum nexthop_types_t nhtype
, uint32_t metric
,
6714 uint8_t type
, unsigned short instance
,
6717 struct bgp_path_info
*new;
6718 struct bgp_path_info
*bpi
;
6719 struct bgp_path_info rmap_path
;
6720 struct bgp_node
*bn
;
6722 struct attr
*new_attr
;
6724 route_map_result_t ret
;
6725 struct bgp_redist
*red
;
6727 /* Make default attribute. */
6728 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6730 * This must not be NULL to satisfy Coverity SA
6732 assert(attr
.aspath
);
6735 case NEXTHOP_TYPE_IFINDEX
:
6737 case NEXTHOP_TYPE_IPV4
:
6738 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6739 attr
.nexthop
= nexthop
->ipv4
;
6741 case NEXTHOP_TYPE_IPV6
:
6742 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6743 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6744 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6746 case NEXTHOP_TYPE_BLACKHOLE
:
6747 switch (p
->family
) {
6749 attr
.nexthop
.s_addr
= INADDR_ANY
;
6752 memset(&attr
.mp_nexthop_global
, 0,
6753 sizeof(attr
.mp_nexthop_global
));
6754 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6759 attr
.nh_ifindex
= ifindex
;
6762 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6765 afi
= family2afi(p
->family
);
6767 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6769 struct attr attr_new
;
6771 /* Copy attribute for modification. */
6772 bgp_attr_dup(&attr_new
, &attr
);
6774 if (red
->redist_metric_flag
)
6775 attr_new
.med
= red
->redist_metric
;
6777 /* Apply route-map. */
6778 if (red
->rmap
.name
) {
6779 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6780 rmap_path
.peer
= bgp
->peer_self
;
6781 rmap_path
.attr
= &attr_new
;
6783 SET_FLAG(bgp
->peer_self
->rmap_type
,
6784 PEER_RMAP_TYPE_REDISTRIBUTE
);
6786 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6789 bgp
->peer_self
->rmap_type
= 0;
6791 if (ret
== RMAP_DENYMATCH
) {
6792 /* Free uninterned attribute. */
6793 bgp_attr_flush(&attr_new
);
6795 /* Unintern original. */
6796 aspath_unintern(&attr
.aspath
);
6797 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6802 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6803 bgp_attr_add_gshut_community(&attr_new
);
6805 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6806 SAFI_UNICAST
, p
, NULL
);
6808 new_attr
= bgp_attr_intern(&attr_new
);
6810 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6812 if (bpi
->peer
== bgp
->peer_self
6813 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6817 /* Ensure the (source route) type is updated. */
6819 if (attrhash_cmp(bpi
->attr
, new_attr
)
6820 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6821 bgp_attr_unintern(&new_attr
);
6822 aspath_unintern(&attr
.aspath
);
6823 bgp_unlock_node(bn
);
6826 /* The attribute is changed. */
6827 bgp_path_info_set_flag(bn
, bpi
,
6828 BGP_PATH_ATTR_CHANGED
);
6830 /* Rewrite BGP route information. */
6831 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6832 bgp_path_info_restore(bn
, bpi
);
6834 bgp_aggregate_decrement(
6835 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6836 bgp_attr_unintern(&bpi
->attr
);
6837 bpi
->attr
= new_attr
;
6838 bpi
->uptime
= bgp_clock();
6840 /* Process change. */
6841 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6843 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6844 bgp_unlock_node(bn
);
6845 aspath_unintern(&attr
.aspath
);
6847 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6849 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6851 vpn_leak_from_vrf_update(
6852 bgp_get_default(), bgp
, bpi
);
6858 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6859 bgp
->peer_self
, new_attr
, bn
);
6860 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6862 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6863 bgp_path_info_add(bn
, new);
6864 bgp_unlock_node(bn
);
6865 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6867 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6868 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6870 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6874 /* Unintern original. */
6875 aspath_unintern(&attr
.aspath
);
6878 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6879 unsigned short instance
)
6882 struct bgp_node
*rn
;
6883 struct bgp_path_info
*pi
;
6884 struct bgp_redist
*red
;
6886 afi
= family2afi(p
->family
);
6888 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6890 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6891 SAFI_UNICAST
, p
, NULL
);
6893 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6894 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6898 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6899 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6901 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6904 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6905 bgp_path_info_delete(rn
, pi
);
6906 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6908 bgp_unlock_node(rn
);
6912 /* Withdraw specified route type's route. */
6913 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6914 unsigned short instance
)
6916 struct bgp_node
*rn
;
6917 struct bgp_path_info
*pi
;
6918 struct bgp_table
*table
;
6920 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6922 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6923 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6924 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6925 && pi
->instance
== instance
)
6929 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6930 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6932 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6935 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6937 bgp_path_info_delete(rn
, pi
);
6938 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6943 /* Static function to display route. */
6944 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6951 if (p
->family
== AF_INET
) {
6955 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6958 json_object_string_add(json
, "prefix",
6959 inet_ntop(p
->family
,
6962 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6963 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6964 json_object_string_add(json
, "network", buf2
);
6966 } else if (p
->family
== AF_ETHERNET
) {
6967 prefix2str(p
, buf
, PREFIX_STRLEN
);
6968 len
= vty_out(vty
, "%s", buf
);
6969 } else if (p
->family
== AF_EVPN
) {
6973 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6976 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6977 } else if (p
->family
== AF_FLOWSPEC
) {
6978 route_vty_out_flowspec(vty
, p
, NULL
,
6980 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6981 NLRI_STRING_FORMAT_MIN
, json
);
6986 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6989 json_object_string_add(json
, "prefix",
6990 inet_ntop(p
->family
,
6993 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6994 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6995 json_object_string_add(json
, "network", buf2
);
7002 vty_out(vty
, "\n%*s", 20, " ");
7004 vty_out(vty
, "%*s", len
, " ");
7008 enum bgp_display_type
{
7012 /* Print the short form route status for a bgp_path_info */
7013 static void route_vty_short_status_out(struct vty
*vty
,
7014 struct bgp_path_info
*path
,
7015 json_object
*json_path
)
7019 /* Route status display. */
7020 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7021 json_object_boolean_true_add(json_path
, "removed");
7023 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7024 json_object_boolean_true_add(json_path
, "stale");
7026 if (path
->extra
&& path
->extra
->suppress
)
7027 json_object_boolean_true_add(json_path
, "suppressed");
7029 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7030 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7031 json_object_boolean_true_add(json_path
, "valid");
7034 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7035 json_object_boolean_true_add(json_path
, "history");
7037 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7038 json_object_boolean_true_add(json_path
, "damped");
7040 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7041 json_object_boolean_true_add(json_path
, "bestpath");
7043 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7044 json_object_boolean_true_add(json_path
, "multipath");
7046 /* Internal route. */
7047 if ((path
->peer
->as
)
7048 && (path
->peer
->as
== path
->peer
->local_as
))
7049 json_object_string_add(json_path
, "pathFrom",
7052 json_object_string_add(json_path
, "pathFrom",
7058 /* Route status display. */
7059 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7061 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7063 else if (path
->extra
&& path
->extra
->suppress
)
7065 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7066 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7072 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7074 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7076 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7078 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7083 /* Internal route. */
7084 if (path
->peer
&& (path
->peer
->as
)
7085 && (path
->peer
->as
== path
->peer
->local_as
))
7091 static char *bgp_nexthop_fqdn(struct peer
*peer
)
7093 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
))
7094 return peer
->hostname
;
7098 /* called from terminal list command */
7099 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7100 struct bgp_path_info
*path
, int display
, safi_t safi
,
7101 json_object
*json_paths
)
7104 json_object
*json_path
= NULL
;
7105 json_object
*json_nexthops
= NULL
;
7106 json_object
*json_nexthop_global
= NULL
;
7107 json_object
*json_nexthop_ll
= NULL
;
7108 json_object
*json_ext_community
= NULL
;
7109 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7111 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7112 bool nexthop_othervrf
= false;
7113 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7114 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7115 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
7118 json_path
= json_object_new_object();
7120 /* short status lead text */
7121 route_vty_short_status_out(vty
, path
, json_path
);
7124 /* print prefix and mask */
7126 route_vty_out_route(p
, vty
, json_path
);
7128 vty_out(vty
, "%*s", 17, " ");
7130 route_vty_out_route(p
, vty
, json_path
);
7133 /* Print attribute */
7137 * If vrf id of nexthop is different from that of prefix,
7138 * set up printable string to append
7140 if (path
->extra
&& path
->extra
->bgp_orig
) {
7141 const char *self
= "";
7146 nexthop_othervrf
= true;
7147 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7149 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7150 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7151 "@%s%s", VRFID_NONE_STR
, self
);
7153 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7154 path
->extra
->bgp_orig
->vrf_id
, self
);
7156 if (path
->extra
->bgp_orig
->inst_type
7157 != BGP_INSTANCE_TYPE_DEFAULT
)
7159 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7161 const char *self
= "";
7166 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7170 * For ENCAP and EVPN routes, nexthop address family is not
7171 * neccessarily the same as the prefix address family.
7172 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7173 * EVPN routes are also exchanged with a MP nexthop. Currently,
7175 * is only IPv4, the value will be present in either
7177 * attr->mp_nexthop_global_in
7179 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7182 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7186 sprintf(nexthop
, "%s",
7187 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7191 sprintf(nexthop
, "%s",
7192 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7196 sprintf(nexthop
, "?");
7201 json_nexthop_global
= json_object_new_object();
7203 json_object_string_add(
7204 json_nexthop_global
, "afi",
7205 nexthop_fqdn
? "fqdn"
7206 : (af
== AF_INET
) ? "ip" : "ipv6");
7207 json_object_string_add(
7208 json_nexthop_global
,
7209 nexthop_fqdn
? "fqdn"
7210 : (af
== AF_INET
) ? "ip" : "ipv6",
7211 nexthop_fqdn
? nexthop_fqdn
: nexthop
);
7212 json_object_boolean_true_add(json_nexthop_global
,
7215 vty_out(vty
, "%s%s",
7216 nexthop_fqdn
? nexthop_fqdn
: nexthop
,
7218 } else if (safi
== SAFI_EVPN
) {
7220 json_nexthop_global
= json_object_new_object();
7222 json_object_string_add(
7223 json_nexthop_global
,
7224 nexthop_fqdn
? "fqdn" : "ip",
7225 nexthop_fqdn
? nexthop_fqdn
7226 : inet_ntoa(attr
->nexthop
));
7227 json_object_string_add(json_nexthop_global
, "afi",
7229 json_object_boolean_true_add(json_nexthop_global
,
7232 vty_out(vty
, "%-16s%s",
7233 nexthop_fqdn
?: inet_ntoa(attr
->nexthop
),
7235 } else if (safi
== SAFI_FLOWSPEC
) {
7236 if (attr
->nexthop
.s_addr
!= 0) {
7238 json_nexthop_global
= json_object_new_object();
7239 json_object_string_add(
7240 json_nexthop_global
,
7241 nexthop_fqdn
? "fqdn" : "ip",
7244 : inet_ntoa(attr
->nexthop
));
7245 json_object_string_add(json_nexthop_global
,
7247 json_object_boolean_true_add(
7248 json_nexthop_global
,
7251 vty_out(vty
, "%-16s",
7254 : inet_ntoa(attr
->nexthop
));
7257 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7259 json_nexthop_global
= json_object_new_object();
7261 json_object_string_add(json_nexthop_global
,
7262 nexthop_fqdn
? "fqdn" : "ip",
7265 : inet_ntoa(attr
->nexthop
));
7267 json_object_string_add(json_nexthop_global
, "afi",
7269 json_object_boolean_true_add(json_nexthop_global
,
7274 snprintf(buf
, sizeof(buf
), "%s%s",
7275 nexthop_fqdn
? nexthop_fqdn
7276 : inet_ntoa(attr
->nexthop
),
7278 vty_out(vty
, "%-16s", buf
);
7283 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7288 json_nexthop_global
= json_object_new_object();
7289 json_object_string_add(
7290 json_nexthop_global
,
7291 nexthop_fqdn
? "fqdn" : "ip",
7294 : inet_ntop(AF_INET6
,
7295 &attr
->mp_nexthop_global
,
7297 json_object_string_add(json_nexthop_global
, "afi",
7299 json_object_string_add(json_nexthop_global
, "scope",
7302 /* We display both LL & GL if both have been
7304 if ((attr
->mp_nexthop_len
7305 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7306 || (path
->peer
->conf_if
)) {
7307 json_nexthop_ll
= json_object_new_object();
7308 json_object_string_add(
7310 nexthop_fqdn
? "fqdn" : "ip",
7315 &attr
->mp_nexthop_local
,
7317 json_object_string_add(json_nexthop_ll
, "afi",
7319 json_object_string_add(json_nexthop_ll
, "scope",
7322 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7323 &attr
->mp_nexthop_local
)
7325 && !attr
->mp_nexthop_prefer_global
)
7326 json_object_boolean_true_add(
7327 json_nexthop_ll
, "used");
7329 json_object_boolean_true_add(
7330 json_nexthop_global
, "used");
7332 json_object_boolean_true_add(
7333 json_nexthop_global
, "used");
7335 /* Display LL if LL/Global both in table unless
7336 * prefer-global is set */
7337 if (((attr
->mp_nexthop_len
7338 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7339 && !attr
->mp_nexthop_prefer_global
)
7340 || (path
->peer
->conf_if
)) {
7341 if (path
->peer
->conf_if
) {
7342 len
= vty_out(vty
, "%s",
7343 path
->peer
->conf_if
);
7344 len
= 16 - len
; /* len of IPv6
7350 vty_out(vty
, "\n%*s", 36, " ");
7352 vty_out(vty
, "%*s", len
, " ");
7360 &attr
->mp_nexthop_local
,
7366 vty_out(vty
, "\n%*s", 36, " ");
7368 vty_out(vty
, "%*s", len
, " ");
7377 &attr
->mp_nexthop_global
,
7383 vty_out(vty
, "\n%*s", 36, " ");
7385 vty_out(vty
, "%*s", len
, " ");
7391 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7395 * Adding "metric" field to match with corresponding
7396 * CLI. "med" will be deprecated in future.
7398 json_object_int_add(json_path
, "med", attr
->med
);
7399 json_object_int_add(json_path
, "metric", attr
->med
);
7401 vty_out(vty
, "%10u", attr
->med
);
7402 else if (!json_paths
)
7406 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7410 * Adding "locPrf" field to match with corresponding
7411 * CLI. "localPref" will be deprecated in future.
7413 json_object_int_add(json_path
, "localpref",
7415 json_object_int_add(json_path
, "locPrf",
7418 vty_out(vty
, "%7u", attr
->local_pref
);
7419 else if (!json_paths
)
7423 json_object_int_add(json_path
, "weight", attr
->weight
);
7425 vty_out(vty
, "%7u ", attr
->weight
);
7429 json_object_string_add(
7430 json_path
, "peerId",
7431 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7439 * Adding "path" field to match with corresponding
7440 * CLI. "aspath" will be deprecated in future.
7442 json_object_string_add(json_path
, "aspath",
7444 json_object_string_add(json_path
, "path",
7447 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7452 json_object_string_add(json_path
, "origin",
7453 bgp_origin_long_str
[attr
->origin
]);
7455 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7458 if (safi
== SAFI_EVPN
&&
7459 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7460 json_ext_community
= json_object_new_object();
7461 json_object_string_add(json_ext_community
,
7463 attr
->ecommunity
->str
);
7464 json_object_object_add(json_path
,
7465 "extendedCommunity",
7466 json_ext_community
);
7470 json_object_boolean_true_add(json_path
,
7471 "announceNexthopSelf");
7472 if (nexthop_othervrf
) {
7473 json_object_string_add(json_path
, "nhVrfName",
7476 json_object_int_add(json_path
, "nhVrfId",
7477 ((nexthop_vrfid
== VRF_UNKNOWN
)
7479 : (int)nexthop_vrfid
));
7484 if (json_nexthop_global
|| json_nexthop_ll
) {
7485 json_nexthops
= json_object_new_array();
7487 if (json_nexthop_global
)
7488 json_object_array_add(json_nexthops
,
7489 json_nexthop_global
);
7491 if (json_nexthop_ll
)
7492 json_object_array_add(json_nexthops
,
7495 json_object_object_add(json_path
, "nexthops",
7499 json_object_array_add(json_paths
, json_path
);
7503 if (safi
== SAFI_EVPN
&&
7504 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7505 vty_out(vty
, "%*s", 20, " ");
7506 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7510 /* prints an additional line, indented, with VNC info, if
7512 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7513 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7518 /* called from terminal list command */
7519 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7520 safi_t safi
, bool use_json
, json_object
*json_ar
)
7522 json_object
*json_status
= NULL
;
7523 json_object
*json_net
= NULL
;
7526 /* Route status display. */
7528 json_status
= json_object_new_object();
7529 json_net
= json_object_new_object();
7536 /* print prefix and mask */
7538 if (safi
== SAFI_EVPN
)
7539 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7540 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7541 json_object_string_add(
7542 json_net
, "addrPrefix",
7543 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7545 json_object_int_add(json_net
, "prefixLen",
7547 prefix2str(p
, buff
, PREFIX_STRLEN
);
7548 json_object_string_add(json_net
, "network", buff
);
7551 route_vty_out_route(p
, vty
, NULL
);
7553 /* Print attribute */
7556 if (p
->family
== AF_INET
7557 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7558 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7559 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7560 json_object_string_add(
7561 json_net
, "nextHop",
7563 attr
->mp_nexthop_global_in
));
7565 json_object_string_add(
7566 json_net
, "nextHop",
7567 inet_ntoa(attr
->nexthop
));
7568 } else if (p
->family
== AF_INET6
7569 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7572 json_object_string_add(
7573 json_net
, "nextHopGlobal",
7575 &attr
->mp_nexthop_global
, buf
,
7577 } else if (p
->family
== AF_EVPN
&&
7578 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7579 json_object_string_add(json_net
,
7580 "nextHop", inet_ntoa(
7581 attr
->mp_nexthop_global_in
));
7584 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7585 json_object_int_add(json_net
, "metric",
7588 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7591 * Adding "locPrf" field to match with
7592 * corresponding CLI. "localPref" will be
7593 * deprecated in future.
7595 json_object_int_add(json_net
, "localPref",
7597 json_object_int_add(json_net
, "locPrf",
7601 json_object_int_add(json_net
, "weight", attr
->weight
);
7607 * Adding "path" field to match with
7608 * corresponding CLI. "localPref" will be
7609 * deprecated in future.
7611 json_object_string_add(json_net
, "asPath",
7613 json_object_string_add(json_net
, "path",
7618 json_object_string_add(json_net
, "bgpOriginCode",
7619 bgp_origin_str
[attr
->origin
]);
7621 if (p
->family
== AF_INET
7622 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7623 || safi
== SAFI_EVPN
7624 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7625 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7626 || safi
== SAFI_EVPN
)
7627 vty_out(vty
, "%-16s",
7629 attr
->mp_nexthop_global_in
));
7631 vty_out(vty
, "%-16s",
7632 inet_ntoa(attr
->nexthop
));
7633 } else if (p
->family
== AF_INET6
7634 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7641 &attr
->mp_nexthop_global
, buf
,
7645 vty_out(vty
, "\n%*s", 36, " ");
7647 vty_out(vty
, "%*s", len
, " ");
7650 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7651 vty_out(vty
, "%10u", attr
->med
);
7655 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7656 vty_out(vty
, "%7u", attr
->local_pref
);
7660 vty_out(vty
, "%7u ", attr
->weight
);
7664 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7667 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7671 json_object_boolean_true_add(json_status
, "*");
7672 json_object_boolean_true_add(json_status
, ">");
7673 json_object_object_add(json_net
, "appliedStatusSymbols",
7676 prefix2str(p
, buff
, PREFIX_STRLEN
);
7677 json_object_object_add(json_ar
, buff
, json_net
);
7682 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7683 struct bgp_path_info
*path
, int display
, safi_t safi
,
7686 json_object
*json_out
= NULL
;
7688 mpls_label_t label
= MPLS_INVALID_LABEL
;
7694 json_out
= json_object_new_object();
7696 /* short status lead text */
7697 route_vty_short_status_out(vty
, path
, json_out
);
7699 /* print prefix and mask */
7702 route_vty_out_route(p
, vty
, NULL
);
7704 vty_out(vty
, "%*s", 17, " ");
7707 /* Print attribute */
7709 if (((p
->family
== AF_INET
)
7710 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7711 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7712 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7713 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7714 || safi
== SAFI_EVPN
) {
7716 json_object_string_add(
7717 json_out
, "mpNexthopGlobalIn",
7718 inet_ntoa(attr
->mp_nexthop_global_in
));
7720 vty_out(vty
, "%-16s",
7721 inet_ntoa(attr
->mp_nexthop_global_in
));
7724 json_object_string_add(
7725 json_out
, "nexthop",
7726 inet_ntoa(attr
->nexthop
));
7728 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
7730 } else if (((p
->family
== AF_INET6
)
7731 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7732 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7733 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7736 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7738 json_object_string_add(
7739 json_out
, "mpNexthopGlobalIn",
7741 &attr
->mp_nexthop_global
,
7742 buf_a
, sizeof(buf_a
)));
7746 &attr
->mp_nexthop_global
,
7747 buf_a
, sizeof(buf_a
)));
7748 } else if (attr
->mp_nexthop_len
7749 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7750 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
7751 &attr
->mp_nexthop_global
,
7752 &attr
->mp_nexthop_local
);
7754 json_object_string_add(json_out
,
7755 "mpNexthopGlobalLocal",
7758 vty_out(vty
, "%s", buf_a
);
7762 label
= decode_label(&path
->extra
->label
[0]);
7764 if (bgp_is_valid_label(&label
)) {
7766 json_object_int_add(json_out
, "notag", label
);
7767 json_object_array_add(json
, json_out
);
7769 vty_out(vty
, "notag/%d", label
);
7775 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7776 struct bgp_path_info
*path
, int display
,
7777 json_object
*json_paths
)
7780 char buf
[BUFSIZ
] = {0};
7781 json_object
*json_path
= NULL
;
7782 json_object
*json_nexthop
= NULL
;
7783 json_object
*json_overlay
= NULL
;
7789 json_path
= json_object_new_object();
7790 json_overlay
= json_object_new_object();
7791 json_nexthop
= json_object_new_object();
7794 /* short status lead text */
7795 route_vty_short_status_out(vty
, path
, json_path
);
7797 /* print prefix and mask */
7799 route_vty_out_route(p
, vty
, json_path
);
7801 vty_out(vty
, "%*s", 17, " ");
7803 /* Print attribute */
7806 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7810 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
7812 vty_out(vty
, "%-16s", buf
);
7814 json_object_string_add(json_nexthop
, "ip", buf
);
7816 json_object_string_add(json_nexthop
, "afi", "ipv4");
7818 json_object_object_add(json_path
, "nexthop",
7823 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
7824 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
7826 vty_out(vty
, "%s(%s)", buf
, buf1
);
7828 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
7830 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
7833 json_object_string_add(json_nexthop
, "afi", "ipv6");
7835 json_object_object_add(json_path
, "nexthop",
7843 json_object_string_add(json_nexthop
, "Error",
7844 "Unsupported address-family");
7848 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7851 vty_out(vty
, "%s", str
);
7853 json_object_string_add(json_overlay
, "esi", str
);
7855 XFREE(MTYPE_TMP
, str
);
7857 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7858 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
7860 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7861 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7866 vty_out(vty
, "/%s", buf
);
7868 json_object_string_add(json_overlay
, "gw", buf
);
7870 if (attr
->ecommunity
) {
7872 struct ecommunity_val
*routermac
= ecommunity_lookup(
7873 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7874 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7877 mac
= ecom_mac2str((char *)routermac
->val
);
7880 vty_out(vty
, "/%s", (char *)mac
);
7882 json_object_string_add(json_overlay
, "rmac",
7885 XFREE(MTYPE_TMP
, mac
);
7892 json_object_object_add(json_path
, "overlay", json_overlay
);
7894 json_object_array_add(json_paths
, json_path
);
7898 /* dampening route */
7899 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7900 struct bgp_path_info
*path
, int display
, afi_t afi
,
7901 safi_t safi
, bool use_json
, json_object
*json
)
7905 char timebuf
[BGP_UPTIME_LEN
];
7907 /* short status lead text */
7908 route_vty_short_status_out(vty
, path
, json
);
7910 /* print prefix and mask */
7913 route_vty_out_route(p
, vty
, NULL
);
7915 vty_out(vty
, "%*s", 17, " ");
7918 len
= vty_out(vty
, "%s", path
->peer
->host
);
7922 vty_out(vty
, "\n%*s", 34, " ");
7925 json_object_int_add(json
, "peerHost", len
);
7927 vty_out(vty
, "%*s", len
, " ");
7931 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
7932 safi
, use_json
, json
);
7935 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7936 BGP_UPTIME_LEN
, afi
, safi
,
7939 /* Print attribute */
7945 json_object_string_add(json
, "asPath",
7948 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7953 json_object_string_add(json
, "origin",
7954 bgp_origin_str
[attr
->origin
]);
7956 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7963 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7964 struct bgp_path_info
*path
, int display
, afi_t afi
,
7965 safi_t safi
, bool use_json
, json_object
*json
)
7968 struct bgp_damp_info
*bdi
;
7969 char timebuf
[BGP_UPTIME_LEN
];
7975 bdi
= path
->extra
->damp_info
;
7977 /* short status lead text */
7978 route_vty_short_status_out(vty
, path
, json
);
7980 /* print prefix and mask */
7983 route_vty_out_route(p
, vty
, NULL
);
7985 vty_out(vty
, "%*s", 17, " ");
7988 len
= vty_out(vty
, "%s", path
->peer
->host
);
7992 vty_out(vty
, "\n%*s", 33, " ");
7995 json_object_int_add(json
, "peerHost", len
);
7997 vty_out(vty
, "%*s", len
, " ");
8000 len
= vty_out(vty
, "%d", bdi
->flap
);
8007 json_object_int_add(json
, "bdiFlap", len
);
8009 vty_out(vty
, "%*s", len
, " ");
8013 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8016 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8017 BGP_UPTIME_LEN
, 0, NULL
));
8019 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8020 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8022 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8023 BGP_UPTIME_LEN
, afi
, safi
,
8027 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8028 BGP_UPTIME_LEN
, afi
,
8029 safi
, use_json
, json
));
8032 vty_out(vty
, "%*s ", 8, " ");
8035 /* Print attribute */
8041 json_object_string_add(json
, "asPath",
8044 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8049 json_object_string_add(json
, "origin",
8050 bgp_origin_str
[attr
->origin
]);
8052 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8058 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8059 int *first
, const char *header
,
8060 json_object
*json_adv_to
)
8062 char buf1
[INET6_ADDRSTRLEN
];
8063 json_object
*json_peer
= NULL
;
8066 /* 'advertised-to' is a dictionary of peers we have advertised
8068 * prefix too. The key is the peer's IP or swpX, the value is
8070 * hostname if we know it and "" if not.
8072 json_peer
= json_object_new_object();
8075 json_object_string_add(json_peer
, "hostname",
8079 json_object_object_add(json_adv_to
, peer
->conf_if
,
8082 json_object_object_add(
8084 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8088 vty_out(vty
, "%s", header
);
8093 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8095 vty_out(vty
, " %s(%s)", peer
->hostname
,
8098 vty_out(vty
, " %s(%s)", peer
->hostname
,
8099 sockunion2str(&peer
->su
, buf1
,
8103 vty_out(vty
, " %s", peer
->conf_if
);
8106 sockunion2str(&peer
->su
, buf1
,
8112 static void route_vty_out_tx_ids(struct vty
*vty
,
8113 struct bgp_addpath_info_data
*d
)
8117 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8118 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8119 d
->addpath_tx_id
[i
],
8120 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8124 static const char *bgp_path_selection_reason2str(
8125 enum bgp_path_selection_reason reason
)
8128 case bgp_path_selection_none
:
8129 return "Nothing to Select";
8131 case bgp_path_selection_first
:
8132 return "First path received";
8134 case bgp_path_selection_evpn_sticky_mac
:
8135 return "EVPN Sticky Mac";
8137 case bgp_path_selection_evpn_seq
:
8138 return "EVPN sequence number";
8140 case bgp_path_selection_evpn_lower_ip
:
8141 return "EVPN lower IP";
8143 case bgp_path_selection_weight
:
8146 case bgp_path_selection_local_pref
:
8147 return "Local Pref";
8149 case bgp_path_selection_local_route
:
8150 return "Local Route";
8152 case bgp_path_selection_confed_as_path
:
8153 return "Confederation based AS Path";
8155 case bgp_path_selection_as_path
:
8158 case bgp_path_selection_origin
:
8161 case bgp_path_selection_med
:
8164 case bgp_path_selection_peer
:
8167 case bgp_path_selection_confed
:
8168 return "Confed Peer Type";
8170 case bgp_path_selection_igp_metric
:
8171 return "IGP Metric";
8173 case bgp_path_selection_older
:
8174 return "Older Path";
8176 case bgp_path_selection_router_id
:
8179 case bgp_path_selection_cluster_length
:
8180 return "Cluser length";
8182 case bgp_path_selection_stale
:
8183 return "Path Staleness";
8185 case bgp_path_selection_local_configured
:
8186 return "Locally configured route";
8188 case bgp_path_selection_neighbor_ip
:
8189 return "Neighbor IP";
8191 case bgp_path_selection_default
:
8192 return "Nothing left to compare";
8195 return "Invalid (internal error)";
8198 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8199 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8200 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8202 char buf
[INET6_ADDRSTRLEN
];
8204 char buf2
[EVPN_ROUTE_STRLEN
];
8206 int sockunion_vty_out(struct vty
*, union sockunion
*);
8208 json_object
*json_bestpath
= NULL
;
8209 json_object
*json_cluster_list
= NULL
;
8210 json_object
*json_cluster_list_list
= NULL
;
8211 json_object
*json_ext_community
= NULL
;
8212 json_object
*json_last_update
= NULL
;
8213 json_object
*json_pmsi
= NULL
;
8214 json_object
*json_nexthop_global
= NULL
;
8215 json_object
*json_nexthop_ll
= NULL
;
8216 json_object
*json_nexthops
= NULL
;
8217 json_object
*json_path
= NULL
;
8218 json_object
*json_peer
= NULL
;
8219 json_object
*json_string
= NULL
;
8220 json_object
*json_adv_to
= NULL
;
8222 struct listnode
*node
, *nnode
;
8224 int addpath_capable
;
8226 unsigned int first_as
;
8228 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8230 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
8233 json_path
= json_object_new_object();
8234 json_peer
= json_object_new_object();
8235 json_nexthop_global
= json_object_new_object();
8243 if (path
->extra
&& path
->extra
->num_labels
) {
8244 bgp_evpn_label2str(path
->extra
->label
,
8245 path
->extra
->num_labels
, tag_buf
,
8248 if (safi
== SAFI_EVPN
) {
8250 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8251 buf2
, sizeof(buf2
));
8252 vty_out(vty
, " Route %s", buf2
);
8253 if (tag_buf
[0] != '\0')
8254 vty_out(vty
, " VNI %s", tag_buf
);
8258 json_object_string_add(json_path
, "VNI",
8263 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8264 struct bgp_path_info
*parent_ri
;
8265 struct bgp_node
*rn
, *prn
;
8267 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8268 rn
= parent_ri
->net
;
8269 if (rn
&& rn
->prn
) {
8271 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8272 buf1
, sizeof(buf1
));
8273 if (is_pi_family_evpn(parent_ri
)) {
8274 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8275 buf2
, sizeof(buf2
));
8276 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8278 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8285 /* Line1 display AS-path, Aggregator */
8288 if (!attr
->aspath
->json
)
8289 aspath_str_update(attr
->aspath
, true);
8290 json_object_lock(attr
->aspath
->json
);
8291 json_object_object_add(json_path
, "aspath",
8292 attr
->aspath
->json
);
8294 if (attr
->aspath
->segments
)
8295 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8297 vty_out(vty
, " Local");
8301 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8303 json_object_boolean_true_add(json_path
, "removed");
8305 vty_out(vty
, ", (removed)");
8308 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8310 json_object_boolean_true_add(json_path
, "stale");
8312 vty_out(vty
, ", (stale)");
8315 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8317 json_object_int_add(json_path
, "aggregatorAs",
8318 attr
->aggregator_as
);
8319 json_object_string_add(
8320 json_path
, "aggregatorId",
8321 inet_ntoa(attr
->aggregator_addr
));
8323 vty_out(vty
, ", (aggregated by %u %s)",
8324 attr
->aggregator_as
,
8325 inet_ntoa(attr
->aggregator_addr
));
8329 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8330 PEER_FLAG_REFLECTOR_CLIENT
)) {
8332 json_object_boolean_true_add(json_path
,
8333 "rxedFromRrClient");
8335 vty_out(vty
, ", (Received from a RR-client)");
8338 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8339 PEER_FLAG_RSERVER_CLIENT
)) {
8341 json_object_boolean_true_add(json_path
,
8342 "rxedFromRsClient");
8344 vty_out(vty
, ", (Received from a RS-client)");
8347 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8349 json_object_boolean_true_add(json_path
,
8350 "dampeningHistoryEntry");
8352 vty_out(vty
, ", (history entry)");
8353 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8355 json_object_boolean_true_add(json_path
,
8356 "dampeningSuppressed");
8358 vty_out(vty
, ", (suppressed due to dampening)");
8364 /* Line2 display Next-hop, Neighbor, Router-id */
8365 /* Display the nexthop */
8366 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8367 || bn
->p
.family
== AF_EVPN
)
8368 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8369 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8370 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8371 || safi
== SAFI_EVPN
) {
8373 json_object_string_add(
8374 json_nexthop_global
,
8375 nexthop_fqdn
? "fqdn" : "ip",
8379 attr
->mp_nexthop_global_in
));
8385 attr
->mp_nexthop_global_in
));
8388 json_object_string_add(
8389 json_nexthop_global
,
8390 nexthop_fqdn
? "fqdn" : "ip",
8393 : inet_ntoa(attr
->nexthop
));
8398 : inet_ntoa(attr
->nexthop
));
8402 json_object_string_add(json_nexthop_global
, "afi",
8406 json_object_string_add(
8407 json_nexthop_global
,
8408 nexthop_fqdn
? "fqdn" : "ip",
8411 : inet_ntop(AF_INET6
,
8412 &attr
->mp_nexthop_global
,
8413 buf
, INET6_ADDRSTRLEN
));
8414 json_object_string_add(json_nexthop_global
, "afi",
8416 json_object_string_add(json_nexthop_global
, "scope",
8422 : inet_ntop(AF_INET6
,
8423 &attr
->mp_nexthop_global
,
8424 buf
, INET6_ADDRSTRLEN
));
8428 /* Display the IGP cost or 'inaccessible' */
8429 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8431 json_object_boolean_false_add(json_nexthop_global
,
8434 vty_out(vty
, " (inaccessible)");
8436 if (path
->extra
&& path
->extra
->igpmetric
) {
8438 json_object_int_add(json_nexthop_global
,
8440 path
->extra
->igpmetric
);
8442 vty_out(vty
, " (metric %u)",
8443 path
->extra
->igpmetric
);
8446 /* IGP cost is 0, display this only for json */
8449 json_object_int_add(json_nexthop_global
,
8454 json_object_boolean_true_add(json_nexthop_global
,
8458 /* Display peer "from" output */
8459 /* This path was originated locally */
8460 if (path
->peer
== bgp
->peer_self
) {
8462 if (safi
== SAFI_EVPN
8463 || (bn
->p
.family
== AF_INET
8464 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8466 json_object_string_add(json_peer
, "peerId",
8469 vty_out(vty
, " from 0.0.0.0 ");
8472 json_object_string_add(json_peer
, "peerId",
8475 vty_out(vty
, " from :: ");
8479 json_object_string_add(json_peer
, "routerId",
8480 inet_ntoa(bgp
->router_id
));
8482 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8485 /* We RXed this path from one of our peers */
8489 json_object_string_add(json_peer
, "peerId",
8490 sockunion2str(&path
->peer
->su
,
8493 json_object_string_add(json_peer
, "routerId",
8495 &path
->peer
->remote_id
,
8496 buf1
, sizeof(buf1
)));
8498 if (path
->peer
->hostname
)
8499 json_object_string_add(json_peer
, "hostname",
8500 path
->peer
->hostname
);
8502 if (path
->peer
->domainname
)
8503 json_object_string_add(json_peer
, "domainname",
8504 path
->peer
->domainname
);
8506 if (path
->peer
->conf_if
)
8507 json_object_string_add(json_peer
, "interface",
8508 path
->peer
->conf_if
);
8510 if (path
->peer
->conf_if
) {
8511 if (path
->peer
->hostname
8512 && bgp_flag_check(path
->peer
->bgp
,
8513 BGP_FLAG_SHOW_HOSTNAME
))
8514 vty_out(vty
, " from %s(%s)",
8515 path
->peer
->hostname
,
8516 path
->peer
->conf_if
);
8518 vty_out(vty
, " from %s",
8519 path
->peer
->conf_if
);
8521 if (path
->peer
->hostname
8522 && bgp_flag_check(path
->peer
->bgp
,
8523 BGP_FLAG_SHOW_HOSTNAME
))
8524 vty_out(vty
, " from %s(%s)",
8525 path
->peer
->hostname
,
8528 vty_out(vty
, " from %s",
8529 sockunion2str(&path
->peer
->su
,
8534 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8535 vty_out(vty
, " (%s)",
8536 inet_ntoa(attr
->originator_id
));
8538 vty_out(vty
, " (%s)",
8540 &path
->peer
->remote_id
, buf1
,
8546 * Note when vrfid of nexthop is different from that of prefix
8548 if (path
->extra
&& path
->extra
->bgp_orig
) {
8549 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8554 if (path
->extra
->bgp_orig
->inst_type
8555 == BGP_INSTANCE_TYPE_DEFAULT
)
8556 vn
= VRF_DEFAULT_NAME
;
8558 vn
= path
->extra
->bgp_orig
->name
;
8560 json_object_string_add(json_path
, "nhVrfName", vn
);
8562 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8563 json_object_int_add(json_path
, "nhVrfId", -1);
8565 json_object_int_add(json_path
, "nhVrfId",
8566 (int)nexthop_vrfid
);
8569 if (nexthop_vrfid
== VRF_UNKNOWN
)
8570 vty_out(vty
, " vrf ?");
8572 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8578 json_object_boolean_true_add(json_path
,
8579 "announceNexthopSelf");
8581 vty_out(vty
, " announce-nh-self");
8588 /* display the link-local nexthop */
8589 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8591 json_nexthop_ll
= json_object_new_object();
8592 json_object_string_add(
8593 json_nexthop_ll
, nexthop_fqdn
? "fqdn" : "ip",
8596 : inet_ntop(AF_INET6
,
8597 &attr
->mp_nexthop_local
,
8598 buf
, INET6_ADDRSTRLEN
));
8599 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8600 json_object_string_add(json_nexthop_ll
, "scope",
8603 json_object_boolean_true_add(json_nexthop_ll
,
8606 if (!attr
->mp_nexthop_prefer_global
)
8607 json_object_boolean_true_add(json_nexthop_ll
,
8610 json_object_boolean_true_add(
8611 json_nexthop_global
, "used");
8613 vty_out(vty
, " (%s) %s\n",
8614 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8615 buf
, INET6_ADDRSTRLEN
),
8616 attr
->mp_nexthop_prefer_global
8621 /* If we do not have a link-local nexthop then we must flag the
8625 json_object_boolean_true_add(json_nexthop_global
,
8629 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8630 * Int/Ext/Local, Atomic, best */
8632 json_object_string_add(json_path
, "origin",
8633 bgp_origin_long_str
[attr
->origin
]);
8635 vty_out(vty
, " Origin %s",
8636 bgp_origin_long_str
[attr
->origin
]);
8638 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8641 * Adding "metric" field to match with
8642 * corresponding CLI. "med" will be
8643 * deprecated in future.
8645 json_object_int_add(json_path
, "med", attr
->med
);
8646 json_object_int_add(json_path
, "metric", attr
->med
);
8648 vty_out(vty
, ", metric %u", attr
->med
);
8651 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8653 json_object_int_add(json_path
, "localpref",
8656 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8659 if (attr
->weight
!= 0) {
8661 json_object_int_add(json_path
, "weight", attr
->weight
);
8663 vty_out(vty
, ", weight %u", attr
->weight
);
8666 if (attr
->tag
!= 0) {
8668 json_object_int_add(json_path
, "tag", attr
->tag
);
8670 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
8673 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8675 json_object_boolean_false_add(json_path
, "valid");
8677 vty_out(vty
, ", invalid");
8678 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8680 json_object_boolean_true_add(json_path
, "valid");
8682 vty_out(vty
, ", valid");
8685 if (path
->peer
!= bgp
->peer_self
) {
8686 if (path
->peer
->as
== path
->peer
->local_as
) {
8687 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
8689 json_object_string_add(
8693 vty_out(vty
, ", confed-internal");
8696 json_object_string_add(
8697 json_peer
, "type", "internal");
8699 vty_out(vty
, ", internal");
8702 if (bgp_confederation_peers_check(bgp
,
8705 json_object_string_add(
8709 vty_out(vty
, ", confed-external");
8712 json_object_string_add(
8713 json_peer
, "type", "external");
8715 vty_out(vty
, ", external");
8718 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8720 json_object_boolean_true_add(json_path
, "aggregated");
8721 json_object_boolean_true_add(json_path
, "local");
8723 vty_out(vty
, ", aggregated, local");
8725 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8727 json_object_boolean_true_add(json_path
, "sourced");
8729 vty_out(vty
, ", sourced");
8732 json_object_boolean_true_add(json_path
, "sourced");
8733 json_object_boolean_true_add(json_path
, "local");
8735 vty_out(vty
, ", sourced, local");
8739 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8741 json_object_boolean_true_add(json_path
,
8744 vty_out(vty
, ", atomic-aggregate");
8747 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8748 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8749 && bgp_path_info_mpath_count(path
))) {
8751 json_object_boolean_true_add(json_path
, "multipath");
8753 vty_out(vty
, ", multipath");
8756 // Mark the bestpath(s)
8757 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8758 first_as
= aspath_get_first_as(attr
->aspath
);
8762 json_bestpath
= json_object_new_object();
8763 json_object_int_add(json_bestpath
, "bestpathFromAs",
8767 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
8769 vty_out(vty
, ", bestpath-from-AS Local");
8773 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8776 json_bestpath
= json_object_new_object();
8777 json_object_boolean_true_add(json_bestpath
, "overall");
8778 json_object_string_add(
8779 json_bestpath
, "selectionReason",
8780 bgp_path_selection_reason2str(bn
->reason
));
8782 vty_out(vty
, ", best");
8783 vty_out(vty
, " (%s)",
8784 bgp_path_selection_reason2str(bn
->reason
));
8789 json_object_object_add(json_path
, "bestpath", json_bestpath
);
8794 /* Line 4 display Community */
8795 if (attr
->community
) {
8797 if (!attr
->community
->json
)
8798 community_str(attr
->community
, true);
8799 json_object_lock(attr
->community
->json
);
8800 json_object_object_add(json_path
, "community",
8801 attr
->community
->json
);
8803 vty_out(vty
, " Community: %s\n",
8804 attr
->community
->str
);
8808 /* Line 5 display Extended-community */
8809 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8811 json_ext_community
= json_object_new_object();
8812 json_object_string_add(json_ext_community
, "string",
8813 attr
->ecommunity
->str
);
8814 json_object_object_add(json_path
, "extendedCommunity",
8815 json_ext_community
);
8817 vty_out(vty
, " Extended Community: %s\n",
8818 attr
->ecommunity
->str
);
8822 /* Line 6 display Large community */
8823 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8825 if (!attr
->lcommunity
->json
)
8826 lcommunity_str(attr
->lcommunity
, true);
8827 json_object_lock(attr
->lcommunity
->json
);
8828 json_object_object_add(json_path
, "largeCommunity",
8829 attr
->lcommunity
->json
);
8831 vty_out(vty
, " Large Community: %s\n",
8832 attr
->lcommunity
->str
);
8836 /* Line 7 display Originator, Cluster-id */
8837 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8838 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8839 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8841 json_object_string_add(
8842 json_path
, "originatorId",
8843 inet_ntoa(attr
->originator_id
));
8845 vty_out(vty
, " Originator: %s",
8846 inet_ntoa(attr
->originator_id
));
8849 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8853 json_cluster_list
= json_object_new_object();
8854 json_cluster_list_list
=
8855 json_object_new_array();
8857 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8859 json_string
= json_object_new_string(
8860 inet_ntoa(attr
->cluster
8862 json_object_array_add(
8863 json_cluster_list_list
,
8868 * struct cluster_list does not have
8869 * "str" variable like aspath and community
8870 * do. Add this someday if someone asks
8872 * json_object_string_add(json_cluster_list,
8873 * "string", attr->cluster->str);
8875 json_object_object_add(json_cluster_list
,
8877 json_cluster_list_list
);
8878 json_object_object_add(json_path
, "clusterList",
8881 vty_out(vty
, ", Cluster list: ");
8883 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8886 inet_ntoa(attr
->cluster
8896 if (path
->extra
&& path
->extra
->damp_info
)
8897 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
8900 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8901 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
8902 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8905 json_object_int_add(json_path
, "remoteLabel", label
);
8907 vty_out(vty
, " Remote label: %d\n", label
);
8911 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8913 json_object_int_add(json_path
, "labelIndex",
8916 vty_out(vty
, " Label Index: %d\n",
8920 /* Line 8 display Addpath IDs */
8921 if (path
->addpath_rx_id
8922 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8924 json_object_int_add(json_path
, "addpathRxId",
8925 path
->addpath_rx_id
);
8927 /* Keep backwards compatibility with the old API
8928 * by putting TX All's ID in the old field
8930 json_object_int_add(
8931 json_path
, "addpathTxId",
8933 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
8935 /* ... but create a specific field for each
8938 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8939 json_object_int_add(
8941 bgp_addpath_names(i
)->id_json_name
,
8942 path
->tx_addpath
.addpath_tx_id
[i
]);
8945 vty_out(vty
, " AddPath ID: RX %u, ",
8946 path
->addpath_rx_id
);
8948 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8952 /* If we used addpath to TX a non-bestpath we need to display
8953 * "Advertised to" on a path-by-path basis
8955 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8958 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8960 bgp_addpath_encode_tx(peer
, afi
, safi
);
8961 has_adj
= bgp_adj_out_lookup(
8963 bgp_addpath_id_for_peer(peer
, afi
, safi
,
8964 &path
->tx_addpath
));
8966 if ((addpath_capable
&& has_adj
)
8967 || (!addpath_capable
&& has_adj
8968 && CHECK_FLAG(path
->flags
,
8969 BGP_PATH_SELECTED
))) {
8970 if (json_path
&& !json_adv_to
)
8971 json_adv_to
= json_object_new_object();
8973 route_vty_out_advertised_to(
8975 " Advertised to:", json_adv_to
);
8981 json_object_object_add(
8982 json_path
, "advertisedTo", json_adv_to
);
8991 /* Line 9 display Uptime */
8992 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8994 json_last_update
= json_object_new_object();
8995 json_object_int_add(json_last_update
, "epoch", tbuf
);
8996 json_object_string_add(json_last_update
, "string",
8998 json_object_object_add(json_path
, "lastUpdate",
9001 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9003 /* Line 10 display PMSI tunnel attribute, if present */
9004 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9006 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9007 PMSI_TNLTYPE_STR_DEFAULT
);
9010 json_pmsi
= json_object_new_object();
9011 json_object_string_add(json_pmsi
, "tunnelType", str
);
9012 json_object_int_add(json_pmsi
, "label",
9013 label2vni(&attr
->label
));
9014 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9016 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9017 str
, label2vni(&attr
->label
));
9020 /* We've constructed the json object for this path, add it to the json
9024 if (json_nexthop_global
|| json_nexthop_ll
) {
9025 json_nexthops
= json_object_new_array();
9027 if (json_nexthop_global
)
9028 json_object_array_add(json_nexthops
,
9029 json_nexthop_global
);
9031 if (json_nexthop_ll
)
9032 json_object_array_add(json_nexthops
,
9035 json_object_object_add(json_path
, "nexthops",
9039 json_object_object_add(json_path
, "peer", json_peer
);
9040 json_object_array_add(json_paths
, json_path
);
9044 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9045 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9046 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9048 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9049 const char *prefix_list_str
, afi_t afi
,
9050 safi_t safi
, enum bgp_show_type type
);
9051 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9052 const char *filter
, afi_t afi
, safi_t safi
,
9053 enum bgp_show_type type
);
9054 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9055 const char *rmap_str
, afi_t afi
, safi_t safi
,
9056 enum bgp_show_type type
);
9057 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9058 const char *com
, int exact
, afi_t afi
,
9060 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9061 const char *prefix
, afi_t afi
, safi_t safi
,
9062 enum bgp_show_type type
);
9063 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9064 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
9065 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9066 const char *comstr
, int exact
, afi_t afi
,
9067 safi_t safi
, bool use_json
);
9070 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9071 struct bgp_table
*table
, enum bgp_show_type type
,
9072 void *output_arg
, bool use_json
, char *rd
,
9073 int is_last
, unsigned long *output_cum
,
9074 unsigned long *total_cum
,
9075 unsigned long *json_header_depth
)
9077 struct bgp_path_info
*pi
;
9078 struct bgp_node
*rn
;
9081 unsigned long output_count
= 0;
9082 unsigned long total_count
= 0;
9085 json_object
*json_paths
= NULL
;
9088 if (output_cum
&& *output_cum
!= 0)
9091 if (use_json
&& !*json_header_depth
) {
9093 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9094 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9095 " \"localAS\": %u,\n \"routes\": { ",
9096 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9097 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9100 table
->version
, inet_ntoa(bgp
->router_id
),
9101 bgp
->default_local_pref
, bgp
->as
);
9102 *json_header_depth
= 2;
9104 vty_out(vty
, " \"routeDistinguishers\" : {");
9105 ++*json_header_depth
;
9109 if (use_json
&& rd
) {
9110 vty_out(vty
, " \"%s\" : { ", rd
);
9113 /* Start processing of routes. */
9114 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9115 pi
= bgp_node_get_bgp_path_info(rn
);
9121 json_paths
= json_object_new_array();
9125 for (; pi
; pi
= pi
->next
) {
9127 if (type
== bgp_show_type_flap_statistics
9128 || type
== bgp_show_type_flap_neighbor
9129 || type
== bgp_show_type_dampend_paths
9130 || type
== bgp_show_type_damp_neighbor
) {
9131 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9134 if (type
== bgp_show_type_regexp
) {
9135 regex_t
*regex
= output_arg
;
9137 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9141 if (type
== bgp_show_type_prefix_list
) {
9142 struct prefix_list
*plist
= output_arg
;
9144 if (prefix_list_apply(plist
, &rn
->p
)
9148 if (type
== bgp_show_type_filter_list
) {
9149 struct as_list
*as_list
= output_arg
;
9151 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9152 != AS_FILTER_PERMIT
)
9155 if (type
== bgp_show_type_route_map
) {
9156 struct route_map
*rmap
= output_arg
;
9157 struct bgp_path_info path
;
9158 struct attr dummy_attr
;
9159 route_map_result_t ret
;
9161 bgp_attr_dup(&dummy_attr
, pi
->attr
);
9163 path
.peer
= pi
->peer
;
9164 path
.attr
= &dummy_attr
;
9166 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9168 if (ret
== RMAP_DENYMATCH
)
9171 if (type
== bgp_show_type_neighbor
9172 || type
== bgp_show_type_flap_neighbor
9173 || type
== bgp_show_type_damp_neighbor
) {
9174 union sockunion
*su
= output_arg
;
9176 if (pi
->peer
== NULL
9177 || pi
->peer
->su_remote
== NULL
9178 || !sockunion_same(pi
->peer
->su_remote
, su
))
9181 if (type
== bgp_show_type_cidr_only
) {
9182 uint32_t destination
;
9184 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9185 if (IN_CLASSC(destination
)
9186 && rn
->p
.prefixlen
== 24)
9188 if (IN_CLASSB(destination
)
9189 && rn
->p
.prefixlen
== 16)
9191 if (IN_CLASSA(destination
)
9192 && rn
->p
.prefixlen
== 8)
9195 if (type
== bgp_show_type_prefix_longer
) {
9197 if (!prefix_match(p
, &rn
->p
))
9200 if (type
== bgp_show_type_community_all
) {
9201 if (!pi
->attr
->community
)
9204 if (type
== bgp_show_type_community
) {
9205 struct community
*com
= output_arg
;
9207 if (!pi
->attr
->community
9208 || !community_match(pi
->attr
->community
,
9212 if (type
== bgp_show_type_community_exact
) {
9213 struct community
*com
= output_arg
;
9215 if (!pi
->attr
->community
9216 || !community_cmp(pi
->attr
->community
, com
))
9219 if (type
== bgp_show_type_community_list
) {
9220 struct community_list
*list
= output_arg
;
9222 if (!community_list_match(pi
->attr
->community
,
9226 if (type
== bgp_show_type_community_list_exact
) {
9227 struct community_list
*list
= output_arg
;
9229 if (!community_list_exact_match(
9230 pi
->attr
->community
, list
))
9233 if (type
== bgp_show_type_lcommunity
) {
9234 struct lcommunity
*lcom
= output_arg
;
9236 if (!pi
->attr
->lcommunity
9237 || !lcommunity_match(pi
->attr
->lcommunity
,
9242 if (type
== bgp_show_type_lcommunity_exact
) {
9243 struct lcommunity
*lcom
= output_arg
;
9245 if (!pi
->attr
->lcommunity
9246 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9250 if (type
== bgp_show_type_lcommunity_list
) {
9251 struct community_list
*list
= output_arg
;
9253 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9258 == bgp_show_type_lcommunity_list_exact
) {
9259 struct community_list
*list
= output_arg
;
9261 if (!lcommunity_list_exact_match(
9262 pi
->attr
->lcommunity
, list
))
9265 if (type
== bgp_show_type_lcommunity_all
) {
9266 if (!pi
->attr
->lcommunity
)
9269 if (type
== bgp_show_type_dampend_paths
9270 || type
== bgp_show_type_damp_neighbor
) {
9271 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9272 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9276 if (!use_json
&& header
) {
9277 vty_out(vty
, "BGP table version is %" PRIu64
9278 ", local router ID is %s, vrf id ",
9280 inet_ntoa(bgp
->router_id
));
9281 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9282 vty_out(vty
, "%s", VRFID_NONE_STR
);
9284 vty_out(vty
, "%u", bgp
->vrf_id
);
9286 vty_out(vty
, "Default local pref %u, ",
9287 bgp
->default_local_pref
);
9288 vty_out(vty
, "local AS %u\n", bgp
->as
);
9289 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9290 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9291 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9292 if (type
== bgp_show_type_dampend_paths
9293 || type
== bgp_show_type_damp_neighbor
)
9294 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9295 else if (type
== bgp_show_type_flap_statistics
9296 || type
== bgp_show_type_flap_neighbor
)
9297 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9299 vty_out(vty
, BGP_SHOW_HEADER
);
9302 if (rd
!= NULL
&& !display
&& !output_count
) {
9305 "Route Distinguisher: %s\n",
9308 if (type
== bgp_show_type_dampend_paths
9309 || type
== bgp_show_type_damp_neighbor
)
9310 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9311 safi
, use_json
, json_paths
);
9312 else if (type
== bgp_show_type_flap_statistics
9313 || type
== bgp_show_type_flap_neighbor
)
9314 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9315 safi
, use_json
, json_paths
);
9317 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9329 if (p
->family
== AF_FLOWSPEC
) {
9330 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9332 bgp_fs_nlri_get_string((unsigned char *)
9333 p
->u
.prefix_flowspec
.ptr
,
9334 p
->u
.prefix_flowspec
9337 NLRI_STRING_FORMAT_MIN
,
9340 vty_out(vty
, "\"%s/%d\": ",
9342 p
->u
.prefix_flowspec
.prefixlen
);
9344 vty_out(vty
, ",\"%s/%d\": ",
9346 p
->u
.prefix_flowspec
.prefixlen
);
9348 prefix2str(p
, buf2
, sizeof(buf2
));
9350 vty_out(vty
, "\"%s\": ", buf2
);
9352 vty_out(vty
, ",\"%s\": ", buf2
);
9355 json_object_to_json_string(json_paths
));
9356 json_object_free(json_paths
);
9363 output_count
+= *output_cum
;
9364 *output_cum
= output_count
;
9367 total_count
+= *total_cum
;
9368 *total_cum
= total_count
;
9372 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9376 for (i
= 0; i
< *json_header_depth
; ++i
)
9377 vty_out(vty
, " } ");
9382 /* No route is displayed */
9383 if (output_count
== 0) {
9384 if (type
== bgp_show_type_normal
)
9386 "No BGP prefixes displayed, %ld exist\n",
9390 "\nDisplayed %ld routes and %ld total paths\n",
9391 output_count
, total_count
);
9398 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9399 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9400 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9402 struct bgp_node
*rn
, *next
;
9403 unsigned long output_cum
= 0;
9404 unsigned long total_cum
= 0;
9405 unsigned long json_header_depth
= 0;
9406 struct bgp_table
*itable
;
9409 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9411 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9412 next
= bgp_route_next(rn
);
9413 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9416 itable
= bgp_node_get_bgp_table_info(rn
);
9417 if (itable
!= NULL
) {
9418 struct prefix_rd prd
;
9419 char rd
[RD_ADDRSTRLEN
];
9421 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9422 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9423 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9424 use_json
, rd
, next
== NULL
, &output_cum
,
9425 &total_cum
, &json_header_depth
);
9431 if (output_cum
== 0)
9432 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9436 "\nDisplayed %ld routes and %ld total paths\n",
9437 output_cum
, total_cum
);
9441 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9442 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9444 struct bgp_table
*table
;
9445 unsigned long json_header_depth
= 0;
9448 bgp
= bgp_get_default();
9453 vty_out(vty
, "No BGP process is configured\n");
9455 vty_out(vty
, "{}\n");
9459 table
= bgp
->rib
[afi
][safi
];
9460 /* use MPLS and ENCAP specific shows until they are merged */
9461 if (safi
== SAFI_MPLS_VPN
) {
9462 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9463 output_arg
, use_json
);
9466 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9467 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9468 output_arg
, use_json
,
9471 /* labeled-unicast routes live in the unicast table */
9472 else if (safi
== SAFI_LABELED_UNICAST
)
9473 safi
= SAFI_UNICAST
;
9475 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9476 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9479 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9480 safi_t safi
, bool use_json
)
9482 struct listnode
*node
, *nnode
;
9485 bool route_output
= false;
9488 vty_out(vty
, "{\n");
9490 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9491 route_output
= true;
9494 vty_out(vty
, ",\n");
9498 vty_out(vty
, "\"%s\":",
9499 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9503 vty_out(vty
, "\nInstance %s:\n",
9504 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9508 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9513 vty_out(vty
, "}\n");
9514 else if (!route_output
)
9515 vty_out(vty
, "%% BGP instance not found\n");
9518 /* Header of detailed BGP route information */
9519 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9520 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9521 afi_t afi
, safi_t safi
, json_object
*json
)
9523 struct bgp_path_info
*pi
;
9526 struct listnode
*node
, *nnode
;
9527 char buf1
[RD_ADDRSTRLEN
];
9528 char buf2
[INET6_ADDRSTRLEN
];
9529 char buf3
[EVPN_ROUTE_STRLEN
];
9530 char prefix_str
[BUFSIZ
];
9535 int route_filter_translated_v4
= 0;
9536 int route_filter_v4
= 0;
9537 int route_filter_translated_v6
= 0;
9538 int route_filter_v6
= 0;
9541 int accept_own_nexthop
= 0;
9544 int no_advertise
= 0;
9548 int has_valid_label
= 0;
9549 mpls_label_t label
= 0;
9550 json_object
*json_adv_to
= NULL
;
9553 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9555 if (has_valid_label
)
9556 label
= label_pton(&rn
->local_label
);
9558 if (safi
== SAFI_EVPN
) {
9561 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9562 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9563 : "", prd
? ":" : "",
9564 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9565 buf3
, sizeof(buf3
)));
9567 json_object_string_add(json
, "rd",
9568 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9570 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9574 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9575 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9576 ? prefix_rd2str(prd
, buf1
,
9579 safi
== SAFI_MPLS_VPN
? ":" : "",
9580 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9585 json_object_string_add(json
, "prefix",
9586 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9589 if (has_valid_label
) {
9591 json_object_int_add(json
, "localLabel", label
);
9593 vty_out(vty
, "Local label: %d\n", label
);
9597 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9598 vty_out(vty
, "not allocated\n");
9600 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9602 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9604 if (pi
->extra
&& pi
->extra
->suppress
)
9607 if (pi
->attr
->community
== NULL
)
9610 no_advertise
+= community_include(
9611 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9612 no_export
+= community_include(pi
->attr
->community
,
9613 COMMUNITY_NO_EXPORT
);
9614 local_as
+= community_include(pi
->attr
->community
,
9615 COMMUNITY_LOCAL_AS
);
9616 accept_own
+= community_include(pi
->attr
->community
,
9617 COMMUNITY_ACCEPT_OWN
);
9618 route_filter_translated_v4
+= community_include(
9619 pi
->attr
->community
,
9620 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9621 route_filter_translated_v6
+= community_include(
9622 pi
->attr
->community
,
9623 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9624 route_filter_v4
+= community_include(
9625 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9626 route_filter_v6
+= community_include(
9627 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9628 llgr_stale
+= community_include(pi
->attr
->community
,
9629 COMMUNITY_LLGR_STALE
);
9630 no_llgr
+= community_include(pi
->attr
->community
,
9632 accept_own_nexthop
+=
9633 community_include(pi
->attr
->community
,
9634 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9635 blackhole
+= community_include(pi
->attr
->community
,
9636 COMMUNITY_BLACKHOLE
);
9637 no_peer
+= community_include(pi
->attr
->community
,
9643 vty_out(vty
, "Paths: (%d available", count
);
9645 vty_out(vty
, ", best #%d", best
);
9646 if (safi
== SAFI_UNICAST
) {
9647 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9648 vty_out(vty
, ", table %s",
9651 vty_out(vty
, ", vrf %s",
9655 vty_out(vty
, ", no best path");
9659 ", accept own local route exported and imported in different VRF");
9660 else if (route_filter_translated_v4
)
9662 ", mark translated RTs for VPNv4 route filtering");
9663 else if (route_filter_v4
)
9665 ", attach RT as-is for VPNv4 route filtering");
9666 else if (route_filter_translated_v6
)
9668 ", mark translated RTs for VPNv6 route filtering");
9669 else if (route_filter_v6
)
9671 ", attach RT as-is for VPNv6 route filtering");
9672 else if (llgr_stale
)
9674 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9677 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9678 else if (accept_own_nexthop
)
9680 ", accept local nexthop");
9682 vty_out(vty
, ", inform peer to blackhole prefix");
9684 vty_out(vty
, ", not advertised to EBGP peer");
9685 else if (no_advertise
)
9686 vty_out(vty
, ", not advertised to any peer");
9688 vty_out(vty
, ", not advertised outside local AS");
9691 ", inform EBGP peer not to advertise to their EBGP peers");
9695 ", Advertisements suppressed by an aggregate.");
9696 vty_out(vty
, ")\n");
9699 /* If we are not using addpath then we can display Advertised to and
9701 * show what peers we advertised the bestpath to. If we are using
9703 * though then we must display Advertised to on a path-by-path basis. */
9704 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9705 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9706 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9707 if (json
&& !json_adv_to
)
9708 json_adv_to
= json_object_new_object();
9710 route_vty_out_advertised_to(
9712 " Advertised to non peer-group peers:\n ",
9719 json_object_object_add(json
, "advertisedTo",
9724 vty_out(vty
, " Not advertised to any peer");
9730 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
9731 struct bgp_node
*bgp_node
, struct vty
*vty
,
9732 struct bgp
*bgp
, afi_t afi
,
9733 safi_t safi
, json_object
*json
,
9734 enum bgp_path_type pathtype
, int *display
)
9736 struct bgp_path_info
*pi
;
9738 char rdbuf
[RD_ADDRSTRLEN
];
9739 json_object
*json_header
= NULL
;
9740 json_object
*json_paths
= NULL
;
9742 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
9745 if (json
&& !json_paths
) {
9746 /* Instantiate json_paths only if path is valid */
9747 json_paths
= json_object_new_array();
9749 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
9750 json_header
= json_object_new_object();
9756 route_vty_out_detail_header(
9757 vty
, bgp
, bgp_node
, pfx_rd
,
9758 AFI_IP
, safi
, json_header
);
9763 if (pathtype
== BGP_PATH_SHOW_ALL
9764 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9765 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
9766 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9767 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
9768 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
9769 route_vty_out_detail(vty
, bgp
, bgp_node
,
9774 if (json
&& json_paths
) {
9775 json_object_object_add(json_header
, "paths", json_paths
);
9778 json_object_object_add(json
, rdbuf
, json_header
);
9782 /* Display specified route of BGP table. */
9783 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9784 struct bgp_table
*rib
, const char *ip_str
,
9785 afi_t afi
, safi_t safi
,
9786 struct prefix_rd
*prd
, int prefix_check
,
9787 enum bgp_path_type pathtype
, bool use_json
)
9791 struct prefix match
;
9792 struct bgp_node
*rn
;
9793 struct bgp_node
*rm
;
9794 struct bgp_table
*table
;
9795 json_object
*json
= NULL
;
9796 json_object
*json_paths
= NULL
;
9798 /* Check IP address argument. */
9799 ret
= str2prefix(ip_str
, &match
);
9801 vty_out(vty
, "address is malformed\n");
9805 match
.family
= afi2family(afi
);
9808 json
= json_object_new_object();
9810 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
9811 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9812 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9814 table
= bgp_node_get_bgp_table_info(rn
);
9818 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9822 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9823 bgp_unlock_node(rm
);
9827 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9828 vty
, bgp
, afi
, safi
, json
,
9829 pathtype
, &display
);
9831 bgp_unlock_node(rm
);
9833 } else if (safi
== SAFI_EVPN
) {
9834 struct bgp_node
*longest_pfx
;
9835 bool is_exact_pfxlen_match
= FALSE
;
9837 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9838 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9840 table
= bgp_node_get_bgp_table_info(rn
);
9845 is_exact_pfxlen_match
= FALSE
;
9847 * Search through all the prefixes for a match. The
9848 * pfx's are enumerated in ascending order of pfxlens.
9849 * So, the last pfx match is the longest match. Set
9850 * is_exact_pfxlen_match when we get exact pfxlen match
9852 for (rm
= bgp_table_top(table
); rm
;
9853 rm
= bgp_route_next(rm
)) {
9855 * Get prefixlen of the ip-prefix within type5
9858 if (evpn_type5_prefix_match(&rm
->p
,
9859 &match
) && rm
->info
) {
9862 bgp_evpn_get_type5_prefixlen(&rm
->p
);
9863 if (type5_pfxlen
== match
.prefixlen
) {
9864 is_exact_pfxlen_match
= TRUE
;
9865 bgp_unlock_node(rm
);
9874 if (prefix_check
&& !is_exact_pfxlen_match
)
9880 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9881 vty
, bgp
, afi
, safi
, json
,
9882 pathtype
, &display
);
9884 bgp_unlock_node(rm
);
9886 } else if (safi
== SAFI_FLOWSPEC
) {
9888 json_paths
= json_object_new_array();
9890 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9891 &match
, prefix_check
,
9895 if (use_json
&& display
)
9896 json_object_object_add(json
, "paths", json_paths
);
9898 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9900 || rn
->p
.prefixlen
== match
.prefixlen
) {
9901 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
9903 pathtype
, &display
);
9906 bgp_unlock_node(rn
);
9911 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9912 json
, JSON_C_TO_STRING_PRETTY
|
9913 JSON_C_TO_STRING_NOSLASHESCAPE
));
9914 json_object_free(json
);
9917 vty_out(vty
, "%% Network not in table\n");
9925 /* Display specified route of Main RIB */
9926 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9927 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9928 int prefix_check
, enum bgp_path_type pathtype
,
9932 bgp
= bgp_get_default();
9935 vty_out(vty
, "No BGP process is configured\n");
9937 vty_out(vty
, "{}\n");
9942 /* labeled-unicast routes live in the unicast table */
9943 if (safi
== SAFI_LABELED_UNICAST
)
9944 safi
= SAFI_UNICAST
;
9946 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9947 afi
, safi
, prd
, prefix_check
, pathtype
,
9951 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9952 struct cmd_token
**argv
, bool exact
, afi_t afi
,
9953 safi_t safi
, bool uj
)
9955 struct lcommunity
*lcom
;
9961 b
= buffer_new(1024);
9962 for (i
= 0; i
< argc
; i
++) {
9964 buffer_putc(b
, ' ');
9966 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9968 buffer_putstr(b
, argv
[i
]->arg
);
9972 buffer_putc(b
, '\0');
9974 str
= buffer_getstr(b
);
9977 lcom
= lcommunity_str2com(str
);
9978 XFREE(MTYPE_TMP
, str
);
9980 vty_out(vty
, "%% Large-community malformed\n");
9984 return bgp_show(vty
, bgp
, afi
, safi
,
9985 (exact
? bgp_show_type_lcommunity_exact
9986 : bgp_show_type_lcommunity
),
9990 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9991 const char *lcom
, bool exact
, afi_t afi
,
9992 safi_t safi
, bool uj
)
9994 struct community_list
*list
;
9996 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9997 LARGE_COMMUNITY_LIST_MASTER
);
9999 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10001 return CMD_WARNING
;
10004 return bgp_show(vty
, bgp
, afi
, safi
,
10005 (exact
? bgp_show_type_lcommunity_list_exact
10006 : bgp_show_type_lcommunity_list
),
10010 DEFUN (show_ip_bgp_large_community_list
,
10011 show_ip_bgp_large_community_list_cmd
,
10012 "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]",
10016 BGP_INSTANCE_HELP_STR
10018 BGP_SAFI_WITH_LABEL_HELP_STR
10019 "Display routes matching the large-community-list\n"
10020 "large-community-list number\n"
10021 "large-community-list name\n"
10022 "Exact match of the large-communities\n"
10026 afi_t afi
= AFI_IP6
;
10027 safi_t safi
= SAFI_UNICAST
;
10029 bool exact_match
= 0;
10031 if (argv_find(argv
, argc
, "ip", &idx
))
10033 if (argv_find(argv
, argc
, "view", &idx
)
10034 || argv_find(argv
, argc
, "vrf", &idx
))
10035 vrf
= argv
[++idx
]->arg
;
10036 if (argv_find(argv
, argc
, "ipv4", &idx
)
10037 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10038 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10039 if (argv_find(argv
, argc
, "unicast", &idx
)
10040 || argv_find(argv
, argc
, "multicast", &idx
))
10041 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10044 bool uj
= use_json(argc
, argv
);
10046 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10048 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10049 return CMD_WARNING
;
10052 argv_find(argv
, argc
, "large-community-list", &idx
);
10054 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10056 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10059 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10060 exact_match
, afi
, safi
, uj
);
10062 DEFUN (show_ip_bgp_large_community
,
10063 show_ip_bgp_large_community_cmd
,
10064 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10068 BGP_INSTANCE_HELP_STR
10070 BGP_SAFI_WITH_LABEL_HELP_STR
10071 "Display routes matching the large-communities\n"
10072 "List of large-community numbers\n"
10073 "Exact match of the large-communities\n"
10077 afi_t afi
= AFI_IP6
;
10078 safi_t safi
= SAFI_UNICAST
;
10080 bool exact_match
= 0;
10082 if (argv_find(argv
, argc
, "ip", &idx
))
10084 if (argv_find(argv
, argc
, "view", &idx
)
10085 || argv_find(argv
, argc
, "vrf", &idx
))
10086 vrf
= argv
[++idx
]->arg
;
10087 if (argv_find(argv
, argc
, "ipv4", &idx
)
10088 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10089 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10090 if (argv_find(argv
, argc
, "unicast", &idx
)
10091 || argv_find(argv
, argc
, "multicast", &idx
))
10092 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10095 bool uj
= use_json(argc
, argv
);
10097 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10099 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10100 return CMD_WARNING
;
10103 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10104 if (argv_find(argv
, argc
, "exact-match", &idx
))
10106 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10107 exact_match
, afi
, safi
, uj
);
10109 return bgp_show(vty
, bgp
, afi
, safi
,
10110 bgp_show_type_lcommunity_all
, NULL
, uj
);
10113 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10117 /* BGP route print out function without JSON */
10118 DEFUN (show_ip_bgp
,
10120 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10121 <dampening <parameters>\
10126 |community-list <(1-500)|WORD> [exact-match]\
10127 |A.B.C.D/M longer-prefixes\
10128 |X:X::X:X/M longer-prefixes\
10133 BGP_INSTANCE_HELP_STR
10135 BGP_SAFI_WITH_LABEL_HELP_STR
10136 "Display detailed information about dampening\n"
10137 "Display detail of configured dampening parameters\n"
10138 "Display routes matching the route-map\n"
10139 "A route-map to match on\n"
10140 "Display routes conforming to the prefix-list\n"
10141 "Prefix-list name\n"
10142 "Display routes conforming to the filter-list\n"
10143 "Regular expression access list name\n"
10144 "BGP RIB advertisement statistics\n"
10145 "Display routes matching the community-list\n"
10146 "community-list number\n"
10147 "community-list name\n"
10148 "Exact match of the communities\n"
10150 "Display route and more specific routes\n"
10152 "Display route and more specific routes\n")
10154 afi_t afi
= AFI_IP6
;
10155 safi_t safi
= SAFI_UNICAST
;
10156 int exact_match
= 0;
10157 struct bgp
*bgp
= NULL
;
10160 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10163 return CMD_WARNING
;
10165 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10166 if (argv_find(argv
, argc
, "parameters", &idx
))
10167 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10170 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10171 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10172 safi
, bgp_show_type_prefix_list
);
10174 if (argv_find(argv
, argc
, "filter-list", &idx
))
10175 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10176 safi
, bgp_show_type_filter_list
);
10178 if (argv_find(argv
, argc
, "statistics", &idx
))
10179 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10181 if (argv_find(argv
, argc
, "route-map", &idx
))
10182 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10183 safi
, bgp_show_type_route_map
);
10185 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10186 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10187 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10189 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10190 exact_match
, afi
, safi
);
10192 /* prefix-longer */
10193 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10194 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10195 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10197 bgp_show_type_prefix_longer
);
10199 return CMD_WARNING
;
10202 /* BGP route print out function with JSON */
10203 DEFUN (show_ip_bgp_json
,
10204 show_ip_bgp_json_cmd
,
10205 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10207 |dampening <flap-statistics|dampened-paths>\
10208 |community [AA:NN|local-AS|no-advertise|no-export\
10209 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10210 |accept-own|accept-own-nexthop|route-filter-v6\
10211 |route-filter-v4|route-filter-translated-v6\
10212 |route-filter-translated-v4] [exact-match]\
10217 BGP_INSTANCE_HELP_STR
10219 BGP_SAFI_WITH_LABEL_HELP_STR
10220 "Display only routes with non-natural netmasks\n"
10221 "Display detailed information about dampening\n"
10222 "Display flap statistics of routes\n"
10223 "Display paths suppressed due to dampening\n"
10224 "Display routes matching the communities\n"
10226 "Do not send outside local AS (well-known community)\n"
10227 "Do not advertise to any peer (well-known community)\n"
10228 "Do not export to next AS (well-known community)\n"
10229 "Graceful shutdown (well-known community)\n"
10230 "Do not export to any peer (well-known community)\n"
10231 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10232 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10233 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10234 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10235 "Should accept VPN route with local nexthop (well-known community)\n"
10236 "RT VPNv6 route filtering (well-known community)\n"
10237 "RT VPNv4 route filtering (well-known community)\n"
10238 "RT translated VPNv6 route filtering (well-known community)\n"
10239 "RT translated VPNv4 route filtering (well-known community)\n"
10240 "Exact match of the communities\n"
10243 afi_t afi
= AFI_IP6
;
10244 safi_t safi
= SAFI_UNICAST
;
10245 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10246 struct bgp
*bgp
= NULL
;
10248 int exact_match
= 0;
10249 bool uj
= use_json(argc
, argv
);
10254 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10257 return CMD_WARNING
;
10259 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10260 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10263 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10264 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10265 return bgp_show(vty
, bgp
, afi
, safi
,
10266 bgp_show_type_dampend_paths
, NULL
, uj
);
10267 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10268 return bgp_show(vty
, bgp
, afi
, safi
,
10269 bgp_show_type_flap_statistics
, NULL
,
10273 if (argv_find(argv
, argc
, "community", &idx
)) {
10274 char *maybecomm
= NULL
;
10275 char *community
= NULL
;
10277 if (idx
+ 1 < argc
) {
10278 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10279 maybecomm
= argv
[idx
+ 1]->arg
;
10281 maybecomm
= argv
[idx
+ 1]->text
;
10284 if (maybecomm
&& !strmatch(maybecomm
, "json")
10285 && !strmatch(maybecomm
, "exact-match"))
10286 community
= maybecomm
;
10288 if (argv_find(argv
, argc
, "exact-match", &idx
))
10292 return bgp_show_community(vty
, bgp
, community
,
10293 exact_match
, afi
, safi
, uj
);
10295 return (bgp_show(vty
, bgp
, afi
, safi
,
10296 bgp_show_type_community_all
, NULL
,
10300 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10303 DEFUN (show_ip_bgp_route
,
10304 show_ip_bgp_route_cmd
,
10305 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10306 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10310 BGP_INSTANCE_HELP_STR
10312 BGP_SAFI_WITH_LABEL_HELP_STR
10313 "Network in the BGP routing table to display\n"
10315 "Network in the BGP routing table to display\n"
10317 "Display only the bestpath\n"
10318 "Display only multipaths\n"
10321 int prefix_check
= 0;
10323 afi_t afi
= AFI_IP6
;
10324 safi_t safi
= SAFI_UNICAST
;
10325 char *prefix
= NULL
;
10326 struct bgp
*bgp
= NULL
;
10327 enum bgp_path_type path_type
;
10328 bool uj
= use_json(argc
, argv
);
10332 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10335 return CMD_WARNING
;
10339 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10340 return CMD_WARNING
;
10343 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10344 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10345 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10347 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10348 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10351 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10352 && afi
!= AFI_IP6
) {
10354 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10355 return CMD_WARNING
;
10357 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10358 && afi
!= AFI_IP
) {
10360 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10361 return CMD_WARNING
;
10364 prefix
= argv
[idx
]->arg
;
10366 /* [<bestpath|multipath>] */
10367 if (argv_find(argv
, argc
, "bestpath", &idx
))
10368 path_type
= BGP_PATH_SHOW_BESTPATH
;
10369 else if (argv_find(argv
, argc
, "multipath", &idx
))
10370 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10372 path_type
= BGP_PATH_SHOW_ALL
;
10374 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10378 DEFUN (show_ip_bgp_regexp
,
10379 show_ip_bgp_regexp_cmd
,
10380 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10384 BGP_INSTANCE_HELP_STR
10386 BGP_SAFI_WITH_LABEL_HELP_STR
10387 "Display routes matching the AS path regular expression\n"
10388 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10390 afi_t afi
= AFI_IP6
;
10391 safi_t safi
= SAFI_UNICAST
;
10392 struct bgp
*bgp
= NULL
;
10395 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10398 return CMD_WARNING
;
10400 // get index of regex
10401 argv_find(argv
, argc
, "regexp", &idx
);
10404 char *regstr
= argv_concat(argv
, argc
, idx
);
10405 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10406 bgp_show_type_regexp
);
10407 XFREE(MTYPE_TMP
, regstr
);
10411 DEFUN (show_ip_bgp_instance_all
,
10412 show_ip_bgp_instance_all_cmd
,
10413 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10417 BGP_INSTANCE_ALL_HELP_STR
10419 BGP_SAFI_WITH_LABEL_HELP_STR
10422 afi_t afi
= AFI_IP
;
10423 safi_t safi
= SAFI_UNICAST
;
10424 struct bgp
*bgp
= NULL
;
10426 bool uj
= use_json(argc
, argv
);
10431 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10434 return CMD_WARNING
;
10436 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10437 return CMD_SUCCESS
;
10440 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10441 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10446 if (!config_bgp_aspath_validate(regstr
)) {
10447 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10449 return CMD_WARNING_CONFIG_FAILED
;
10452 regex
= bgp_regcomp(regstr
);
10454 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10455 return CMD_WARNING
;
10458 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10459 bgp_regex_free(regex
);
10463 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10464 const char *prefix_list_str
, afi_t afi
,
10465 safi_t safi
, enum bgp_show_type type
)
10467 struct prefix_list
*plist
;
10469 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10470 if (plist
== NULL
) {
10471 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10473 return CMD_WARNING
;
10476 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10479 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10480 const char *filter
, afi_t afi
, safi_t safi
,
10481 enum bgp_show_type type
)
10483 struct as_list
*as_list
;
10485 as_list
= as_list_lookup(filter
);
10486 if (as_list
== NULL
) {
10487 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10489 return CMD_WARNING
;
10492 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10495 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10496 const char *rmap_str
, afi_t afi
, safi_t safi
,
10497 enum bgp_show_type type
)
10499 struct route_map
*rmap
;
10501 rmap
= route_map_lookup_by_name(rmap_str
);
10503 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10504 return CMD_WARNING
;
10507 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10510 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10511 const char *comstr
, int exact
, afi_t afi
,
10512 safi_t safi
, bool use_json
)
10514 struct community
*com
;
10517 com
= community_str2com(comstr
);
10519 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10520 return CMD_WARNING
;
10523 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10524 (exact
? bgp_show_type_community_exact
10525 : bgp_show_type_community
),
10527 community_free(&com
);
10532 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10533 const char *com
, int exact
, afi_t afi
,
10536 struct community_list
*list
;
10538 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10539 if (list
== NULL
) {
10540 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10541 return CMD_WARNING
;
10544 return bgp_show(vty
, bgp
, afi
, safi
,
10545 (exact
? bgp_show_type_community_list_exact
10546 : bgp_show_type_community_list
),
10550 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10551 const char *prefix
, afi_t afi
, safi_t safi
,
10552 enum bgp_show_type type
)
10559 ret
= str2prefix(prefix
, p
);
10561 vty_out(vty
, "%% Malformed Prefix\n");
10562 return CMD_WARNING
;
10565 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10571 BGP_STATS_MAXBITLEN
= 0,
10573 BGP_STATS_PREFIXES
,
10575 BGP_STATS_UNAGGREGATEABLE
,
10576 BGP_STATS_MAX_AGGREGATEABLE
,
10577 BGP_STATS_AGGREGATES
,
10579 BGP_STATS_ASPATH_COUNT
,
10580 BGP_STATS_ASPATH_MAXHOPS
,
10581 BGP_STATS_ASPATH_TOTHOPS
,
10582 BGP_STATS_ASPATH_MAXSIZE
,
10583 BGP_STATS_ASPATH_TOTSIZE
,
10584 BGP_STATS_ASN_HIGHEST
,
10588 static const char *table_stats_strs
[] = {
10589 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10590 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10591 [BGP_STATS_RIB
] = "Total Advertisements",
10592 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10593 [BGP_STATS_MAX_AGGREGATEABLE
] =
10594 "Maximum aggregateable prefixes",
10595 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10596 [BGP_STATS_SPACE
] = "Address space advertised",
10597 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10598 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10599 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10600 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10601 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10602 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10603 [BGP_STATS_MAX
] = NULL
,
10606 struct bgp_table_stats
{
10607 struct bgp_table
*table
;
10608 unsigned long long counts
[BGP_STATS_MAX
];
10609 double total_space
;
10613 #define TALLY_SIGFIG 100000
10614 static unsigned long
10615 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10617 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10618 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10619 unsigned long ret
= newtot
/ count
;
10621 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10628 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10629 struct bgp_table_stats
*ts
, unsigned int space
)
10631 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10632 struct bgp_path_info
*pi
;
10637 if (!bgp_node_has_bgp_path_info_data(rn
))
10640 ts
->counts
[BGP_STATS_PREFIXES
]++;
10641 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10644 ts
->counts
[BGP_STATS_AVGPLEN
]
10645 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10646 ts
->counts
[BGP_STATS_AVGPLEN
],
10650 /* check if the prefix is included by any other announcements */
10651 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10652 prn
= bgp_node_parent_nolock(prn
);
10654 if (prn
== NULL
|| prn
== top
) {
10655 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10656 /* announced address space */
10658 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10659 } else if (bgp_node_has_bgp_path_info_data(prn
))
10660 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10663 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10664 ts
->counts
[BGP_STATS_RIB
]++;
10666 if (CHECK_FLAG(pi
->attr
->flag
,
10667 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
10668 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10670 /* as-path stats */
10671 if (pi
->attr
->aspath
) {
10672 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10673 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10674 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10676 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10678 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10679 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10681 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10682 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10684 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10685 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10687 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10688 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10689 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10691 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10692 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10693 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10696 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10697 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10702 static int bgp_table_stats_walker(struct thread
*t
)
10704 struct bgp_node
*rn
, *nrn
;
10705 struct bgp_node
*top
;
10706 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10707 unsigned int space
= 0;
10709 if (!(top
= bgp_table_top(ts
->table
)))
10712 switch (ts
->table
->afi
) {
10714 space
= IPV4_MAX_BITLEN
;
10717 space
= IPV6_MAX_BITLEN
;
10723 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10725 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10726 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10727 struct bgp_table
*table
;
10729 table
= bgp_node_get_bgp_table_info(rn
);
10733 top
= bgp_table_top(table
);
10734 for (nrn
= bgp_table_top(table
); nrn
;
10735 nrn
= bgp_route_next(nrn
))
10736 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10738 bgp_table_stats_rn(rn
, top
, ts
, space
);
10745 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10748 struct bgp_table_stats ts
;
10751 if (!bgp
->rib
[afi
][safi
]) {
10752 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10754 return CMD_WARNING
;
10757 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
10759 /* labeled-unicast routes live in the unicast table */
10760 if (safi
== SAFI_LABELED_UNICAST
)
10761 safi
= SAFI_UNICAST
;
10763 memset(&ts
, 0, sizeof(ts
));
10764 ts
.table
= bgp
->rib
[afi
][safi
];
10765 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10767 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10768 if (!table_stats_strs
[i
])
10773 case BGP_STATS_ASPATH_AVGHOPS
:
10774 case BGP_STATS_ASPATH_AVGSIZE
:
10775 case BGP_STATS_AVGPLEN
:
10776 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10777 vty_out (vty
, "%12.2f",
10778 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10781 case BGP_STATS_ASPATH_TOTHOPS
:
10782 case BGP_STATS_ASPATH_TOTSIZE
:
10783 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10784 vty_out(vty
, "%12.2f",
10786 ? (float)ts
.counts
[i
]
10788 [BGP_STATS_ASPATH_COUNT
]
10791 case BGP_STATS_TOTPLEN
:
10792 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10793 vty_out(vty
, "%12.2f",
10795 ? (float)ts
.counts
[i
]
10797 [BGP_STATS_PREFIXES
]
10800 case BGP_STATS_SPACE
:
10801 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10802 vty_out(vty
, "%12g\n", ts
.total_space
);
10804 if (afi
== AFI_IP6
) {
10805 vty_out(vty
, "%30s: ", "/32 equivalent ");
10806 vty_out(vty
, "%12g\n",
10807 ts
.total_space
* pow(2.0, -128 + 32));
10808 vty_out(vty
, "%30s: ", "/48 equivalent ");
10809 vty_out(vty
, "%12g\n",
10810 ts
.total_space
* pow(2.0, -128 + 48));
10812 vty_out(vty
, "%30s: ", "% announced ");
10813 vty_out(vty
, "%12.2f\n",
10814 ts
.total_space
* 100. * pow(2.0, -32));
10815 vty_out(vty
, "%30s: ", "/8 equivalent ");
10816 vty_out(vty
, "%12.2f\n",
10817 ts
.total_space
* pow(2.0, -32 + 8));
10818 vty_out(vty
, "%30s: ", "/24 equivalent ");
10819 vty_out(vty
, "%12.2f\n",
10820 ts
.total_space
* pow(2.0, -32 + 24));
10824 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10825 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10828 vty_out(vty
, "\n");
10830 return CMD_SUCCESS
;
10842 PCOUNT_PFCNT
, /* the figure we display to users */
10846 static const char *pcount_strs
[] = {
10847 [PCOUNT_ADJ_IN
] = "Adj-in",
10848 [PCOUNT_DAMPED
] = "Damped",
10849 [PCOUNT_REMOVED
] = "Removed",
10850 [PCOUNT_HISTORY
] = "History",
10851 [PCOUNT_STALE
] = "Stale",
10852 [PCOUNT_VALID
] = "Valid",
10853 [PCOUNT_ALL
] = "All RIB",
10854 [PCOUNT_COUNTED
] = "PfxCt counted",
10855 [PCOUNT_PFCNT
] = "Useable",
10856 [PCOUNT_MAX
] = NULL
,
10859 struct peer_pcounts
{
10860 unsigned int count
[PCOUNT_MAX
];
10861 const struct peer
*peer
;
10862 const struct bgp_table
*table
;
10865 static int bgp_peer_count_walker(struct thread
*t
)
10867 struct bgp_node
*rn
;
10868 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10869 const struct peer
*peer
= pc
->peer
;
10871 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10872 struct bgp_adj_in
*ain
;
10873 struct bgp_path_info
*pi
;
10875 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10876 if (ain
->peer
== peer
)
10877 pc
->count
[PCOUNT_ADJ_IN
]++;
10879 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10881 if (pi
->peer
!= peer
)
10884 pc
->count
[PCOUNT_ALL
]++;
10886 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10887 pc
->count
[PCOUNT_DAMPED
]++;
10888 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10889 pc
->count
[PCOUNT_HISTORY
]++;
10890 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10891 pc
->count
[PCOUNT_REMOVED
]++;
10892 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10893 pc
->count
[PCOUNT_STALE
]++;
10894 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10895 pc
->count
[PCOUNT_VALID
]++;
10896 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10897 pc
->count
[PCOUNT_PFCNT
]++;
10899 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10900 pc
->count
[PCOUNT_COUNTED
]++;
10901 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10903 EC_LIB_DEVELOPMENT
,
10904 "Attempting to count but flags say it is unusable");
10906 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10908 EC_LIB_DEVELOPMENT
,
10909 "Not counted but flags say we should");
10916 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10917 safi_t safi
, bool use_json
)
10919 struct peer_pcounts pcounts
= {.peer
= peer
};
10921 json_object
*json
= NULL
;
10922 json_object
*json_loop
= NULL
;
10925 json
= json_object_new_object();
10926 json_loop
= json_object_new_object();
10929 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10930 || !peer
->bgp
->rib
[afi
][safi
]) {
10932 json_object_string_add(
10934 "No such neighbor or address family");
10935 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10936 json_object_free(json
);
10938 vty_out(vty
, "%% No such neighbor or address family\n");
10940 return CMD_WARNING
;
10943 memset(&pcounts
, 0, sizeof(pcounts
));
10944 pcounts
.peer
= peer
;
10945 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10947 /* in-place call via thread subsystem so as to record execution time
10948 * stats for the thread-walk (i.e. ensure this can't be blamed on
10949 * on just vty_read()).
10951 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10954 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10955 json_object_string_add(json
, "multiProtocol",
10956 get_afi_safi_str(afi
, safi
, true));
10957 json_object_int_add(json
, "pfxCounter",
10958 peer
->pcount
[afi
][safi
]);
10960 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10961 json_object_int_add(json_loop
, pcount_strs
[i
],
10964 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10966 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10967 json_object_string_add(json
, "pfxctDriftFor",
10969 json_object_string_add(
10970 json
, "recommended",
10971 "Please report this bug, with the above command output");
10973 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10974 json
, JSON_C_TO_STRING_PRETTY
));
10975 json_object_free(json
);
10979 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10980 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10981 peer
->hostname
, peer
->host
,
10982 get_afi_safi_str(afi
, safi
, false));
10984 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10985 get_afi_safi_str(afi
, safi
, false));
10988 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
10989 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10991 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10992 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10995 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10996 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10998 "Please report this bug, with the above command output\n");
11002 return CMD_SUCCESS
;
11005 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11006 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11007 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11008 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11012 BGP_INSTANCE_HELP_STR
11015 "Detailed information on TCP and BGP neighbor connections\n"
11016 "Neighbor to display information about\n"
11017 "Neighbor to display information about\n"
11018 "Neighbor on BGP configured interface\n"
11019 "Display detailed prefix count information\n"
11022 afi_t afi
= AFI_IP6
;
11023 safi_t safi
= SAFI_UNICAST
;
11026 struct bgp
*bgp
= NULL
;
11027 bool uj
= use_json(argc
, argv
);
11032 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11035 return CMD_WARNING
;
11037 argv_find(argv
, argc
, "neighbors", &idx
);
11038 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11040 return CMD_WARNING
;
11042 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11045 #ifdef KEEP_OLD_VPN_COMMANDS
11046 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11047 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11048 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11053 "Display information about all VPNv4 NLRIs\n"
11054 "Detailed information on TCP and BGP neighbor connections\n"
11055 "Neighbor to display information about\n"
11056 "Neighbor to display information about\n"
11057 "Neighbor on BGP configured interface\n"
11058 "Display detailed prefix count information\n"
11063 bool uj
= use_json(argc
, argv
);
11065 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11067 return CMD_WARNING
;
11069 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11072 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11073 show_ip_bgp_vpn_all_route_prefix_cmd
,
11074 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11079 "Display information about all VPNv4 NLRIs\n"
11080 "Network in the BGP routing table to display\n"
11081 "Network in the BGP routing table to display\n"
11085 char *network
= NULL
;
11086 struct bgp
*bgp
= bgp_get_default();
11088 vty_out(vty
, "Can't find default instance\n");
11089 return CMD_WARNING
;
11092 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11093 network
= argv
[idx
]->arg
;
11094 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11095 network
= argv
[idx
]->arg
;
11097 vty_out(vty
, "Unable to figure out Network\n");
11098 return CMD_WARNING
;
11101 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11102 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11104 #endif /* KEEP_OLD_VPN_COMMANDS */
11106 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11107 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11108 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11113 "Network in the BGP routing table to display\n"
11114 "Network in the BGP routing table to display\n"
11115 "Network in the BGP routing table to display\n"
11116 "Network in the BGP routing table to display\n"
11120 char *network
= NULL
;
11121 int prefix_check
= 0;
11123 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11124 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11125 network
= argv
[idx
]->arg
;
11126 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11127 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11128 network
= argv
[idx
]->arg
;
11131 vty_out(vty
, "Unable to figure out Network\n");
11132 return CMD_WARNING
;
11134 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11135 prefix_check
, BGP_PATH_SHOW_ALL
,
11136 use_json(argc
, argv
));
11139 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11140 safi_t safi
, enum bgp_show_adj_route_type type
,
11141 const char *rmap_name
, bool use_json
,
11144 struct bgp_table
*table
;
11145 struct bgp_adj_in
*ain
;
11146 struct bgp_adj_out
*adj
;
11147 unsigned long output_count
;
11148 unsigned long filtered_count
;
11149 struct bgp_node
*rn
;
11155 struct update_subgroup
*subgrp
;
11156 json_object
*json_scode
= NULL
;
11157 json_object
*json_ocode
= NULL
;
11158 json_object
*json_ar
= NULL
;
11159 struct peer_af
*paf
;
11160 bool route_filtered
;
11163 json_scode
= json_object_new_object();
11164 json_ocode
= json_object_new_object();
11165 json_ar
= json_object_new_object();
11167 json_object_string_add(json_scode
, "suppressed", "s");
11168 json_object_string_add(json_scode
, "damped", "d");
11169 json_object_string_add(json_scode
, "history", "h");
11170 json_object_string_add(json_scode
, "valid", "*");
11171 json_object_string_add(json_scode
, "best", ">");
11172 json_object_string_add(json_scode
, "multipath", "=");
11173 json_object_string_add(json_scode
, "internal", "i");
11174 json_object_string_add(json_scode
, "ribFailure", "r");
11175 json_object_string_add(json_scode
, "stale", "S");
11176 json_object_string_add(json_scode
, "removed", "R");
11178 json_object_string_add(json_ocode
, "igp", "i");
11179 json_object_string_add(json_ocode
, "egp", "e");
11180 json_object_string_add(json_ocode
, "incomplete", "?");
11187 json_object_string_add(json
, "alert", "no BGP");
11188 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11189 json_object_free(json
);
11191 vty_out(vty
, "%% No bgp\n");
11195 /* labeled-unicast routes live in the unicast table */
11196 if (safi
== SAFI_LABELED_UNICAST
)
11197 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11199 table
= bgp
->rib
[afi
][safi
];
11201 output_count
= filtered_count
= 0;
11202 subgrp
= peer_subgroup(peer
, afi
, safi
);
11204 if (type
== bgp_show_adj_route_advertised
&& subgrp
11205 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11207 json_object_int_add(json
, "bgpTableVersion",
11209 json_object_string_add(json
, "bgpLocalRouterId",
11210 inet_ntoa(bgp
->router_id
));
11211 json_object_int_add(json
, "defaultLocPrf",
11212 bgp
->default_local_pref
);
11213 json_object_int_add(json
, "localAS", bgp
->as
);
11214 json_object_object_add(json
, "bgpStatusCodes",
11216 json_object_object_add(json
, "bgpOriginCodes",
11218 json_object_string_add(
11219 json
, "bgpOriginatingDefaultNetwork",
11220 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11222 vty_out(vty
, "BGP table version is %" PRIu64
11223 ", local router ID is %s, vrf id ",
11224 table
->version
, inet_ntoa(bgp
->router_id
));
11225 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11226 vty_out(vty
, "%s", VRFID_NONE_STR
);
11228 vty_out(vty
, "%u", bgp
->vrf_id
);
11229 vty_out(vty
, "\n");
11230 vty_out(vty
, "Default local pref %u, ",
11231 bgp
->default_local_pref
);
11232 vty_out(vty
, "local AS %u\n", bgp
->as
);
11233 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11234 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11235 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11237 vty_out(vty
, "Originating default network %s\n\n",
11238 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11243 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11244 if (type
== bgp_show_adj_route_received
11245 || type
== bgp_show_adj_route_filtered
) {
11246 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11247 if (ain
->peer
!= peer
)
11252 json_object_int_add(
11253 json
, "bgpTableVersion",
11255 json_object_string_add(
11257 "bgpLocalRouterId",
11260 json_object_int_add(json
,
11262 bgp
->default_local_pref
);
11263 json_object_int_add(json
,
11264 "localAS", bgp
->as
);
11265 json_object_object_add(
11266 json
, "bgpStatusCodes",
11268 json_object_object_add(
11269 json
, "bgpOriginCodes",
11273 "BGP table version is 0, local router ID is %s, vrf id ",
11276 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11282 vty_out(vty
, "\n");
11284 "Default local pref %u, ",
11285 bgp
->default_local_pref
);
11286 vty_out(vty
, "local AS %u\n",
11289 BGP_SHOW_SCODE_HEADER
);
11291 BGP_SHOW_NCODE_HEADER
);
11293 BGP_SHOW_OCODE_HEADER
);
11299 vty_out(vty
, BGP_SHOW_HEADER
);
11303 bgp_attr_dup(&attr
, ain
->attr
);
11304 route_filtered
= false;
11306 /* Filter prefix using distribute list,
11307 * filter list or prefix list
11309 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11310 safi
)) == FILTER_DENY
)
11311 route_filtered
= true;
11313 /* Filter prefix using route-map */
11314 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11315 afi
, safi
, rmap_name
, NULL
, 0,
11318 if (type
== bgp_show_adj_route_filtered
&&
11319 !route_filtered
&& ret
!= RMAP_DENY
) {
11320 bgp_attr_undup(&attr
, ain
->attr
);
11324 if (type
== bgp_show_adj_route_received
&&
11325 (route_filtered
|| ret
== RMAP_DENY
))
11328 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11329 use_json
, json_ar
);
11330 bgp_attr_undup(&attr
, ain
->attr
);
11333 } else if (type
== bgp_show_adj_route_advertised
) {
11334 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11335 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11336 if (paf
->peer
!= peer
|| !adj
->attr
)
11341 json_object_int_add(
11345 json_object_string_add(
11347 "bgpLocalRouterId",
11350 json_object_int_add(
11351 json
, "defaultLocPrf",
11352 bgp
->default_local_pref
11354 json_object_int_add(
11357 json_object_object_add(
11361 json_object_object_add(
11367 "BGP table version is %" PRIu64
11368 ", local router ID is %s, vrf id ",
11381 vty_out(vty
, "\n");
11383 "Default local pref %u, ",
11384 bgp
->default_local_pref
11390 BGP_SHOW_SCODE_HEADER
);
11392 BGP_SHOW_NCODE_HEADER
);
11394 BGP_SHOW_OCODE_HEADER
);
11405 bgp_attr_dup(&attr
, adj
->attr
);
11406 ret
= bgp_output_modifier(
11407 peer
, &rn
->p
, &attr
, afi
, safi
,
11410 if (ret
!= RMAP_DENY
) {
11411 route_vty_out_tmp(vty
, &rn
->p
,
11420 bgp_attr_undup(&attr
, adj
->attr
);
11426 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11427 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11428 json_object_int_add(json
, "filteredPrefixCounter",
11431 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11432 json
, JSON_C_TO_STRING_PRETTY
));
11433 json_object_free(json
);
11434 } else if (output_count
> 0) {
11435 if (filtered_count
> 0)
11437 "\nTotal number of prefixes %ld (%ld filtered)\n",
11438 output_count
, filtered_count
);
11440 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11445 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11446 safi_t safi
, enum bgp_show_adj_route_type type
,
11447 const char *rmap_name
, bool use_json
)
11449 json_object
*json
= NULL
;
11452 json
= json_object_new_object();
11454 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11456 json_object_string_add(
11458 "No such neighbor or address family");
11459 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11460 json_object_free(json
);
11462 vty_out(vty
, "%% No such neighbor or address family\n");
11464 return CMD_WARNING
;
11467 if ((type
== bgp_show_adj_route_received
11468 || type
== bgp_show_adj_route_filtered
)
11469 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11470 PEER_FLAG_SOFT_RECONFIG
)) {
11472 json_object_string_add(
11474 "Inbound soft reconfiguration not enabled");
11475 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11476 json_object_free(json
);
11479 "%% Inbound soft reconfiguration not enabled\n");
11481 return CMD_WARNING
;
11484 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11486 return CMD_SUCCESS
;
11489 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11490 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11491 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11492 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11496 BGP_INSTANCE_HELP_STR
11498 BGP_SAFI_WITH_LABEL_HELP_STR
11499 "Detailed information on TCP and BGP neighbor connections\n"
11500 "Neighbor to display information about\n"
11501 "Neighbor to display information about\n"
11502 "Neighbor on BGP configured interface\n"
11503 "Display the routes advertised to a BGP neighbor\n"
11504 "Display the received routes from neighbor\n"
11505 "Display the filtered routes received from neighbor\n"
11506 "Route-map to modify the attributes\n"
11507 "Name of the route map\n"
11510 afi_t afi
= AFI_IP6
;
11511 safi_t safi
= SAFI_UNICAST
;
11512 char *rmap_name
= NULL
;
11513 char *peerstr
= NULL
;
11514 struct bgp
*bgp
= NULL
;
11516 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11518 bool uj
= use_json(argc
, argv
);
11523 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11526 return CMD_WARNING
;
11528 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11529 argv_find(argv
, argc
, "neighbors", &idx
);
11530 peerstr
= argv
[++idx
]->arg
;
11532 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11534 return CMD_WARNING
;
11536 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11537 type
= bgp_show_adj_route_advertised
;
11538 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11539 type
= bgp_show_adj_route_received
;
11540 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11541 type
= bgp_show_adj_route_filtered
;
11543 if (argv_find(argv
, argc
, "route-map", &idx
))
11544 rmap_name
= argv
[++idx
]->arg
;
11546 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11549 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11550 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11551 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11557 "Address Family modifier\n"
11558 "Detailed information on TCP and BGP neighbor connections\n"
11559 "Neighbor to display information about\n"
11560 "Neighbor to display information about\n"
11561 "Neighbor on BGP configured interface\n"
11562 "Display information received from a BGP neighbor\n"
11563 "Display the prefixlist filter\n"
11566 afi_t afi
= AFI_IP6
;
11567 safi_t safi
= SAFI_UNICAST
;
11568 char *peerstr
= NULL
;
11571 union sockunion su
;
11577 /* show [ip] bgp */
11578 if (argv_find(argv
, argc
, "ip", &idx
))
11580 /* [<ipv4|ipv6> [unicast]] */
11581 if (argv_find(argv
, argc
, "ipv4", &idx
))
11583 if (argv_find(argv
, argc
, "ipv6", &idx
))
11585 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11586 argv_find(argv
, argc
, "neighbors", &idx
);
11587 peerstr
= argv
[++idx
]->arg
;
11589 bool uj
= use_json(argc
, argv
);
11591 ret
= str2sockunion(peerstr
, &su
);
11593 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11596 vty_out(vty
, "{}\n");
11599 "%% Malformed address or name: %s\n",
11601 return CMD_WARNING
;
11604 peer
= peer_lookup(NULL
, &su
);
11607 vty_out(vty
, "{}\n");
11609 vty_out(vty
, "No peer\n");
11610 return CMD_WARNING
;
11614 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11615 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11618 vty_out(vty
, "Address Family: %s\n",
11619 get_afi_safi_str(afi
, safi
, false));
11620 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11623 vty_out(vty
, "{}\n");
11625 vty_out(vty
, "No functional output\n");
11628 return CMD_SUCCESS
;
11631 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11632 afi_t afi
, safi_t safi
,
11633 enum bgp_show_type type
, bool use_json
)
11635 /* labeled-unicast routes live in the unicast table */
11636 if (safi
== SAFI_LABELED_UNICAST
)
11637 safi
= SAFI_UNICAST
;
11639 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11641 json_object
*json_no
= NULL
;
11642 json_no
= json_object_new_object();
11643 json_object_string_add(
11644 json_no
, "warning",
11645 "No such neighbor or address family");
11646 vty_out(vty
, "%s\n",
11647 json_object_to_json_string(json_no
));
11648 json_object_free(json_no
);
11650 vty_out(vty
, "%% No such neighbor or address family\n");
11651 return CMD_WARNING
;
11654 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11657 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11658 show_ip_bgp_flowspec_routes_detailed_cmd
,
11659 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11663 BGP_INSTANCE_HELP_STR
11666 "Detailed information on flowspec entries\n"
11669 afi_t afi
= AFI_IP
;
11670 safi_t safi
= SAFI_UNICAST
;
11671 struct bgp
*bgp
= NULL
;
11673 bool uj
= use_json(argc
, argv
);
11678 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11681 return CMD_WARNING
;
11683 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11686 DEFUN (show_ip_bgp_neighbor_routes
,
11687 show_ip_bgp_neighbor_routes_cmd
,
11688 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11689 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11693 BGP_INSTANCE_HELP_STR
11695 BGP_SAFI_WITH_LABEL_HELP_STR
11696 "Detailed information on TCP and BGP neighbor connections\n"
11697 "Neighbor to display information about\n"
11698 "Neighbor to display information about\n"
11699 "Neighbor on BGP configured interface\n"
11700 "Display flap statistics of the routes learned from neighbor\n"
11701 "Display the dampened routes received from neighbor\n"
11702 "Display routes learned from neighbor\n"
11705 char *peerstr
= NULL
;
11706 struct bgp
*bgp
= NULL
;
11707 afi_t afi
= AFI_IP6
;
11708 safi_t safi
= SAFI_UNICAST
;
11710 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11712 bool uj
= use_json(argc
, argv
);
11717 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11720 return CMD_WARNING
;
11722 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11723 argv_find(argv
, argc
, "neighbors", &idx
);
11724 peerstr
= argv
[++idx
]->arg
;
11726 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11728 return CMD_WARNING
;
11730 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11731 sh_type
= bgp_show_type_flap_neighbor
;
11732 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11733 sh_type
= bgp_show_type_damp_neighbor
;
11734 else if (argv_find(argv
, argc
, "routes", &idx
))
11735 sh_type
= bgp_show_type_neighbor
;
11737 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11740 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11742 struct bgp_distance
{
11743 /* Distance value for the IP source prefix. */
11746 /* Name of the access-list to be matched. */
11750 DEFUN (show_bgp_afi_vpn_rd_route
,
11751 show_bgp_afi_vpn_rd_route_cmd
,
11752 "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]",
11756 "Address Family modifier\n"
11757 "Display information for a route distinguisher\n"
11758 "Route Distinguisher\n"
11759 "Network in the BGP routing table to display\n"
11760 "Network in the BGP routing table to display\n"
11764 struct prefix_rd prd
;
11765 afi_t afi
= AFI_MAX
;
11768 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11769 vty_out(vty
, "%% Malformed Address Family\n");
11770 return CMD_WARNING
;
11773 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11775 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11776 return CMD_WARNING
;
11779 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11780 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11783 static struct bgp_distance
*bgp_distance_new(void)
11785 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11788 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11790 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11793 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11794 const char *ip_str
, const char *access_list_str
)
11801 struct bgp_node
*rn
;
11802 struct bgp_distance
*bdistance
;
11804 afi
= bgp_node_afi(vty
);
11805 safi
= bgp_node_safi(vty
);
11807 ret
= str2prefix(ip_str
, &p
);
11809 vty_out(vty
, "Malformed prefix\n");
11810 return CMD_WARNING_CONFIG_FAILED
;
11813 distance
= atoi(distance_str
);
11815 /* Get BGP distance node. */
11816 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11817 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11819 bgp_unlock_node(rn
);
11821 bdistance
= bgp_distance_new();
11822 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11825 /* Set distance value. */
11826 bdistance
->distance
= distance
;
11828 /* Reset access-list configuration. */
11829 if (bdistance
->access_list
) {
11830 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11831 bdistance
->access_list
= NULL
;
11833 if (access_list_str
)
11834 bdistance
->access_list
=
11835 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11837 return CMD_SUCCESS
;
11840 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11841 const char *ip_str
, const char *access_list_str
)
11848 struct bgp_node
*rn
;
11849 struct bgp_distance
*bdistance
;
11851 afi
= bgp_node_afi(vty
);
11852 safi
= bgp_node_safi(vty
);
11854 ret
= str2prefix(ip_str
, &p
);
11856 vty_out(vty
, "Malformed prefix\n");
11857 return CMD_WARNING_CONFIG_FAILED
;
11860 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11861 (struct prefix
*)&p
);
11863 vty_out(vty
, "Can't find specified prefix\n");
11864 return CMD_WARNING_CONFIG_FAILED
;
11867 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11868 distance
= atoi(distance_str
);
11870 if (bdistance
->distance
!= distance
) {
11871 vty_out(vty
, "Distance does not match configured\n");
11872 return CMD_WARNING_CONFIG_FAILED
;
11875 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11876 bgp_distance_free(bdistance
);
11878 bgp_node_set_bgp_path_info(rn
, NULL
);
11879 bgp_unlock_node(rn
);
11880 bgp_unlock_node(rn
);
11882 return CMD_SUCCESS
;
11885 /* Apply BGP information to distance method. */
11886 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11887 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11889 struct bgp_node
*rn
;
11892 struct bgp_distance
*bdistance
;
11893 struct access_list
*alist
;
11894 struct bgp_static
*bgp_static
;
11899 peer
= pinfo
->peer
;
11901 if (pinfo
->attr
->distance
)
11902 return pinfo
->attr
->distance
;
11904 /* Check source address. */
11905 sockunion2hostprefix(&peer
->su
, &q
);
11906 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11908 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11909 bgp_unlock_node(rn
);
11911 if (bdistance
->access_list
) {
11912 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11914 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11915 return bdistance
->distance
;
11917 return bdistance
->distance
;
11920 /* Backdoor check. */
11921 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11923 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11924 bgp_unlock_node(rn
);
11926 if (bgp_static
->backdoor
) {
11927 if (bgp
->distance_local
[afi
][safi
])
11928 return bgp
->distance_local
[afi
][safi
];
11930 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11934 if (peer
->sort
== BGP_PEER_EBGP
) {
11935 if (bgp
->distance_ebgp
[afi
][safi
])
11936 return bgp
->distance_ebgp
[afi
][safi
];
11937 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11939 if (bgp
->distance_ibgp
[afi
][safi
])
11940 return bgp
->distance_ibgp
[afi
][safi
];
11941 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11945 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
11946 * we should tell ZEBRA update the routes for a specific
11947 * AFI/SAFI to reflect changes in RIB.
11949 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
11951 safi_t update_safi
)
11956 FOREACH_AFI_SAFI (afi
, safi
) {
11957 if (!bgp_fibupd_safi(safi
))
11960 if (afi
!= update_afi
&& safi
!= update_safi
)
11963 if (BGP_DEBUG(zebra
, ZEBRA
))
11965 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
11966 __func__
, afi
, safi
);
11967 bgp_zebra_announce_table(bgp
, afi
, safi
);
11971 DEFUN (bgp_distance
,
11973 "distance bgp (1-255) (1-255) (1-255)",
11974 "Define an administrative distance\n"
11976 "Distance for routes external to the AS\n"
11977 "Distance for routes internal to the AS\n"
11978 "Distance for local routes\n")
11980 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11981 int idx_number
= 2;
11982 int idx_number_2
= 3;
11983 int idx_number_3
= 4;
11984 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
11985 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
11986 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
11990 afi
= bgp_node_afi(vty
);
11991 safi
= bgp_node_safi(vty
);
11993 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
11994 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
11995 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
11996 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
11997 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
11998 bgp
->distance_local
[afi
][safi
] = distance_local
;
11999 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12001 return CMD_SUCCESS
;
12004 DEFUN (no_bgp_distance
,
12005 no_bgp_distance_cmd
,
12006 "no distance bgp [(1-255) (1-255) (1-255)]",
12008 "Define an administrative distance\n"
12010 "Distance for routes external to the AS\n"
12011 "Distance for routes internal to the AS\n"
12012 "Distance for local routes\n")
12014 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12018 afi
= bgp_node_afi(vty
);
12019 safi
= bgp_node_safi(vty
);
12021 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12022 || bgp
->distance_ibgp
[afi
][safi
] != 0
12023 || bgp
->distance_local
[afi
][safi
] != 0) {
12024 bgp
->distance_ebgp
[afi
][safi
] = 0;
12025 bgp
->distance_ibgp
[afi
][safi
] = 0;
12026 bgp
->distance_local
[afi
][safi
] = 0;
12027 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12029 return CMD_SUCCESS
;
12033 DEFUN (bgp_distance_source
,
12034 bgp_distance_source_cmd
,
12035 "distance (1-255) A.B.C.D/M",
12036 "Define an administrative distance\n"
12037 "Administrative distance\n"
12038 "IP source prefix\n")
12040 int idx_number
= 1;
12041 int idx_ipv4_prefixlen
= 2;
12042 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12043 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12044 return CMD_SUCCESS
;
12047 DEFUN (no_bgp_distance_source
,
12048 no_bgp_distance_source_cmd
,
12049 "no distance (1-255) A.B.C.D/M",
12051 "Define an administrative distance\n"
12052 "Administrative distance\n"
12053 "IP source prefix\n")
12055 int idx_number
= 2;
12056 int idx_ipv4_prefixlen
= 3;
12057 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12058 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12059 return CMD_SUCCESS
;
12062 DEFUN (bgp_distance_source_access_list
,
12063 bgp_distance_source_access_list_cmd
,
12064 "distance (1-255) A.B.C.D/M WORD",
12065 "Define an administrative distance\n"
12066 "Administrative distance\n"
12067 "IP source prefix\n"
12068 "Access list name\n")
12070 int idx_number
= 1;
12071 int idx_ipv4_prefixlen
= 2;
12073 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12074 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12075 return CMD_SUCCESS
;
12078 DEFUN (no_bgp_distance_source_access_list
,
12079 no_bgp_distance_source_access_list_cmd
,
12080 "no distance (1-255) A.B.C.D/M WORD",
12082 "Define an administrative distance\n"
12083 "Administrative distance\n"
12084 "IP source prefix\n"
12085 "Access list name\n")
12087 int idx_number
= 2;
12088 int idx_ipv4_prefixlen
= 3;
12090 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12091 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12092 return CMD_SUCCESS
;
12095 DEFUN (ipv6_bgp_distance_source
,
12096 ipv6_bgp_distance_source_cmd
,
12097 "distance (1-255) X:X::X:X/M",
12098 "Define an administrative distance\n"
12099 "Administrative distance\n"
12100 "IP source prefix\n")
12102 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12103 return CMD_SUCCESS
;
12106 DEFUN (no_ipv6_bgp_distance_source
,
12107 no_ipv6_bgp_distance_source_cmd
,
12108 "no distance (1-255) X:X::X:X/M",
12110 "Define an administrative distance\n"
12111 "Administrative distance\n"
12112 "IP source prefix\n")
12114 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12115 return CMD_SUCCESS
;
12118 DEFUN (ipv6_bgp_distance_source_access_list
,
12119 ipv6_bgp_distance_source_access_list_cmd
,
12120 "distance (1-255) X:X::X:X/M WORD",
12121 "Define an administrative distance\n"
12122 "Administrative distance\n"
12123 "IP source prefix\n"
12124 "Access list name\n")
12126 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12127 return CMD_SUCCESS
;
12130 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12131 no_ipv6_bgp_distance_source_access_list_cmd
,
12132 "no distance (1-255) X:X::X:X/M WORD",
12134 "Define an administrative distance\n"
12135 "Administrative distance\n"
12136 "IP source prefix\n"
12137 "Access list name\n")
12139 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12140 return CMD_SUCCESS
;
12143 DEFUN (bgp_damp_set
,
12145 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12146 "BGP Specific commands\n"
12147 "Enable route-flap dampening\n"
12148 "Half-life time for the penalty\n"
12149 "Value to start reusing a route\n"
12150 "Value to start suppressing a route\n"
12151 "Maximum duration to suppress a stable route\n")
12153 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12154 int idx_half_life
= 2;
12156 int idx_suppress
= 4;
12157 int idx_max_suppress
= 5;
12158 int half
= DEFAULT_HALF_LIFE
* 60;
12159 int reuse
= DEFAULT_REUSE
;
12160 int suppress
= DEFAULT_SUPPRESS
;
12161 int max
= 4 * half
;
12164 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12165 reuse
= atoi(argv
[idx_reuse
]->arg
);
12166 suppress
= atoi(argv
[idx_suppress
]->arg
);
12167 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12168 } else if (argc
== 3) {
12169 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12173 if (suppress
< reuse
) {
12175 "Suppress value cannot be less than reuse value \n");
12179 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12180 reuse
, suppress
, max
);
12183 DEFUN (bgp_damp_unset
,
12184 bgp_damp_unset_cmd
,
12185 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12187 "BGP Specific commands\n"
12188 "Enable route-flap dampening\n"
12189 "Half-life time for the penalty\n"
12190 "Value to start reusing a route\n"
12191 "Value to start suppressing a route\n"
12192 "Maximum duration to suppress a stable route\n")
12194 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12195 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12198 /* Display specified route of BGP table. */
12199 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12200 const char *ip_str
, afi_t afi
, safi_t safi
,
12201 struct prefix_rd
*prd
, int prefix_check
)
12204 struct prefix match
;
12205 struct bgp_node
*rn
;
12206 struct bgp_node
*rm
;
12207 struct bgp_path_info
*pi
;
12208 struct bgp_path_info
*pi_temp
;
12210 struct bgp_table
*table
;
12212 /* BGP structure lookup. */
12214 bgp
= bgp_lookup_by_name(view_name
);
12216 vty_out(vty
, "%% Can't find BGP instance %s\n",
12218 return CMD_WARNING
;
12221 bgp
= bgp_get_default();
12223 vty_out(vty
, "%% No BGP process is configured\n");
12224 return CMD_WARNING
;
12228 /* Check IP address argument. */
12229 ret
= str2prefix(ip_str
, &match
);
12231 vty_out(vty
, "%% address is malformed\n");
12232 return CMD_WARNING
;
12235 match
.family
= afi2family(afi
);
12237 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12238 || (safi
== SAFI_EVPN
)) {
12239 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12240 rn
= bgp_route_next(rn
)) {
12241 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12243 table
= bgp_node_get_bgp_table_info(rn
);
12246 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12250 || rm
->p
.prefixlen
== match
.prefixlen
) {
12251 pi
= bgp_node_get_bgp_path_info(rm
);
12253 if (pi
->extra
&& pi
->extra
->damp_info
) {
12254 pi_temp
= pi
->next
;
12255 bgp_damp_info_free(
12256 pi
->extra
->damp_info
,
12264 bgp_unlock_node(rm
);
12267 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12270 || rn
->p
.prefixlen
== match
.prefixlen
) {
12271 pi
= bgp_node_get_bgp_path_info(rn
);
12273 if (pi
->extra
&& pi
->extra
->damp_info
) {
12274 pi_temp
= pi
->next
;
12275 bgp_damp_info_free(
12276 pi
->extra
->damp_info
,
12284 bgp_unlock_node(rn
);
12288 return CMD_SUCCESS
;
12291 DEFUN (clear_ip_bgp_dampening
,
12292 clear_ip_bgp_dampening_cmd
,
12293 "clear ip bgp dampening",
12297 "Clear route flap dampening information\n")
12299 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
12300 return CMD_SUCCESS
;
12303 DEFUN (clear_ip_bgp_dampening_prefix
,
12304 clear_ip_bgp_dampening_prefix_cmd
,
12305 "clear ip bgp dampening A.B.C.D/M",
12309 "Clear route flap dampening information\n"
12312 int idx_ipv4_prefixlen
= 4;
12313 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12314 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12317 DEFUN (clear_ip_bgp_dampening_address
,
12318 clear_ip_bgp_dampening_address_cmd
,
12319 "clear ip bgp dampening A.B.C.D",
12323 "Clear route flap dampening information\n"
12324 "Network to clear damping information\n")
12327 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12328 SAFI_UNICAST
, NULL
, 0);
12331 DEFUN (clear_ip_bgp_dampening_address_mask
,
12332 clear_ip_bgp_dampening_address_mask_cmd
,
12333 "clear ip bgp dampening A.B.C.D A.B.C.D",
12337 "Clear route flap dampening information\n"
12338 "Network to clear damping information\n"
12342 int idx_ipv4_2
= 5;
12344 char prefix_str
[BUFSIZ
];
12346 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12349 vty_out(vty
, "%% Inconsistent address and mask\n");
12350 return CMD_WARNING
;
12353 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12357 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12359 struct vty
*vty
= arg
;
12360 struct peer
*peer
= bucket
->data
;
12361 char buf
[SU_ADDRSTRLEN
];
12363 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12364 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12367 DEFUN (show_bgp_peerhash
,
12368 show_bgp_peerhash_cmd
,
12369 "show bgp peerhash",
12372 "Display information about the BGP peerhash\n")
12374 struct list
*instances
= bm
->bgp
;
12375 struct listnode
*node
;
12378 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12379 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12380 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12384 return CMD_SUCCESS
;
12387 /* also used for encap safi */
12388 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12389 afi_t afi
, safi_t safi
)
12391 struct bgp_node
*prn
;
12392 struct bgp_node
*rn
;
12393 struct bgp_table
*table
;
12395 struct prefix_rd
*prd
;
12396 struct bgp_static
*bgp_static
;
12397 mpls_label_t label
;
12398 char buf
[SU_ADDRSTRLEN
];
12399 char rdbuf
[RD_ADDRSTRLEN
];
12401 /* Network configuration. */
12402 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12403 prn
= bgp_route_next(prn
)) {
12404 table
= bgp_node_get_bgp_table_info(prn
);
12408 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12409 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12410 if (bgp_static
== NULL
)
12414 prd
= (struct prefix_rd
*)&prn
->p
;
12416 /* "network" configuration display. */
12417 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12418 label
= decode_label(&bgp_static
->label
);
12420 vty_out(vty
, " network %s/%d rd %s",
12421 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12423 p
->prefixlen
, rdbuf
);
12424 if (safi
== SAFI_MPLS_VPN
)
12425 vty_out(vty
, " label %u", label
);
12427 if (bgp_static
->rmap
.name
)
12428 vty_out(vty
, " route-map %s",
12429 bgp_static
->rmap
.name
);
12431 if (bgp_static
->backdoor
)
12432 vty_out(vty
, " backdoor");
12434 vty_out(vty
, "\n");
12439 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12440 afi_t afi
, safi_t safi
)
12442 struct bgp_node
*prn
;
12443 struct bgp_node
*rn
;
12444 struct bgp_table
*table
;
12446 struct prefix_rd
*prd
;
12447 struct bgp_static
*bgp_static
;
12448 char buf
[PREFIX_STRLEN
* 2];
12449 char buf2
[SU_ADDRSTRLEN
];
12450 char rdbuf
[RD_ADDRSTRLEN
];
12452 /* Network configuration. */
12453 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12454 prn
= bgp_route_next(prn
)) {
12455 table
= bgp_node_get_bgp_table_info(prn
);
12459 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12460 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12461 if (bgp_static
== NULL
)
12464 char *macrouter
= NULL
;
12467 if (bgp_static
->router_mac
)
12468 macrouter
= prefix_mac2str(
12469 bgp_static
->router_mac
, NULL
, 0);
12470 if (bgp_static
->eth_s_id
)
12471 esi
= esi2str(bgp_static
->eth_s_id
);
12473 prd
= (struct prefix_rd
*)&prn
->p
;
12475 /* "network" configuration display. */
12476 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12477 if (p
->u
.prefix_evpn
.route_type
== 5) {
12478 char local_buf
[PREFIX_STRLEN
];
12479 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12480 struct prefix_evpn
*)p
)
12484 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12485 local_buf
, PREFIX_STRLEN
);
12486 sprintf(buf
, "%s/%u", local_buf
,
12487 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12489 prefix2str(p
, buf
, sizeof(buf
));
12492 if (bgp_static
->gatewayIp
.family
== AF_INET
12493 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12494 inet_ntop(bgp_static
->gatewayIp
.family
,
12495 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12498 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12500 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12501 decode_label(&bgp_static
->label
), esi
, buf2
,
12504 XFREE(MTYPE_TMP
, macrouter
);
12505 XFREE(MTYPE_TMP
, esi
);
12510 /* Configuration of static route announcement and aggregate
12512 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12515 struct bgp_node
*rn
;
12517 struct bgp_static
*bgp_static
;
12518 struct bgp_aggregate
*bgp_aggregate
;
12519 char buf
[SU_ADDRSTRLEN
];
12521 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12522 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12526 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12527 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12531 /* Network configuration. */
12532 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12533 rn
= bgp_route_next(rn
)) {
12534 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12535 if (bgp_static
== NULL
)
12540 vty_out(vty
, " network %s/%d",
12541 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12544 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12545 vty_out(vty
, " label-index %u",
12546 bgp_static
->label_index
);
12548 if (bgp_static
->rmap
.name
)
12549 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12551 if (bgp_static
->backdoor
)
12552 vty_out(vty
, " backdoor");
12554 vty_out(vty
, "\n");
12557 /* Aggregate-address configuration. */
12558 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12559 rn
= bgp_route_next(rn
)) {
12560 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12561 if (bgp_aggregate
== NULL
)
12566 vty_out(vty
, " aggregate-address %s/%d",
12567 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12570 if (bgp_aggregate
->as_set
)
12571 vty_out(vty
, " as-set");
12573 if (bgp_aggregate
->summary_only
)
12574 vty_out(vty
, " summary-only");
12576 if (bgp_aggregate
->rmap
.name
)
12577 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12579 vty_out(vty
, "\n");
12583 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12586 struct bgp_node
*rn
;
12587 struct bgp_distance
*bdistance
;
12589 /* Distance configuration. */
12590 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12591 && bgp
->distance_local
[afi
][safi
]
12592 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12593 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12594 || bgp
->distance_local
[afi
][safi
]
12595 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12596 vty_out(vty
, " distance bgp %d %d %d\n",
12597 bgp
->distance_ebgp
[afi
][safi
],
12598 bgp
->distance_ibgp
[afi
][safi
],
12599 bgp
->distance_local
[afi
][safi
]);
12602 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12603 rn
= bgp_route_next(rn
)) {
12604 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12605 if (bdistance
!= NULL
) {
12606 char buf
[PREFIX_STRLEN
];
12608 vty_out(vty
, " distance %d %s %s\n",
12609 bdistance
->distance
,
12610 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12611 bdistance
->access_list
? bdistance
->access_list
12617 /* Allocate routing table structure and install commands. */
12618 void bgp_route_init(void)
12623 /* Init BGP distance table. */
12624 FOREACH_AFI_SAFI (afi
, safi
)
12625 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12627 /* IPv4 BGP commands. */
12628 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12629 install_element(BGP_NODE
, &bgp_network_cmd
);
12630 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12632 install_element(BGP_NODE
, &aggregate_address_cmd
);
12633 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12634 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12635 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12637 /* IPv4 unicast configuration. */
12638 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12639 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12640 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12642 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12643 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12644 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12645 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12647 /* IPv4 multicast configuration. */
12648 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12649 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12650 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12651 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12652 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12653 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12654 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12656 /* IPv4 labeled-unicast configuration. */
12657 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12658 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12659 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12660 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12661 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12663 install_element(VIEW_NODE
,
12664 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12665 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12666 install_element(VIEW_NODE
,
12667 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12668 #ifdef KEEP_OLD_VPN_COMMANDS
12669 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12670 #endif /* KEEP_OLD_VPN_COMMANDS */
12671 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12672 install_element(VIEW_NODE
,
12673 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
12675 /* BGP dampening clear commands */
12676 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12677 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12679 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12680 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12683 install_element(ENABLE_NODE
,
12684 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12685 #ifdef KEEP_OLD_VPN_COMMANDS
12686 install_element(ENABLE_NODE
,
12687 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12688 #endif /* KEEP_OLD_VPN_COMMANDS */
12690 /* New config IPv6 BGP commands. */
12691 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12692 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12693 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12695 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12696 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12698 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12700 install_element(BGP_NODE
, &bgp_distance_cmd
);
12701 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12702 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12703 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12704 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12705 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12706 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12707 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12708 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12709 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12710 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12711 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12712 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12713 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12714 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12715 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12716 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12717 install_element(BGP_IPV4M_NODE
,
12718 &no_bgp_distance_source_access_list_cmd
);
12719 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12720 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12721 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12722 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12723 install_element(BGP_IPV6_NODE
,
12724 &ipv6_bgp_distance_source_access_list_cmd
);
12725 install_element(BGP_IPV6_NODE
,
12726 &no_ipv6_bgp_distance_source_access_list_cmd
);
12727 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12728 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12729 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12730 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12731 install_element(BGP_IPV6M_NODE
,
12732 &ipv6_bgp_distance_source_access_list_cmd
);
12733 install_element(BGP_IPV6M_NODE
,
12734 &no_ipv6_bgp_distance_source_access_list_cmd
);
12736 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12737 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12738 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12739 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12741 /* IPv4 Multicast Mode */
12742 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12743 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12745 /* Large Communities */
12746 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12747 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12749 /* show bgp ipv4 flowspec detailed */
12750 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12752 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12755 void bgp_route_finish(void)
12760 FOREACH_AFI_SAFI (afi
, safi
) {
12761 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12762 bgp_distance_table
[afi
][safi
] = NULL
;