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
,
2973 uint8_t type
, uint8_t stype
,
2974 struct attr
*attr
, struct bgp_node
*rn
)
2978 /* Only validated for unicast and multicast currently. */
2979 /* Also valid for EVPN where the nexthop is an IP address. */
2980 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2983 /* If NEXT_HOP is present, validate it. */
2984 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2985 if (attr
->nexthop
.s_addr
== 0
2986 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2987 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
2992 /* If MP_NEXTHOP is present, validate it. */
2993 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2994 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2995 * it is not an IPv6 link-local address.
2997 if (attr
->mp_nexthop_len
) {
2998 switch (attr
->mp_nexthop_len
) {
2999 case BGP_ATTR_NHLEN_IPV4
:
3000 case BGP_ATTR_NHLEN_VPNV4
:
3001 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
3002 || IPV4_CLASS_DE(ntohl(
3003 attr
->mp_nexthop_global_in
.s_addr
))
3004 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3008 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3009 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3010 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3011 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
3012 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3013 || IN6_IS_ADDR_MULTICAST(
3014 &attr
->mp_nexthop_global
)
3015 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3028 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3029 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3030 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3031 uint32_t num_labels
, int soft_reconfig
,
3032 struct bgp_route_evpn
*evpn
)
3035 int aspath_loop_count
= 0;
3036 struct bgp_node
*rn
;
3038 struct attr new_attr
;
3039 struct attr
*attr_new
;
3040 struct bgp_path_info
*pi
;
3041 struct bgp_path_info
*new;
3042 struct bgp_path_info_extra
*extra
;
3044 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3046 int do_loop_check
= 1;
3047 int has_valid_label
= 0;
3049 uint8_t pi_type
= 0;
3050 uint8_t pi_sub_type
= 0;
3053 int vnc_implicit_withdraw
= 0;
3057 memset(&new_attr
, 0, sizeof(struct attr
));
3058 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3059 new_attr
.label
= MPLS_INVALID_LABEL
;
3062 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3063 /* TODO: Check to see if we can get rid of "is_valid_label" */
3064 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3065 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3067 has_valid_label
= bgp_is_valid_label(label
);
3069 /* When peer's soft reconfiguration enabled. Record input packet in
3072 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3073 && peer
!= bgp
->peer_self
)
3074 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3076 /* Check previously received route. */
3077 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3078 if (pi
->peer
== peer
&& pi
->type
== type
3079 && pi
->sub_type
== sub_type
3080 && pi
->addpath_rx_id
== addpath_id
)
3083 /* AS path local-as loop check. */
3084 if (peer
->change_local_as
) {
3085 if (peer
->allowas_in
[afi
][safi
])
3086 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3087 else if (!CHECK_FLAG(peer
->flags
,
3088 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3089 aspath_loop_count
= 1;
3091 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3092 > aspath_loop_count
) {
3093 peer
->stat_pfx_aspath_loop
++;
3094 reason
= "as-path contains our own AS;";
3099 /* If the peer is configured for "allowas-in origin" and the last ASN in
3101 * as-path is our ASN then we do not need to call aspath_loop_check
3103 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3104 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3107 /* AS path loop check. */
3108 if (do_loop_check
) {
3109 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3110 > peer
->allowas_in
[afi
][safi
]
3111 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3112 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3113 > peer
->allowas_in
[afi
][safi
])) {
3114 peer
->stat_pfx_aspath_loop
++;
3115 reason
= "as-path contains our own AS;";
3120 /* Route reflector originator ID check. */
3121 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3122 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3123 peer
->stat_pfx_originator_loop
++;
3124 reason
= "originator is us;";
3128 /* Route reflector cluster ID check. */
3129 if (bgp_cluster_filter(peer
, attr
)) {
3130 peer
->stat_pfx_cluster_loop
++;
3131 reason
= "reflected from the same cluster;";
3135 /* Apply incoming filter. */
3136 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3137 peer
->stat_pfx_filter
++;
3142 /* RFC 8212 to prevent route leaks.
3143 * This specification intends to improve this situation by requiring the
3144 * explicit configuration of both BGP Import and Export Policies for any
3145 * External BGP (EBGP) session such as customers, peers, or
3146 * confederation boundaries for all enabled address families. Through
3147 * codification of the aforementioned requirement, operators will
3148 * benefit from consistent behavior across different BGP
3151 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3152 if (!bgp_inbound_policy_exists(peer
,
3153 &peer
->filter
[afi
][safi
])) {
3154 reason
= "inbound policy missing";
3158 bgp_attr_dup(&new_attr
, attr
);
3160 /* Apply incoming route-map.
3161 * NB: new_attr may now contain newly allocated values from route-map
3163 * commands, so we need bgp_attr_flush in the error paths, until we
3165 * the attr (which takes over the memory references) */
3166 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
,
3167 label
, num_labels
, rn
) == RMAP_DENY
) {
3168 peer
->stat_pfx_filter
++;
3169 reason
= "route-map;";
3170 bgp_attr_flush(&new_attr
);
3174 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3175 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3176 /* remove from RIB previous entry */
3177 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3180 if (peer
->sort
== BGP_PEER_EBGP
) {
3182 /* If we receive the graceful-shutdown community from an eBGP
3183 * peer we must lower local-preference */
3184 if (new_attr
.community
3185 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3186 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3187 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3189 /* If graceful-shutdown is configured then add the GSHUT
3190 * community to all paths received from eBGP peers */
3191 } else if (bgp_flag_check(peer
->bgp
,
3192 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3193 bgp_attr_add_gshut_community(&new_attr
);
3199 pi_sub_type
= pi
->sub_type
;
3202 /* next hop check. */
3203 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3204 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
,
3205 pi_sub_type
, &new_attr
, rn
)) {
3206 peer
->stat_pfx_nh_invalid
++;
3207 reason
= "martian or self next-hop;";
3208 bgp_attr_flush(&new_attr
);
3212 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3213 peer
->stat_pfx_nh_invalid
++;
3214 reason
= "self mac;";
3218 attr_new
= bgp_attr_intern(&new_attr
);
3220 /* If the update is implicit withdraw. */
3222 pi
->uptime
= bgp_clock();
3223 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3225 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3227 /* Same attribute comes in. */
3228 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3229 && attrhash_cmp(pi
->attr
, attr_new
)
3230 && (!has_valid_label
3231 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3232 num_labels
* sizeof(mpls_label_t
))
3234 && (overlay_index_equal(
3235 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3236 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3237 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3238 BGP_CONFIG_DAMPENING
)
3239 && peer
->sort
== BGP_PEER_EBGP
3240 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3241 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3242 bgp_debug_rdpfxpath2str(
3243 afi
, safi
, prd
, p
, label
,
3244 num_labels
, addpath_id
? 1 : 0,
3245 addpath_id
, pfx_buf
,
3247 zlog_debug("%s rcvd %s", peer
->host
,
3251 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3252 != BGP_DAMP_SUPPRESSED
) {
3253 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3255 bgp_process(bgp
, rn
, afi
, safi
);
3257 } else /* Duplicate - odd */
3259 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3260 if (!peer
->rcvd_attr_printed
) {
3262 "%s rcvd UPDATE w/ attr: %s",
3264 peer
->rcvd_attr_str
);
3265 peer
->rcvd_attr_printed
= 1;
3268 bgp_debug_rdpfxpath2str(
3269 afi
, safi
, prd
, p
, label
,
3270 num_labels
, addpath_id
? 1 : 0,
3271 addpath_id
, pfx_buf
,
3274 "%s rcvd %s...duplicate ignored",
3275 peer
->host
, pfx_buf
);
3278 /* graceful restart STALE flag unset. */
3279 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3280 bgp_path_info_unset_flag(
3281 rn
, pi
, BGP_PATH_STALE
);
3282 bgp_process(bgp
, rn
, afi
, safi
);
3286 bgp_unlock_node(rn
);
3287 bgp_attr_unintern(&attr_new
);
3292 /* Withdraw/Announce before we fully processed the withdraw */
3293 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3294 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3295 bgp_debug_rdpfxpath2str(
3296 afi
, safi
, prd
, p
, label
, num_labels
,
3297 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3300 "%s rcvd %s, flapped quicker than processing",
3301 peer
->host
, pfx_buf
);
3304 bgp_path_info_restore(rn
, pi
);
3307 /* Received Logging. */
3308 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3309 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3310 num_labels
, addpath_id
? 1 : 0,
3311 addpath_id
, pfx_buf
,
3313 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3316 /* graceful restart STALE flag unset. */
3317 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3318 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3320 /* The attribute is changed. */
3321 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3323 /* implicit withdraw, decrement aggregate and pcount here.
3324 * only if update is accepted, they'll increment below.
3326 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3328 /* Update bgp route dampening information. */
3329 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3330 && peer
->sort
== BGP_PEER_EBGP
) {
3331 /* This is implicit withdraw so we should update
3334 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3335 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3338 if (safi
== SAFI_MPLS_VPN
) {
3339 struct bgp_node
*prn
= NULL
;
3340 struct bgp_table
*table
= NULL
;
3342 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3343 (struct prefix
*)prd
);
3344 if (bgp_node_has_bgp_path_info_data(prn
)) {
3345 table
= bgp_node_get_bgp_table_info(prn
);
3347 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3348 bgp
, prd
, table
, p
, pi
);
3350 bgp_unlock_node(prn
);
3352 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3353 && (safi
== SAFI_UNICAST
)) {
3354 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3356 * Implicit withdraw case.
3358 ++vnc_implicit_withdraw
;
3359 vnc_import_bgp_del_route(bgp
, p
, pi
);
3360 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3365 /* Special handling for EVPN update of an existing route. If the
3366 * extended community attribute has changed, we need to
3368 * the route using its existing extended community. It will be
3369 * subsequently processed for import with the new extended
3372 if (safi
== SAFI_EVPN
&& !same_attr
) {
3374 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3376 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3379 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3380 attr_new
->ecommunity
);
3382 if (bgp_debug_update(peer
, p
, NULL
, 1))
3384 "Change in EXT-COMM, existing %s new %s",
3386 pi
->attr
->ecommunity
),
3388 attr_new
->ecommunity
));
3389 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3395 /* Update to new attribute. */
3396 bgp_attr_unintern(&pi
->attr
);
3397 pi
->attr
= attr_new
;
3399 /* Update MPLS label */
3400 if (has_valid_label
) {
3401 extra
= bgp_path_info_extra_get(pi
);
3402 if (extra
->label
!= label
) {
3403 memcpy(&extra
->label
, label
,
3404 num_labels
* sizeof(mpls_label_t
));
3405 extra
->num_labels
= num_labels
;
3407 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3408 bgp_set_valid_label(&extra
->label
[0]);
3412 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3413 && (safi
== SAFI_UNICAST
)) {
3414 if (vnc_implicit_withdraw
) {
3416 * Add back the route with its new attributes
3418 * The route is still selected, until the route
3420 * queued by bgp_process actually runs. We have
3422 * update to the VNC side immediately to avoid
3424 * configuration changes (e.g., route-map
3426 * trigger re-importation of the entire RIB.
3428 vnc_import_bgp_add_route(bgp
, p
, pi
);
3429 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3433 /* Update Overlay Index */
3434 if (afi
== AFI_L2VPN
) {
3435 overlay_index_update(
3436 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3437 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3440 /* Update bgp route dampening information. */
3441 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3442 && peer
->sort
== BGP_PEER_EBGP
) {
3443 /* Now we do normal update dampening. */
3444 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3445 if (ret
== BGP_DAMP_SUPPRESSED
) {
3446 bgp_unlock_node(rn
);
3451 /* Nexthop reachability check - for unicast and
3452 * labeled-unicast.. */
3453 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3454 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3455 || (safi
== SAFI_EVPN
&&
3456 bgp_evpn_is_prefix_nht_supported(p
))) {
3457 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3458 && !CHECK_FLAG(peer
->flags
,
3459 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3461 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3466 struct bgp
*bgp_nexthop
= bgp
;
3468 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3469 bgp_nexthop
= pi
->extra
->bgp_orig
;
3471 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3473 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3474 pi
, NULL
, connected
)
3475 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3476 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3478 if (BGP_DEBUG(nht
, NHT
)) {
3479 char buf1
[INET6_ADDRSTRLEN
];
3481 (const void *)&attr_new
3483 buf1
, INET6_ADDRSTRLEN
);
3484 zlog_debug("%s(%s): NH unresolved",
3485 __FUNCTION__
, buf1
);
3487 bgp_path_info_unset_flag(rn
, pi
,
3491 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3494 if (safi
== SAFI_MPLS_VPN
) {
3495 struct bgp_node
*prn
= NULL
;
3496 struct bgp_table
*table
= NULL
;
3498 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3499 (struct prefix
*)prd
);
3500 if (bgp_node_has_bgp_path_info_data(prn
)) {
3501 table
= bgp_node_get_bgp_table_info(prn
);
3503 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3504 bgp
, prd
, table
, p
, pi
);
3506 bgp_unlock_node(prn
);
3510 /* If this is an EVPN route and some attribute has changed,
3512 * route for import. If the extended community has changed, we
3514 * have done the un-import earlier and the import would result
3516 * route getting injected into appropriate L2 VNIs. If it is
3518 * some other attribute change, the import will result in
3520 * the attributes for the route in the VNI(s).
3522 if (safi
== SAFI_EVPN
&& !same_attr
&&
3523 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3524 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3526 /* Process change. */
3527 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3529 bgp_process(bgp
, rn
, afi
, safi
);
3530 bgp_unlock_node(rn
);
3532 if (SAFI_UNICAST
== safi
3533 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3534 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3536 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3538 if ((SAFI_MPLS_VPN
== safi
)
3539 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3541 vpn_leak_to_vrf_update(bgp
, pi
);
3545 if (SAFI_MPLS_VPN
== safi
) {
3546 mpls_label_t label_decoded
= decode_label(label
);
3548 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3549 type
, sub_type
, &label_decoded
);
3551 if (SAFI_ENCAP
== safi
) {
3552 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3553 type
, sub_type
, NULL
);
3558 } // End of implicit withdraw
3560 /* Received Logging. */
3561 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3562 if (!peer
->rcvd_attr_printed
) {
3563 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3564 peer
->rcvd_attr_str
);
3565 peer
->rcvd_attr_printed
= 1;
3568 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3569 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3571 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3574 /* Make new BGP info. */
3575 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3577 /* Update MPLS label */
3578 if (has_valid_label
) {
3579 extra
= bgp_path_info_extra_get(new);
3580 if (extra
->label
!= label
) {
3581 memcpy(&extra
->label
, label
,
3582 num_labels
* sizeof(mpls_label_t
));
3583 extra
->num_labels
= num_labels
;
3585 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3586 bgp_set_valid_label(&extra
->label
[0]);
3589 /* Update Overlay Index */
3590 if (afi
== AFI_L2VPN
) {
3591 overlay_index_update(new->attr
,
3592 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3593 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3595 /* Nexthop reachability check. */
3596 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3597 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3598 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
3599 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3600 && !CHECK_FLAG(peer
->flags
,
3601 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3602 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3607 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
3609 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
3611 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3612 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3614 if (BGP_DEBUG(nht
, NHT
)) {
3615 char buf1
[INET6_ADDRSTRLEN
];
3617 (const void *)&attr_new
->nexthop
,
3618 buf1
, INET6_ADDRSTRLEN
);
3619 zlog_debug("%s(%s): NH unresolved",
3620 __FUNCTION__
, buf1
);
3622 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3625 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3628 new->addpath_rx_id
= addpath_id
;
3630 /* Increment prefix */
3631 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3633 /* Register new BGP information. */
3634 bgp_path_info_add(rn
, new);
3636 /* route_node_get lock */
3637 bgp_unlock_node(rn
);
3640 if (safi
== SAFI_MPLS_VPN
) {
3641 struct bgp_node
*prn
= NULL
;
3642 struct bgp_table
*table
= NULL
;
3644 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3645 if (bgp_node_has_bgp_path_info_data(prn
)) {
3646 table
= bgp_node_get_bgp_table_info(prn
);
3648 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3649 bgp
, prd
, table
, p
, new);
3651 bgp_unlock_node(prn
);
3655 /* If maximum prefix count is configured and current prefix
3657 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3660 /* If this is an EVPN route, process for import. */
3661 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
3662 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3664 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3666 /* Process change. */
3667 bgp_process(bgp
, rn
, afi
, safi
);
3669 if (SAFI_UNICAST
== safi
3670 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3671 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3672 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3674 if ((SAFI_MPLS_VPN
== safi
)
3675 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3677 vpn_leak_to_vrf_update(bgp
, new);
3680 if (SAFI_MPLS_VPN
== safi
) {
3681 mpls_label_t label_decoded
= decode_label(label
);
3683 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3684 sub_type
, &label_decoded
);
3686 if (SAFI_ENCAP
== safi
) {
3687 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3694 /* This BGP update is filtered. Log the reason then update BGP
3697 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3699 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3700 if (!peer
->rcvd_attr_printed
) {
3701 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3702 peer
->rcvd_attr_str
);
3703 peer
->rcvd_attr_printed
= 1;
3706 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3707 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3709 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3710 peer
->host
, pfx_buf
, reason
);
3714 /* If this is an EVPN route, un-import it as it is now filtered.
3716 if (safi
== SAFI_EVPN
)
3717 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3719 if (SAFI_UNICAST
== safi
3720 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3721 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3723 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3725 if ((SAFI_MPLS_VPN
== safi
)
3726 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3728 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3731 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3734 bgp_unlock_node(rn
);
3738 * Filtered update is treated as an implicit withdrawal (see
3740 * a few lines above)
3742 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3743 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3751 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3752 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3753 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3754 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3757 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3758 struct bgp_node
*rn
;
3759 struct bgp_path_info
*pi
;
3762 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3763 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3771 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3773 /* If peer is soft reconfiguration enabled. Record input packet for
3774 * further calculation.
3776 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3777 * routes that are filtered. This tanks out Quagga RS pretty badly due
3779 * the iteration over all RS clients.
3780 * Since we need to remove the entry from adj_in anyway, do that first
3782 * if there was no entry, we don't need to do anything more.
3784 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3785 && peer
!= bgp
->peer_self
)
3786 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3787 peer
->stat_pfx_dup_withdraw
++;
3789 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3790 bgp_debug_rdpfxpath2str(
3791 afi
, safi
, prd
, p
, label
, num_labels
,
3792 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3795 "%s withdrawing route %s not in adj-in",
3796 peer
->host
, pfx_buf
);
3798 bgp_unlock_node(rn
);
3802 /* Lookup withdrawn route. */
3803 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3804 if (pi
->peer
== peer
&& pi
->type
== type
3805 && pi
->sub_type
== sub_type
3806 && pi
->addpath_rx_id
== addpath_id
)
3810 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3811 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3812 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3814 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3818 /* Withdraw specified route from routing table. */
3819 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3820 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3821 if (SAFI_UNICAST
== safi
3822 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3823 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3824 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3826 if ((SAFI_MPLS_VPN
== safi
)
3827 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3829 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3831 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3832 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3833 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3835 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3838 /* Unlock bgp_node_get() lock. */
3839 bgp_unlock_node(rn
);
3844 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3847 struct update_subgroup
*subgrp
;
3848 subgrp
= peer_subgroup(peer
, afi
, safi
);
3849 subgroup_default_originate(subgrp
, withdraw
);
3854 * bgp_stop_announce_route_timer
3856 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3858 if (!paf
->t_announce_route
)
3861 THREAD_TIMER_OFF(paf
->t_announce_route
);
3865 * bgp_announce_route_timer_expired
3867 * Callback that is invoked when the route announcement timer for a
3870 static int bgp_announce_route_timer_expired(struct thread
*t
)
3872 struct peer_af
*paf
;
3875 paf
= THREAD_ARG(t
);
3878 if (peer
->status
!= Established
)
3881 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3884 peer_af_announce_route(paf
, 1);
3889 * bgp_announce_route
3891 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3893 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3895 struct peer_af
*paf
;
3896 struct update_subgroup
*subgrp
;
3898 paf
= peer_af_find(peer
, afi
, safi
);
3901 subgrp
= PAF_SUBGRP(paf
);
3904 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3905 * or a refresh has already been triggered.
3907 if (!subgrp
|| paf
->t_announce_route
)
3911 * Start a timer to stagger/delay the announce. This serves
3912 * two purposes - announcement can potentially be combined for
3913 * multiple peers and the announcement doesn't happen in the
3916 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3917 (subgrp
->peer_count
== 1)
3918 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3919 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3920 &paf
->t_announce_route
);
3924 * Announce routes from all AF tables to a peer.
3926 * This should ONLY be called when there is a need to refresh the
3927 * routes to the peer based on a policy change for this peer alone
3928 * or a route refresh request received from the peer.
3929 * The operation will result in splitting the peer from its existing
3930 * subgroups and putting it in new subgroups.
3932 void bgp_announce_route_all(struct peer
*peer
)
3937 FOREACH_AFI_SAFI (afi
, safi
)
3938 bgp_announce_route(peer
, afi
, safi
);
3941 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3942 struct bgp_table
*table
,
3943 struct prefix_rd
*prd
)
3946 struct bgp_node
*rn
;
3947 struct bgp_adj_in
*ain
;
3950 table
= peer
->bgp
->rib
[afi
][safi
];
3952 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3953 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3954 if (ain
->peer
!= peer
)
3957 struct bgp_path_info
*pi
;
3958 uint32_t num_labels
= 0;
3959 mpls_label_t
*label_pnt
= NULL
;
3960 struct bgp_route_evpn evpn
;
3962 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
3964 if (pi
->peer
== peer
)
3967 if (pi
&& pi
->extra
)
3968 num_labels
= pi
->extra
->num_labels
;
3970 label_pnt
= &pi
->extra
->label
[0];
3972 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3975 memset(&evpn
, 0, sizeof(evpn
));
3977 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3978 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3979 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3980 num_labels
, 1, &evpn
);
3983 bgp_unlock_node(rn
);
3989 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3991 struct bgp_node
*rn
;
3992 struct bgp_table
*table
;
3994 if (peer
->status
!= Established
)
3997 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3998 && (safi
!= SAFI_EVPN
))
3999 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4001 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4002 rn
= bgp_route_next(rn
)) {
4003 table
= bgp_node_get_bgp_table_info(rn
);
4004 if (table
!= NULL
) {
4005 struct prefix_rd prd
;
4007 prd
.family
= AF_UNSPEC
;
4009 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
4011 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
4018 struct bgp_clear_node_queue
{
4019 struct bgp_node
*rn
;
4022 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4024 struct bgp_clear_node_queue
*cnq
= data
;
4025 struct bgp_node
*rn
= cnq
->rn
;
4026 struct peer
*peer
= wq
->spec
.data
;
4027 struct bgp_path_info
*pi
;
4029 afi_t afi
= bgp_node_table(rn
)->afi
;
4030 safi_t safi
= bgp_node_table(rn
)->safi
;
4035 /* It is possible that we have multiple paths for a prefix from a peer
4036 * if that peer is using AddPath.
4038 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4039 if (pi
->peer
!= peer
)
4042 /* graceful restart STALE flag set. */
4043 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4044 && peer
->nsf
[afi
][safi
]
4045 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4046 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4047 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4049 /* If this is an EVPN route, process for
4051 if (safi
== SAFI_EVPN
)
4052 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
4054 /* Handle withdraw for VRF route-leaking and L3VPN */
4055 if (SAFI_UNICAST
== safi
4056 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4057 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4058 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4061 if (SAFI_MPLS_VPN
== safi
&&
4062 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4063 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4066 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4072 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4074 struct bgp_clear_node_queue
*cnq
= data
;
4075 struct bgp_node
*rn
= cnq
->rn
;
4076 struct bgp_table
*table
= bgp_node_table(rn
);
4078 bgp_unlock_node(rn
);
4079 bgp_table_unlock(table
);
4080 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4083 static void bgp_clear_node_complete(struct work_queue
*wq
)
4085 struct peer
*peer
= wq
->spec
.data
;
4087 /* Tickle FSM to start moving again */
4088 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4090 peer_unlock(peer
); /* bgp_clear_route */
4093 static void bgp_clear_node_queue_init(struct peer
*peer
)
4095 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4097 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4098 #undef CLEAR_QUEUE_NAME_LEN
4100 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4101 peer
->clear_node_queue
->spec
.hold
= 10;
4102 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4103 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4104 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4105 peer
->clear_node_queue
->spec
.max_retries
= 0;
4107 /* we only 'lock' this peer reference when the queue is actually active
4109 peer
->clear_node_queue
->spec
.data
= peer
;
4112 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4113 struct bgp_table
*table
)
4115 struct bgp_node
*rn
;
4116 int force
= bm
->process_main_queue
? 0 : 1;
4119 table
= peer
->bgp
->rib
[afi
][safi
];
4121 /* If still no table => afi/safi isn't configured at all or smth. */
4125 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4126 struct bgp_path_info
*pi
, *next
;
4127 struct bgp_adj_in
*ain
;
4128 struct bgp_adj_in
*ain_next
;
4130 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4131 * queued for every clearing peer, regardless of whether it is
4132 * relevant to the peer at hand.
4134 * Overview: There are 3 different indices which need to be
4135 * scrubbed, potentially, when a peer is removed:
4137 * 1 peer's routes visible via the RIB (ie accepted routes)
4138 * 2 peer's routes visible by the (optional) peer's adj-in index
4139 * 3 other routes visible by the peer's adj-out index
4141 * 3 there is no hurry in scrubbing, once the struct peer is
4142 * removed from bgp->peer, we could just GC such deleted peer's
4143 * adj-outs at our leisure.
4145 * 1 and 2 must be 'scrubbed' in some way, at least made
4146 * invisible via RIB index before peer session is allowed to be
4147 * brought back up. So one needs to know when such a 'search' is
4152 * - there'd be a single global queue or a single RIB walker
4153 * - rather than tracking which route_nodes still need to be
4154 * examined on a peer basis, we'd track which peers still
4157 * Given that our per-peer prefix-counts now should be reliable,
4158 * this may actually be achievable. It doesn't seem to be a huge
4159 * problem at this time,
4161 * It is possible that we have multiple paths for a prefix from
4163 * if that peer is using AddPath.
4167 ain_next
= ain
->next
;
4169 if (ain
->peer
== peer
) {
4170 bgp_adj_in_remove(rn
, ain
);
4171 bgp_unlock_node(rn
);
4177 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4179 if (pi
->peer
!= peer
)
4183 bgp_path_info_reap(rn
, pi
);
4185 struct bgp_clear_node_queue
*cnq
;
4187 /* both unlocked in bgp_clear_node_queue_del */
4188 bgp_table_lock(bgp_node_table(rn
));
4191 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4192 sizeof(struct bgp_clear_node_queue
));
4194 work_queue_add(peer
->clear_node_queue
, cnq
);
4202 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4204 struct bgp_node
*rn
;
4205 struct bgp_table
*table
;
4207 if (peer
->clear_node_queue
== NULL
)
4208 bgp_clear_node_queue_init(peer
);
4210 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4211 * Idle until it receives a Clearing_Completed event. This protects
4212 * against peers which flap faster than we can we clear, which could
4215 * a) race with routes from the new session being installed before
4216 * clear_route_node visits the node (to delete the route of that
4218 * b) resource exhaustion, clear_route_node likely leads to an entry
4219 * on the process_main queue. Fast-flapping could cause that queue
4223 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4224 * the unlock will happen upon work-queue completion; other wise, the
4225 * unlock happens at the end of this function.
4227 if (!peer
->clear_node_queue
->thread
)
4230 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4231 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4233 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4234 rn
= bgp_route_next(rn
)) {
4235 table
= bgp_node_get_bgp_table_info(rn
);
4239 bgp_clear_route_table(peer
, afi
, safi
, table
);
4242 /* unlock if no nodes got added to the clear-node-queue. */
4243 if (!peer
->clear_node_queue
->thread
)
4247 void bgp_clear_route_all(struct peer
*peer
)
4252 FOREACH_AFI_SAFI (afi
, safi
)
4253 bgp_clear_route(peer
, afi
, safi
);
4256 rfapiProcessPeerDown(peer
);
4260 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4262 struct bgp_table
*table
;
4263 struct bgp_node
*rn
;
4264 struct bgp_adj_in
*ain
;
4265 struct bgp_adj_in
*ain_next
;
4267 table
= peer
->bgp
->rib
[afi
][safi
];
4269 /* It is possible that we have multiple paths for a prefix from a peer
4270 * if that peer is using AddPath.
4272 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4276 ain_next
= ain
->next
;
4278 if (ain
->peer
== peer
) {
4279 bgp_adj_in_remove(rn
, ain
);
4280 bgp_unlock_node(rn
);
4288 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4290 struct bgp_node
*rn
;
4291 struct bgp_path_info
*pi
;
4292 struct bgp_table
*table
;
4294 if (safi
== SAFI_MPLS_VPN
) {
4295 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4296 rn
= bgp_route_next(rn
)) {
4297 struct bgp_node
*rm
;
4299 /* look for neighbor in tables */
4300 table
= bgp_node_get_bgp_table_info(rn
);
4304 for (rm
= bgp_table_top(table
); rm
;
4305 rm
= bgp_route_next(rm
))
4306 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4308 if (pi
->peer
!= peer
)
4310 if (!CHECK_FLAG(pi
->flags
,
4314 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4319 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4320 rn
= bgp_route_next(rn
))
4321 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4323 if (pi
->peer
!= peer
)
4325 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4327 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4333 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4335 if (peer
->sort
== BGP_PEER_EBGP
4336 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4337 || FILTER_LIST_OUT_NAME(filter
)
4338 || DISTRIBUTE_OUT_NAME(filter
)))
4343 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4345 if (peer
->sort
== BGP_PEER_EBGP
4346 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4347 || FILTER_LIST_IN_NAME(filter
)
4348 || DISTRIBUTE_IN_NAME(filter
)))
4353 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4356 struct bgp_node
*rn
;
4357 struct bgp_path_info
*pi
;
4358 struct bgp_path_info
*next
;
4360 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4361 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4364 /* Unimport EVPN routes from VRFs */
4365 if (safi
== SAFI_EVPN
)
4366 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4370 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4371 && pi
->type
== ZEBRA_ROUTE_BGP
4372 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4373 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4374 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4376 if (bgp_fibupd_safi(safi
))
4377 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4379 bgp_path_info_reap(rn
, pi
);
4384 /* Delete all kernel routes. */
4385 void bgp_cleanup_routes(struct bgp
*bgp
)
4388 struct bgp_node
*rn
;
4389 struct bgp_table
*table
;
4391 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4392 if (afi
== AFI_L2VPN
)
4394 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4397 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4399 if (afi
!= AFI_L2VPN
) {
4401 safi
= SAFI_MPLS_VPN
;
4402 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4403 rn
= bgp_route_next(rn
)) {
4404 table
= bgp_node_get_bgp_table_info(rn
);
4405 if (table
!= NULL
) {
4406 bgp_cleanup_table(bgp
, table
, safi
);
4407 bgp_table_finish(&table
);
4408 bgp_node_set_bgp_table_info(rn
, NULL
);
4409 bgp_unlock_node(rn
);
4413 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4414 rn
= bgp_route_next(rn
)) {
4415 table
= bgp_node_get_bgp_table_info(rn
);
4416 if (table
!= NULL
) {
4417 bgp_cleanup_table(bgp
, table
, safi
);
4418 bgp_table_finish(&table
);
4419 bgp_node_set_bgp_table_info(rn
, NULL
);
4420 bgp_unlock_node(rn
);
4425 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4426 rn
= bgp_route_next(rn
)) {
4427 table
= bgp_node_get_bgp_table_info(rn
);
4428 if (table
!= NULL
) {
4429 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4430 bgp_table_finish(&table
);
4431 bgp_node_set_bgp_table_info(rn
, NULL
);
4432 bgp_unlock_node(rn
);
4437 void bgp_reset(void)
4440 bgp_zclient_reset();
4441 access_list_reset();
4442 prefix_list_reset();
4445 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4447 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4448 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4449 PEER_CAP_ADDPATH_AF_TX_RCV
));
4452 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4454 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4455 struct bgp_nlri
*packet
)
4464 int addpath_encoded
;
4465 uint32_t addpath_id
;
4468 lim
= pnt
+ packet
->length
;
4470 safi
= packet
->safi
;
4472 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4474 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4475 syntactic validity. If the field is syntactically incorrect,
4476 then the Error Subcode is set to Invalid Network Field. */
4477 for (; pnt
< lim
; pnt
+= psize
) {
4478 /* Clear prefix structure. */
4479 memset(&p
, 0, sizeof(struct prefix
));
4481 if (addpath_encoded
) {
4483 /* When packet overflow occurs return immediately. */
4484 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4485 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4487 addpath_id
= ntohl(*((uint32_t *)pnt
));
4488 pnt
+= BGP_ADDPATH_ID_LEN
;
4491 /* Fetch prefix length. */
4492 p
.prefixlen
= *pnt
++;
4493 /* afi/safi validity already verified by caller,
4494 * bgp_update_receive */
4495 p
.family
= afi2family(afi
);
4497 /* Prefix length check. */
4498 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4501 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4502 peer
->host
, p
.prefixlen
, packet
->afi
);
4503 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4506 /* Packet size overflow check. */
4507 psize
= PSIZE(p
.prefixlen
);
4509 /* When packet overflow occur return immediately. */
4510 if (pnt
+ psize
> lim
) {
4513 "%s [Error] Update packet error (prefix length %d overflows packet)",
4514 peer
->host
, p
.prefixlen
);
4515 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4518 /* Defensive coding, double-check the psize fits in a struct
4520 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4523 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4524 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4525 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4528 /* Fetch prefix from NLRI packet. */
4529 memcpy(p
.u
.val
, pnt
, psize
);
4531 /* Check address. */
4532 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4533 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4534 /* From RFC4271 Section 6.3:
4536 * If a prefix in the NLRI field is semantically
4538 * (e.g., an unexpected multicast IP address),
4540 * be logged locally, and the prefix SHOULD be
4545 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4546 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4551 /* Check address. */
4552 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4553 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4558 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4560 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4565 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4570 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4572 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4579 /* Normal process. */
4581 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4582 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4583 NULL
, NULL
, 0, 0, NULL
);
4585 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4586 safi
, ZEBRA_ROUTE_BGP
,
4587 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4590 /* Do not send BGP notification twice when maximum-prefix count
4592 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4593 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4595 /* Address family configuration mismatch. */
4597 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4600 /* Packet length consistency check. */
4604 "%s [Error] Update packet error (prefix length mismatch with total length)",
4606 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4609 return BGP_NLRI_PARSE_OK
;
4612 static struct bgp_static
*bgp_static_new(void)
4614 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4617 static void bgp_static_free(struct bgp_static
*bgp_static
)
4619 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4620 route_map_counter_decrement(bgp_static
->rmap
.map
);
4622 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4623 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4626 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4627 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4629 struct bgp_node
*rn
;
4630 struct bgp_path_info
*pi
;
4631 struct bgp_path_info
*new;
4632 struct bgp_path_info rmap_path
;
4634 struct attr
*attr_new
;
4635 route_map_result_t ret
;
4637 int vnc_implicit_withdraw
= 0;
4644 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4646 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4648 attr
.nexthop
= bgp_static
->igpnexthop
;
4649 attr
.med
= bgp_static
->igpmetric
;
4650 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4652 if (bgp_static
->atomic
)
4653 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4655 /* Store label index, if required. */
4656 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4657 attr
.label_index
= bgp_static
->label_index
;
4658 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4661 /* Apply route-map. */
4662 if (bgp_static
->rmap
.name
) {
4663 struct attr attr_tmp
= attr
;
4665 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4666 rmap_path
.peer
= bgp
->peer_self
;
4667 rmap_path
.attr
= &attr_tmp
;
4669 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4671 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4674 bgp
->peer_self
->rmap_type
= 0;
4676 if (ret
== RMAP_DENYMATCH
) {
4677 /* Free uninterned attribute. */
4678 bgp_attr_flush(&attr_tmp
);
4680 /* Unintern original. */
4681 aspath_unintern(&attr
.aspath
);
4682 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4686 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4687 bgp_attr_add_gshut_community(&attr_tmp
);
4689 attr_new
= bgp_attr_intern(&attr_tmp
);
4692 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4693 bgp_attr_add_gshut_community(&attr
);
4695 attr_new
= bgp_attr_intern(&attr
);
4698 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4699 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4700 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4704 if (attrhash_cmp(pi
->attr
, attr_new
)
4705 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4706 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4707 bgp_unlock_node(rn
);
4708 bgp_attr_unintern(&attr_new
);
4709 aspath_unintern(&attr
.aspath
);
4712 /* The attribute is changed. */
4713 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4715 /* Rewrite BGP route information. */
4716 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4717 bgp_path_info_restore(rn
, pi
);
4719 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4721 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4722 && (safi
== SAFI_UNICAST
)) {
4723 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4725 * Implicit withdraw case.
4726 * We have to do this before pi is
4729 ++vnc_implicit_withdraw
;
4730 vnc_import_bgp_del_route(bgp
, p
, pi
);
4731 vnc_import_bgp_exterior_del_route(
4736 bgp_attr_unintern(&pi
->attr
);
4737 pi
->attr
= attr_new
;
4738 pi
->uptime
= bgp_clock();
4740 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4741 && (safi
== SAFI_UNICAST
)) {
4742 if (vnc_implicit_withdraw
) {
4743 vnc_import_bgp_add_route(bgp
, p
, pi
);
4744 vnc_import_bgp_exterior_add_route(
4750 /* Nexthop reachability check. */
4751 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4752 && (safi
== SAFI_UNICAST
4753 || safi
== SAFI_LABELED_UNICAST
)) {
4755 struct bgp
*bgp_nexthop
= bgp
;
4757 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4758 bgp_nexthop
= pi
->extra
->bgp_orig
;
4760 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4762 bgp_path_info_set_flag(rn
, pi
,
4765 if (BGP_DEBUG(nht
, NHT
)) {
4766 char buf1
[INET6_ADDRSTRLEN
];
4767 inet_ntop(p
->family
,
4771 "%s(%s): Route not in table, not advertising",
4772 __FUNCTION__
, buf1
);
4774 bgp_path_info_unset_flag(
4775 rn
, pi
, BGP_PATH_VALID
);
4778 /* Delete the NHT structure if any, if we're
4780 * enabling/disabling import check. We
4781 * deregister the route
4782 * from NHT to avoid overloading NHT and the
4783 * process interaction
4785 bgp_unlink_nexthop(pi
);
4786 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4788 /* Process change. */
4789 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4790 bgp_process(bgp
, rn
, afi
, safi
);
4792 if (SAFI_UNICAST
== safi
4793 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4795 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4796 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4800 bgp_unlock_node(rn
);
4801 aspath_unintern(&attr
.aspath
);
4806 /* Make new BGP info. */
4807 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4809 /* Nexthop reachability check. */
4810 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4811 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4812 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4813 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4815 if (BGP_DEBUG(nht
, NHT
)) {
4816 char buf1
[INET6_ADDRSTRLEN
];
4817 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4820 "%s(%s): Route not in table, not advertising",
4821 __FUNCTION__
, buf1
);
4823 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4826 /* Delete the NHT structure if any, if we're toggling between
4827 * enabling/disabling import check. We deregister the route
4828 * from NHT to avoid overloading NHT and the process interaction
4830 bgp_unlink_nexthop(new);
4832 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4835 /* Aggregate address increment. */
4836 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4838 /* Register new BGP information. */
4839 bgp_path_info_add(rn
, new);
4841 /* route_node_get lock */
4842 bgp_unlock_node(rn
);
4844 /* Process change. */
4845 bgp_process(bgp
, rn
, afi
, safi
);
4847 if (SAFI_UNICAST
== safi
4848 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4849 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4850 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4853 /* Unintern original. */
4854 aspath_unintern(&attr
.aspath
);
4857 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4860 struct bgp_node
*rn
;
4861 struct bgp_path_info
*pi
;
4863 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4865 /* Check selected route and self inserted route. */
4866 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4867 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4868 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4871 /* Withdraw static BGP route from routing table. */
4873 if (SAFI_UNICAST
== safi
4874 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4875 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4876 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4878 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4879 bgp_unlink_nexthop(pi
);
4880 bgp_path_info_delete(rn
, pi
);
4881 bgp_process(bgp
, rn
, afi
, safi
);
4884 /* Unlock bgp_node_lookup. */
4885 bgp_unlock_node(rn
);
4889 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4891 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4892 afi_t afi
, safi_t safi
,
4893 struct prefix_rd
*prd
)
4895 struct bgp_node
*rn
;
4896 struct bgp_path_info
*pi
;
4898 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4900 /* Check selected route and self inserted route. */
4901 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4902 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4903 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4906 /* Withdraw static BGP route from routing table. */
4909 rfapiProcessWithdraw(
4910 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4911 1); /* Kill, since it is an administrative change */
4913 if (SAFI_MPLS_VPN
== safi
4914 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4915 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4917 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4918 bgp_path_info_delete(rn
, pi
);
4919 bgp_process(bgp
, rn
, afi
, safi
);
4922 /* Unlock bgp_node_lookup. */
4923 bgp_unlock_node(rn
);
4926 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4927 struct bgp_static
*bgp_static
, afi_t afi
,
4930 struct bgp_node
*rn
;
4931 struct bgp_path_info
*new;
4932 struct attr
*attr_new
;
4933 struct attr attr
= {0};
4934 struct bgp_path_info
*pi
;
4936 mpls_label_t label
= 0;
4938 uint32_t num_labels
= 0;
4943 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4945 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4948 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4950 attr
.nexthop
= bgp_static
->igpnexthop
;
4951 attr
.med
= bgp_static
->igpmetric
;
4952 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4954 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4955 || (safi
== SAFI_ENCAP
)) {
4956 if (afi
== AFI_IP
) {
4957 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4958 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4961 if (afi
== AFI_L2VPN
) {
4962 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4964 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4965 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4966 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4967 sizeof(struct in6_addr
));
4968 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4969 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4970 struct bgp_encap_type_vxlan bet
;
4971 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4972 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4973 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4975 if (bgp_static
->router_mac
) {
4976 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4979 /* Apply route-map. */
4980 if (bgp_static
->rmap
.name
) {
4981 struct attr attr_tmp
= attr
;
4982 struct bgp_path_info rmap_path
;
4983 route_map_result_t ret
;
4985 rmap_path
.peer
= bgp
->peer_self
;
4986 rmap_path
.attr
= &attr_tmp
;
4988 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4990 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4993 bgp
->peer_self
->rmap_type
= 0;
4995 if (ret
== RMAP_DENYMATCH
) {
4996 /* Free uninterned attribute. */
4997 bgp_attr_flush(&attr_tmp
);
4999 /* Unintern original. */
5000 aspath_unintern(&attr
.aspath
);
5001 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5006 attr_new
= bgp_attr_intern(&attr_tmp
);
5008 attr_new
= bgp_attr_intern(&attr
);
5011 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5012 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5013 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5017 memset(&add
, 0, sizeof(union gw_addr
));
5018 if (attrhash_cmp(pi
->attr
, attr_new
)
5019 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
5020 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5021 bgp_unlock_node(rn
);
5022 bgp_attr_unintern(&attr_new
);
5023 aspath_unintern(&attr
.aspath
);
5026 /* The attribute is changed. */
5027 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5029 /* Rewrite BGP route information. */
5030 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5031 bgp_path_info_restore(rn
, pi
);
5033 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5034 bgp_attr_unintern(&pi
->attr
);
5035 pi
->attr
= attr_new
;
5036 pi
->uptime
= bgp_clock();
5039 label
= decode_label(&pi
->extra
->label
[0]);
5042 /* Process change. */
5043 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5044 bgp_process(bgp
, rn
, afi
, safi
);
5046 if (SAFI_MPLS_VPN
== safi
5047 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5048 vpn_leak_to_vrf_update(bgp
, pi
);
5051 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5052 pi
->attr
, afi
, safi
, pi
->type
,
5053 pi
->sub_type
, &label
);
5055 bgp_unlock_node(rn
);
5056 aspath_unintern(&attr
.aspath
);
5062 /* Make new BGP info. */
5063 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5065 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5066 new->extra
= bgp_path_info_extra_new();
5068 new->extra
->label
[0] = bgp_static
->label
;
5069 new->extra
->num_labels
= num_labels
;
5072 label
= decode_label(&bgp_static
->label
);
5075 /* Aggregate address increment. */
5076 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5078 /* Register new BGP information. */
5079 bgp_path_info_add(rn
, new);
5080 /* route_node_get lock */
5081 bgp_unlock_node(rn
);
5083 /* Process change. */
5084 bgp_process(bgp
, rn
, afi
, safi
);
5086 if (SAFI_MPLS_VPN
== safi
5087 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5088 vpn_leak_to_vrf_update(bgp
, new);
5091 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5092 safi
, new->type
, new->sub_type
, &label
);
5095 /* Unintern original. */
5096 aspath_unintern(&attr
.aspath
);
5099 /* Configure static BGP network. When user don't run zebra, static
5100 route should be installed as valid. */
5101 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5102 const char *ip_str
, afi_t afi
, safi_t safi
,
5103 const char *rmap
, int backdoor
, uint32_t label_index
)
5105 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5108 struct bgp_static
*bgp_static
;
5109 struct bgp_node
*rn
;
5110 uint8_t need_update
= 0;
5112 /* Convert IP prefix string to struct prefix. */
5113 ret
= str2prefix(ip_str
, &p
);
5115 vty_out(vty
, "%% Malformed prefix\n");
5116 return CMD_WARNING_CONFIG_FAILED
;
5118 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5119 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5120 return CMD_WARNING_CONFIG_FAILED
;
5127 /* Set BGP static route configuration. */
5128 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5131 vty_out(vty
, "%% Can't find static route specified\n");
5132 return CMD_WARNING_CONFIG_FAILED
;
5135 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5137 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5138 && (label_index
!= bgp_static
->label_index
)) {
5140 "%% label-index doesn't match static route\n");
5141 return CMD_WARNING_CONFIG_FAILED
;
5144 if ((rmap
&& bgp_static
->rmap
.name
)
5145 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5147 "%% route-map name doesn't match static route\n");
5148 return CMD_WARNING_CONFIG_FAILED
;
5151 /* Update BGP RIB. */
5152 if (!bgp_static
->backdoor
)
5153 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5155 /* Clear configuration. */
5156 bgp_static_free(bgp_static
);
5157 bgp_node_set_bgp_static_info(rn
, NULL
);
5158 bgp_unlock_node(rn
);
5159 bgp_unlock_node(rn
);
5162 /* Set BGP static route configuration. */
5163 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5165 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5167 /* Configuration change. */
5168 /* Label index cannot be changed. */
5169 if (bgp_static
->label_index
!= label_index
) {
5170 vty_out(vty
, "%% cannot change label-index\n");
5171 return CMD_WARNING_CONFIG_FAILED
;
5174 /* Check previous routes are installed into BGP. */
5175 if (bgp_static
->valid
5176 && bgp_static
->backdoor
!= backdoor
)
5179 bgp_static
->backdoor
= backdoor
;
5182 XFREE(MTYPE_ROUTE_MAP_NAME
,
5183 bgp_static
->rmap
.name
);
5184 route_map_counter_decrement(
5185 bgp_static
->rmap
.map
);
5186 bgp_static
->rmap
.name
=
5187 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5188 bgp_static
->rmap
.map
=
5189 route_map_lookup_by_name(rmap
);
5190 route_map_counter_increment(
5191 bgp_static
->rmap
.map
);
5193 XFREE(MTYPE_ROUTE_MAP_NAME
,
5194 bgp_static
->rmap
.name
);
5195 route_map_counter_decrement(
5196 bgp_static
->rmap
.map
);
5197 bgp_static
->rmap
.name
= NULL
;
5198 bgp_static
->rmap
.map
= NULL
;
5199 bgp_static
->valid
= 0;
5201 bgp_unlock_node(rn
);
5203 /* New configuration. */
5204 bgp_static
= bgp_static_new();
5205 bgp_static
->backdoor
= backdoor
;
5206 bgp_static
->valid
= 0;
5207 bgp_static
->igpmetric
= 0;
5208 bgp_static
->igpnexthop
.s_addr
= 0;
5209 bgp_static
->label_index
= label_index
;
5212 XFREE(MTYPE_ROUTE_MAP_NAME
,
5213 bgp_static
->rmap
.name
);
5214 route_map_counter_decrement(
5215 bgp_static
->rmap
.map
);
5216 bgp_static
->rmap
.name
=
5217 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5218 bgp_static
->rmap
.map
=
5219 route_map_lookup_by_name(rmap
);
5220 route_map_counter_increment(
5221 bgp_static
->rmap
.map
);
5223 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5226 bgp_static
->valid
= 1;
5228 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5230 if (!bgp_static
->backdoor
)
5231 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5237 void bgp_static_add(struct bgp
*bgp
)
5241 struct bgp_node
*rn
;
5242 struct bgp_node
*rm
;
5243 struct bgp_table
*table
;
5244 struct bgp_static
*bgp_static
;
5246 FOREACH_AFI_SAFI (afi
, safi
)
5247 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5248 rn
= bgp_route_next(rn
)) {
5249 if (!bgp_node_has_bgp_path_info_data(rn
))
5252 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5253 || (safi
== SAFI_EVPN
)) {
5254 table
= bgp_node_get_bgp_table_info(rn
);
5256 for (rm
= bgp_table_top(table
); rm
;
5257 rm
= bgp_route_next(rm
)) {
5259 bgp_node_get_bgp_static_info(
5261 bgp_static_update_safi(bgp
, &rm
->p
,
5268 bgp_node_get_bgp_static_info(rn
), afi
,
5274 /* Called from bgp_delete(). Delete all static routes from the BGP
5276 void bgp_static_delete(struct bgp
*bgp
)
5280 struct bgp_node
*rn
;
5281 struct bgp_node
*rm
;
5282 struct bgp_table
*table
;
5283 struct bgp_static
*bgp_static
;
5285 FOREACH_AFI_SAFI (afi
, safi
)
5286 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5287 rn
= bgp_route_next(rn
)) {
5288 if (!bgp_node_has_bgp_path_info_data(rn
))
5291 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5292 || (safi
== SAFI_EVPN
)) {
5293 table
= bgp_node_get_bgp_table_info(rn
);
5295 for (rm
= bgp_table_top(table
); rm
;
5296 rm
= bgp_route_next(rm
)) {
5298 bgp_node_get_bgp_static_info(
5303 bgp_static_withdraw_safi(
5304 bgp
, &rm
->p
, AFI_IP
, safi
,
5305 (struct prefix_rd
*)&rn
->p
);
5306 bgp_static_free(bgp_static
);
5307 bgp_node_set_bgp_static_info(rn
, NULL
);
5308 bgp_unlock_node(rn
);
5311 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5312 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5313 bgp_static_free(bgp_static
);
5314 bgp_node_set_bgp_static_info(rn
, NULL
);
5315 bgp_unlock_node(rn
);
5320 void bgp_static_redo_import_check(struct bgp
*bgp
)
5324 struct bgp_node
*rn
;
5325 struct bgp_node
*rm
;
5326 struct bgp_table
*table
;
5327 struct bgp_static
*bgp_static
;
5329 /* Use this flag to force reprocessing of the route */
5330 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5331 FOREACH_AFI_SAFI (afi
, safi
) {
5332 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5333 rn
= bgp_route_next(rn
)) {
5334 if (!bgp_node_has_bgp_path_info_data(rn
))
5337 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5338 || (safi
== SAFI_EVPN
)) {
5339 table
= bgp_node_get_bgp_table_info(rn
);
5341 for (rm
= bgp_table_top(table
); rm
;
5342 rm
= bgp_route_next(rm
)) {
5344 bgp_node_get_bgp_static_info(
5346 bgp_static_update_safi(bgp
, &rm
->p
,
5351 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5352 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5357 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5360 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5363 struct bgp_table
*table
;
5364 struct bgp_node
*rn
;
5365 struct bgp_path_info
*pi
;
5367 /* Do not install the aggregate route if BGP is in the
5368 * process of termination.
5370 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5371 (bgp
->peer_self
== NULL
))
5374 table
= bgp
->rib
[afi
][safi
];
5375 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5376 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5377 if (pi
->peer
== bgp
->peer_self
5378 && ((pi
->type
== ZEBRA_ROUTE_BGP
5379 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5380 || (pi
->type
!= ZEBRA_ROUTE_BGP
5382 == BGP_ROUTE_REDISTRIBUTE
))) {
5383 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5385 bgp_unlink_nexthop(pi
);
5386 bgp_path_info_delete(rn
, pi
);
5387 bgp_process(bgp
, rn
, afi
, safi
);
5394 * Purge all networks and redistributed routes from routing table.
5395 * Invoked upon the instance going down.
5397 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5402 FOREACH_AFI_SAFI (afi
, safi
)
5403 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5408 * Currently this is used to set static routes for VPN and ENCAP.
5409 * I think it can probably be factored with bgp_static_set.
5411 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5412 const char *ip_str
, const char *rd_str
,
5413 const char *label_str
, const char *rmap_str
,
5414 int evpn_type
, const char *esi
, const char *gwip
,
5415 const char *ethtag
, const char *routermac
)
5417 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5420 struct prefix_rd prd
;
5421 struct bgp_node
*prn
;
5422 struct bgp_node
*rn
;
5423 struct bgp_table
*table
;
5424 struct bgp_static
*bgp_static
;
5425 mpls_label_t label
= MPLS_INVALID_LABEL
;
5426 struct prefix gw_ip
;
5428 /* validate ip prefix */
5429 ret
= str2prefix(ip_str
, &p
);
5431 vty_out(vty
, "%% Malformed prefix\n");
5432 return CMD_WARNING_CONFIG_FAILED
;
5435 if ((afi
== AFI_L2VPN
)
5436 && (bgp_build_evpn_prefix(evpn_type
,
5437 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5438 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5439 return CMD_WARNING_CONFIG_FAILED
;
5442 ret
= str2prefix_rd(rd_str
, &prd
);
5444 vty_out(vty
, "%% Malformed rd\n");
5445 return CMD_WARNING_CONFIG_FAILED
;
5449 unsigned long label_val
;
5450 label_val
= strtoul(label_str
, NULL
, 10);
5451 encode_label(label_val
, &label
);
5454 if (safi
== SAFI_EVPN
) {
5455 if (esi
&& str2esi(esi
, NULL
) == 0) {
5456 vty_out(vty
, "%% Malformed ESI\n");
5457 return CMD_WARNING_CONFIG_FAILED
;
5459 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5460 vty_out(vty
, "%% Malformed Router MAC\n");
5461 return CMD_WARNING_CONFIG_FAILED
;
5464 memset(&gw_ip
, 0, sizeof(struct prefix
));
5465 ret
= str2prefix(gwip
, &gw_ip
);
5467 vty_out(vty
, "%% Malformed GatewayIp\n");
5468 return CMD_WARNING_CONFIG_FAILED
;
5470 if ((gw_ip
.family
== AF_INET
5471 && is_evpn_prefix_ipaddr_v6(
5472 (struct prefix_evpn
*)&p
))
5473 || (gw_ip
.family
== AF_INET6
5474 && is_evpn_prefix_ipaddr_v4(
5475 (struct prefix_evpn
*)&p
))) {
5477 "%% GatewayIp family differs with IP prefix\n");
5478 return CMD_WARNING_CONFIG_FAILED
;
5482 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5483 if (!bgp_node_has_bgp_path_info_data(prn
))
5484 bgp_node_set_bgp_table_info(prn
,
5485 bgp_table_init(bgp
, afi
, safi
));
5486 table
= bgp_node_get_bgp_table_info(prn
);
5488 rn
= bgp_node_get(table
, &p
);
5490 if (bgp_node_has_bgp_path_info_data(rn
)) {
5491 vty_out(vty
, "%% Same network configuration exists\n");
5492 bgp_unlock_node(rn
);
5494 /* New configuration. */
5495 bgp_static
= bgp_static_new();
5496 bgp_static
->backdoor
= 0;
5497 bgp_static
->valid
= 0;
5498 bgp_static
->igpmetric
= 0;
5499 bgp_static
->igpnexthop
.s_addr
= 0;
5500 bgp_static
->label
= label
;
5501 bgp_static
->prd
= prd
;
5504 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5505 route_map_counter_decrement(bgp_static
->rmap
.map
);
5506 bgp_static
->rmap
.name
=
5507 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5508 bgp_static
->rmap
.map
=
5509 route_map_lookup_by_name(rmap_str
);
5510 route_map_counter_increment(bgp_static
->rmap
.map
);
5513 if (safi
== SAFI_EVPN
) {
5515 bgp_static
->eth_s_id
=
5517 sizeof(struct eth_segment_id
));
5518 str2esi(esi
, bgp_static
->eth_s_id
);
5521 bgp_static
->router_mac
=
5522 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5523 (void)prefix_str2mac(routermac
,
5524 bgp_static
->router_mac
);
5527 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5529 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5531 bgp_static
->valid
= 1;
5532 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5538 /* Configure static BGP network. */
5539 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5540 const char *ip_str
, const char *rd_str
,
5541 const char *label_str
, int evpn_type
, const char *esi
,
5542 const char *gwip
, const char *ethtag
)
5544 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5547 struct prefix_rd prd
;
5548 struct bgp_node
*prn
;
5549 struct bgp_node
*rn
;
5550 struct bgp_table
*table
;
5551 struct bgp_static
*bgp_static
;
5552 mpls_label_t label
= MPLS_INVALID_LABEL
;
5554 /* Convert IP prefix string to struct prefix. */
5555 ret
= str2prefix(ip_str
, &p
);
5557 vty_out(vty
, "%% Malformed prefix\n");
5558 return CMD_WARNING_CONFIG_FAILED
;
5561 if ((afi
== AFI_L2VPN
)
5562 && (bgp_build_evpn_prefix(evpn_type
,
5563 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5564 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5565 return CMD_WARNING_CONFIG_FAILED
;
5567 ret
= str2prefix_rd(rd_str
, &prd
);
5569 vty_out(vty
, "%% Malformed rd\n");
5570 return CMD_WARNING_CONFIG_FAILED
;
5574 unsigned long label_val
;
5575 label_val
= strtoul(label_str
, NULL
, 10);
5576 encode_label(label_val
, &label
);
5579 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5580 if (!bgp_node_has_bgp_path_info_data(prn
))
5581 bgp_node_set_bgp_table_info(prn
,
5582 bgp_table_init(bgp
, afi
, safi
));
5584 bgp_unlock_node(prn
);
5585 table
= bgp_node_get_bgp_table_info(prn
);
5587 rn
= bgp_node_lookup(table
, &p
);
5590 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5592 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5593 bgp_static_free(bgp_static
);
5594 bgp_node_set_bgp_static_info(rn
, NULL
);
5595 bgp_unlock_node(rn
);
5596 bgp_unlock_node(rn
);
5598 vty_out(vty
, "%% Can't find the route\n");
5603 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5604 const char *rmap_name
)
5606 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5607 struct bgp_rmap
*rmap
;
5609 rmap
= &bgp
->table_map
[afi
][safi
];
5611 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5612 route_map_counter_decrement(rmap
->map
);
5613 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5614 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5615 route_map_counter_increment(rmap
->map
);
5617 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5618 route_map_counter_decrement(rmap
->map
);
5623 if (bgp_fibupd_safi(safi
))
5624 bgp_zebra_announce_table(bgp
, afi
, safi
);
5629 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5630 const char *rmap_name
)
5632 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5633 struct bgp_rmap
*rmap
;
5635 rmap
= &bgp
->table_map
[afi
][safi
];
5636 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5637 route_map_counter_decrement(rmap
->map
);
5641 if (bgp_fibupd_safi(safi
))
5642 bgp_zebra_announce_table(bgp
, afi
, safi
);
5647 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5650 if (bgp
->table_map
[afi
][safi
].name
) {
5651 vty_out(vty
, " table-map %s\n",
5652 bgp
->table_map
[afi
][safi
].name
);
5656 DEFUN (bgp_table_map
,
5659 "BGP table to RIB route download filter\n"
5660 "Name of the route map\n")
5663 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5664 argv
[idx_word
]->arg
);
5666 DEFUN (no_bgp_table_map
,
5667 no_bgp_table_map_cmd
,
5668 "no table-map WORD",
5670 "BGP table to RIB route download filter\n"
5671 "Name of the route map\n")
5674 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5675 argv
[idx_word
]->arg
);
5681 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5682 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5683 backdoor$backdoor}]",
5685 "Specify a network to announce via BGP\n"
5690 "Route-map to modify the attributes\n"
5691 "Name of the route map\n"
5692 "Label index to associate with the prefix\n"
5693 "Label index value\n"
5694 "Specify a BGP backdoor route\n")
5696 char addr_prefix_str
[BUFSIZ
];
5701 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5704 vty_out(vty
, "%% Inconsistent address and mask\n");
5705 return CMD_WARNING_CONFIG_FAILED
;
5709 return bgp_static_set(
5710 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5711 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5712 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5715 DEFPY(ipv6_bgp_network
,
5716 ipv6_bgp_network_cmd
,
5717 "[no] network X:X::X:X/M$prefix \
5718 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5720 "Specify a network to announce via BGP\n"
5722 "Route-map to modify the attributes\n"
5723 "Name of the route map\n"
5724 "Label index to associate with the prefix\n"
5725 "Label index value\n")
5727 return bgp_static_set(
5728 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5729 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5732 static struct bgp_aggregate
*bgp_aggregate_new(void)
5734 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5737 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5739 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
5740 route_map_counter_decrement(aggregate
->rmap
.map
);
5741 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5744 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5745 struct aspath
*aspath
,
5746 struct community
*comm
,
5747 struct ecommunity
*ecomm
,
5748 struct lcommunity
*lcomm
)
5750 static struct aspath
*ae
= NULL
;
5753 ae
= aspath_empty();
5758 if (origin
!= pi
->attr
->origin
)
5761 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5764 if (!community_cmp(pi
->attr
->community
, comm
))
5767 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5770 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5773 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5779 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5780 struct prefix
*p
, uint8_t origin
,
5781 struct aspath
*aspath
,
5782 struct community
*community
,
5783 struct ecommunity
*ecommunity
,
5784 struct lcommunity
*lcommunity
,
5785 uint8_t atomic_aggregate
,
5786 struct bgp_aggregate
*aggregate
)
5788 struct bgp_node
*rn
;
5789 struct bgp_table
*table
;
5790 struct bgp_path_info
*pi
, *orig
, *new;
5793 table
= bgp
->rib
[afi
][safi
];
5795 rn
= bgp_node_get(table
, p
);
5797 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5798 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5799 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5802 if (aggregate
->count
> 0) {
5804 * If the aggregate information has not changed
5805 * no need to re-install it again.
5807 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5808 ecommunity
, lcommunity
)) {
5809 bgp_unlock_node(rn
);
5812 aspath_free(aspath
);
5814 community_free(&community
);
5816 ecommunity_free(&ecommunity
);
5818 lcommunity_free(&lcommunity
);
5824 * Mark the old as unusable
5827 bgp_path_info_delete(rn
, pi
);
5829 attr
= bgp_attr_aggregate_intern(
5830 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
5831 aggregate
, atomic_aggregate
, p
);
5834 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
5838 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5839 bgp
->peer_self
, attr
, rn
);
5841 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5843 bgp_path_info_add(rn
, new);
5844 bgp_process(bgp
, rn
, afi
, safi
);
5846 for (pi
= orig
; pi
; pi
= pi
->next
)
5847 if (pi
->peer
== bgp
->peer_self
5848 && pi
->type
== ZEBRA_ROUTE_BGP
5849 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5852 /* Withdraw static BGP route from routing table. */
5854 bgp_path_info_delete(rn
, pi
);
5855 bgp_process(bgp
, rn
, afi
, safi
);
5859 bgp_unlock_node(rn
);
5862 /* Update an aggregate as routes are added/removed from the BGP table */
5863 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5864 afi_t afi
, safi_t safi
,
5865 struct bgp_aggregate
*aggregate
)
5867 struct bgp_table
*table
;
5868 struct bgp_node
*top
;
5869 struct bgp_node
*rn
;
5871 struct aspath
*aspath
= NULL
;
5872 struct community
*community
= NULL
;
5873 struct ecommunity
*ecommunity
= NULL
;
5874 struct lcommunity
*lcommunity
= NULL
;
5875 struct bgp_path_info
*pi
;
5876 unsigned long match
= 0;
5877 uint8_t atomic_aggregate
= 0;
5879 /* If the bgp instance is being deleted or self peer is deleted
5880 * then do not create aggregate route
5882 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5883 (bgp
->peer_self
== NULL
))
5886 /* ORIGIN attribute: If at least one route among routes that are
5887 aggregated has ORIGIN with the value INCOMPLETE, then the
5888 aggregated route must have the ORIGIN attribute with the value
5889 INCOMPLETE. Otherwise, if at least one route among routes that
5890 are aggregated has ORIGIN with the value EGP, then the aggregated
5891 route must have the origin attribute with the value EGP. In all
5892 other case the value of the ORIGIN attribute of the aggregated
5893 route is INTERNAL. */
5894 origin
= BGP_ORIGIN_IGP
;
5896 table
= bgp
->rib
[afi
][safi
];
5898 top
= bgp_node_get(table
, p
);
5899 for (rn
= bgp_node_get(table
, p
); rn
;
5900 rn
= bgp_route_next_until(rn
, top
)) {
5901 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5906 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5907 if (BGP_PATH_HOLDDOWN(pi
))
5911 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5912 atomic_aggregate
= 1;
5914 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5918 * summary-only aggregate route suppress
5919 * aggregated route announcements.
5921 if (aggregate
->summary_only
) {
5922 (bgp_path_info_extra_get(pi
))->suppress
++;
5923 bgp_path_info_set_flag(rn
, pi
,
5924 BGP_PATH_ATTR_CHANGED
);
5931 * If at least one route among routes that are
5932 * aggregated has ORIGIN with the value INCOMPLETE,
5933 * then the aggregated route MUST have the ORIGIN
5934 * attribute with the value INCOMPLETE. Otherwise, if
5935 * at least one route among routes that are aggregated
5936 * has ORIGIN with the value EGP, then the aggregated
5937 * route MUST have the ORIGIN attribute with the value
5940 switch (pi
->attr
->origin
) {
5941 case BGP_ORIGIN_INCOMPLETE
:
5942 aggregate
->incomplete_origin_count
++;
5944 case BGP_ORIGIN_EGP
:
5945 aggregate
->egp_origin_count
++;
5953 if (!aggregate
->as_set
)
5957 * as-set aggregate route generate origin, as path,
5958 * and community aggregation.
5960 /* Compute aggregate route's as-path.
5962 bgp_compute_aggregate_aspath_hash(aggregate
,
5965 /* Compute aggregate route's community.
5967 if (pi
->attr
->community
)
5968 bgp_compute_aggregate_community_hash(
5970 pi
->attr
->community
);
5972 /* Compute aggregate route's extended community.
5974 if (pi
->attr
->ecommunity
)
5975 bgp_compute_aggregate_ecommunity_hash(
5977 pi
->attr
->ecommunity
);
5979 /* Compute aggregate route's large community.
5981 if (pi
->attr
->lcommunity
)
5982 bgp_compute_aggregate_lcommunity_hash(
5984 pi
->attr
->lcommunity
);
5987 bgp_process(bgp
, rn
, afi
, safi
);
5989 if (aggregate
->as_set
) {
5990 bgp_compute_aggregate_aspath_val(aggregate
);
5991 bgp_compute_aggregate_community_val(aggregate
);
5992 bgp_compute_aggregate_ecommunity_val(aggregate
);
5993 bgp_compute_aggregate_lcommunity_val(aggregate
);
5997 bgp_unlock_node(top
);
6000 if (aggregate
->incomplete_origin_count
> 0)
6001 origin
= BGP_ORIGIN_INCOMPLETE
;
6002 else if (aggregate
->egp_origin_count
> 0)
6003 origin
= BGP_ORIGIN_EGP
;
6005 if (aggregate
->as_set
) {
6006 if (aggregate
->aspath
)
6007 /* Retrieve aggregate route's as-path.
6009 aspath
= aspath_dup(aggregate
->aspath
);
6011 if (aggregate
->community
)
6012 /* Retrieve aggregate route's community.
6014 community
= community_dup(aggregate
->community
);
6016 if (aggregate
->ecommunity
)
6017 /* Retrieve aggregate route's ecommunity.
6019 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6021 if (aggregate
->lcommunity
)
6022 /* Retrieve aggregate route's lcommunity.
6024 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6027 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6028 ecommunity
, lcommunity
, atomic_aggregate
,
6032 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6033 safi_t safi
, struct bgp_aggregate
*aggregate
)
6035 struct bgp_table
*table
;
6036 struct bgp_node
*top
;
6037 struct bgp_node
*rn
;
6038 struct bgp_path_info
*pi
;
6039 unsigned long match
;
6041 table
= bgp
->rib
[afi
][safi
];
6043 /* If routes exists below this node, generate aggregate routes. */
6044 top
= bgp_node_get(table
, p
);
6045 for (rn
= bgp_node_get(table
, p
); rn
;
6046 rn
= bgp_route_next_until(rn
, top
)) {
6047 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6051 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6052 if (BGP_PATH_HOLDDOWN(pi
))
6055 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6058 if (aggregate
->summary_only
&& pi
->extra
) {
6059 pi
->extra
->suppress
--;
6061 if (pi
->extra
->suppress
== 0) {
6062 bgp_path_info_set_flag(
6063 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6069 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6070 aggregate
->incomplete_origin_count
--;
6071 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6072 aggregate
->egp_origin_count
--;
6074 if (aggregate
->as_set
) {
6075 /* Remove as-path from aggregate.
6077 bgp_remove_aspath_from_aggregate_hash(
6081 if (pi
->attr
->community
)
6082 /* Remove community from aggregate.
6084 bgp_remove_comm_from_aggregate_hash(
6086 pi
->attr
->community
);
6088 if (pi
->attr
->ecommunity
)
6089 /* Remove ecommunity from aggregate.
6091 bgp_remove_ecomm_from_aggregate_hash(
6093 pi
->attr
->ecommunity
);
6095 if (pi
->attr
->lcommunity
)
6096 /* Remove lcommunity from aggregate.
6098 bgp_remove_lcomm_from_aggregate_hash(
6100 pi
->attr
->lcommunity
);
6105 /* If this node was suppressed, process the change. */
6107 bgp_process(bgp
, rn
, afi
, safi
);
6109 if (aggregate
->as_set
) {
6110 aspath_free(aggregate
->aspath
);
6111 aggregate
->aspath
= NULL
;
6112 if (aggregate
->community
)
6113 community_free(&aggregate
->community
);
6114 if (aggregate
->ecommunity
)
6115 ecommunity_free(&aggregate
->ecommunity
);
6116 if (aggregate
->lcommunity
)
6117 lcommunity_free(&aggregate
->lcommunity
);
6120 bgp_unlock_node(top
);
6123 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6124 struct bgp_path_info
*pinew
, afi_t afi
,
6126 struct bgp_aggregate
*aggregate
)
6129 struct aspath
*aspath
= NULL
;
6130 uint8_t atomic_aggregate
= 0;
6131 struct community
*community
= NULL
;
6132 struct ecommunity
*ecommunity
= NULL
;
6133 struct lcommunity
*lcommunity
= NULL
;
6135 /* ORIGIN attribute: If at least one route among routes that are
6136 * aggregated has ORIGIN with the value INCOMPLETE, then the
6137 * aggregated route must have the ORIGIN attribute with the value
6138 * INCOMPLETE. Otherwise, if at least one route among routes that
6139 * are aggregated has ORIGIN with the value EGP, then the aggregated
6140 * route must have the origin attribute with the value EGP. In all
6141 * other case the value of the ORIGIN attribute of the aggregated
6142 * route is INTERNAL.
6144 origin
= BGP_ORIGIN_IGP
;
6148 if (aggregate
->summary_only
)
6149 (bgp_path_info_extra_get(pinew
))->suppress
++;
6151 switch (pinew
->attr
->origin
) {
6152 case BGP_ORIGIN_INCOMPLETE
:
6153 aggregate
->incomplete_origin_count
++;
6155 case BGP_ORIGIN_EGP
:
6156 aggregate
->egp_origin_count
++;
6164 if (aggregate
->incomplete_origin_count
> 0)
6165 origin
= BGP_ORIGIN_INCOMPLETE
;
6166 else if (aggregate
->egp_origin_count
> 0)
6167 origin
= BGP_ORIGIN_EGP
;
6169 if (aggregate
->as_set
) {
6170 /* Compute aggregate route's as-path.
6172 bgp_compute_aggregate_aspath(aggregate
,
6173 pinew
->attr
->aspath
);
6175 /* Compute aggregate route's community.
6177 if (pinew
->attr
->community
)
6178 bgp_compute_aggregate_community(
6180 pinew
->attr
->community
);
6182 /* Compute aggregate route's extended community.
6184 if (pinew
->attr
->ecommunity
)
6185 bgp_compute_aggregate_ecommunity(
6187 pinew
->attr
->ecommunity
);
6189 /* Compute aggregate route's large community.
6191 if (pinew
->attr
->lcommunity
)
6192 bgp_compute_aggregate_lcommunity(
6194 pinew
->attr
->lcommunity
);
6196 /* Retrieve aggregate route's as-path.
6198 if (aggregate
->aspath
)
6199 aspath
= aspath_dup(aggregate
->aspath
);
6201 /* Retrieve aggregate route's community.
6203 if (aggregate
->community
)
6204 community
= community_dup(aggregate
->community
);
6206 /* Retrieve aggregate route's ecommunity.
6208 if (aggregate
->ecommunity
)
6209 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6211 /* Retrieve aggregate route's lcommunity.
6213 if (aggregate
->lcommunity
)
6214 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6217 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6218 aspath
, community
, ecommunity
,
6219 lcommunity
, atomic_aggregate
, aggregate
);
6222 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6224 struct bgp_path_info
*pi
,
6225 struct bgp_aggregate
*aggregate
,
6226 struct prefix
*aggr_p
)
6229 struct aspath
*aspath
= NULL
;
6230 uint8_t atomic_aggregate
= 0;
6231 struct community
*community
= NULL
;
6232 struct ecommunity
*ecommunity
= NULL
;
6233 struct lcommunity
*lcommunity
= NULL
;
6234 unsigned long match
= 0;
6236 if (BGP_PATH_HOLDDOWN(pi
))
6239 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6242 if (aggregate
->summary_only
6244 && pi
->extra
->suppress
> 0) {
6245 pi
->extra
->suppress
--;
6247 if (pi
->extra
->suppress
== 0) {
6248 bgp_path_info_set_flag(pi
->net
, pi
,
6249 BGP_PATH_ATTR_CHANGED
);
6254 if (aggregate
->count
> 0)
6257 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6258 aggregate
->incomplete_origin_count
--;
6259 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6260 aggregate
->egp_origin_count
--;
6262 if (aggregate
->as_set
) {
6263 /* Remove as-path from aggregate.
6265 bgp_remove_aspath_from_aggregate(aggregate
,
6268 if (pi
->attr
->community
)
6269 /* Remove community from aggregate.
6271 bgp_remove_community_from_aggregate(
6273 pi
->attr
->community
);
6275 if (pi
->attr
->ecommunity
)
6276 /* Remove ecommunity from aggregate.
6278 bgp_remove_ecommunity_from_aggregate(
6280 pi
->attr
->ecommunity
);
6282 if (pi
->attr
->lcommunity
)
6283 /* Remove lcommunity from aggregate.
6285 bgp_remove_lcommunity_from_aggregate(
6287 pi
->attr
->lcommunity
);
6290 /* If this node was suppressed, process the change. */
6292 bgp_process(bgp
, pi
->net
, afi
, safi
);
6294 origin
= BGP_ORIGIN_IGP
;
6295 if (aggregate
->incomplete_origin_count
> 0)
6296 origin
= BGP_ORIGIN_INCOMPLETE
;
6297 else if (aggregate
->egp_origin_count
> 0)
6298 origin
= BGP_ORIGIN_EGP
;
6300 if (aggregate
->as_set
) {
6301 /* Retrieve aggregate route's as-path.
6303 if (aggregate
->aspath
)
6304 aspath
= aspath_dup(aggregate
->aspath
);
6306 /* Retrieve aggregate route's community.
6308 if (aggregate
->community
)
6309 community
= community_dup(aggregate
->community
);
6311 /* Retrieve aggregate route's ecommunity.
6313 if (aggregate
->ecommunity
)
6314 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6316 /* Retrieve aggregate route's lcommunity.
6318 if (aggregate
->lcommunity
)
6319 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6322 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6323 aspath
, community
, ecommunity
,
6324 lcommunity
, atomic_aggregate
, aggregate
);
6327 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6328 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6330 struct bgp_node
*child
;
6331 struct bgp_node
*rn
;
6332 struct bgp_aggregate
*aggregate
;
6333 struct bgp_table
*table
;
6335 table
= bgp
->aggregate
[afi
][safi
];
6337 /* No aggregates configured. */
6338 if (bgp_table_top_nolock(table
) == NULL
)
6341 if (p
->prefixlen
== 0)
6344 if (BGP_PATH_HOLDDOWN(pi
))
6347 child
= bgp_node_get(table
, p
);
6349 /* Aggregate address configuration check. */
6350 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6351 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6352 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6353 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6357 bgp_unlock_node(child
);
6360 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6361 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6363 struct bgp_node
*child
;
6364 struct bgp_node
*rn
;
6365 struct bgp_aggregate
*aggregate
;
6366 struct bgp_table
*table
;
6368 table
= bgp
->aggregate
[afi
][safi
];
6370 /* No aggregates configured. */
6371 if (bgp_table_top_nolock(table
) == NULL
)
6374 if (p
->prefixlen
== 0)
6377 child
= bgp_node_get(table
, p
);
6379 /* Aggregate address configuration check. */
6380 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6381 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6382 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6383 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6384 del
, aggregate
, &rn
->p
);
6387 bgp_unlock_node(child
);
6390 /* Aggregate route attribute. */
6391 #define AGGREGATE_SUMMARY_ONLY 1
6392 #define AGGREGATE_AS_SET 1
6394 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6395 afi_t afi
, safi_t safi
)
6397 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6400 struct bgp_node
*rn
;
6401 struct bgp_aggregate
*aggregate
;
6403 /* Convert string to prefix structure. */
6404 ret
= str2prefix(prefix_str
, &p
);
6406 vty_out(vty
, "Malformed prefix\n");
6407 return CMD_WARNING_CONFIG_FAILED
;
6411 /* Old configuration check. */
6412 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6415 "%% There is no aggregate-address configuration.\n");
6416 return CMD_WARNING_CONFIG_FAILED
;
6419 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6420 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6421 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6422 NULL
, NULL
, 0, aggregate
);
6424 /* Unlock aggregate address configuration. */
6425 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6427 if (aggregate
->community
)
6428 community_free(&aggregate
->community
);
6430 if (aggregate
->community_hash
) {
6431 /* Delete all communities in the hash.
6433 hash_clean(aggregate
->community_hash
,
6434 bgp_aggr_community_remove
);
6435 /* Free up the community_hash.
6437 hash_free(aggregate
->community_hash
);
6440 if (aggregate
->ecommunity
)
6441 ecommunity_free(&aggregate
->ecommunity
);
6443 if (aggregate
->ecommunity_hash
) {
6444 /* Delete all ecommunities in the hash.
6446 hash_clean(aggregate
->ecommunity_hash
,
6447 bgp_aggr_ecommunity_remove
);
6448 /* Free up the ecommunity_hash.
6450 hash_free(aggregate
->ecommunity_hash
);
6453 if (aggregate
->lcommunity
)
6454 lcommunity_free(&aggregate
->lcommunity
);
6456 if (aggregate
->lcommunity_hash
) {
6457 /* Delete all lcommunities in the hash.
6459 hash_clean(aggregate
->lcommunity_hash
,
6460 bgp_aggr_lcommunity_remove
);
6461 /* Free up the lcommunity_hash.
6463 hash_free(aggregate
->lcommunity_hash
);
6466 if (aggregate
->aspath
)
6467 aspath_free(aggregate
->aspath
);
6469 if (aggregate
->aspath_hash
) {
6470 /* Delete all as-paths in the hash.
6472 hash_clean(aggregate
->aspath_hash
,
6473 bgp_aggr_aspath_remove
);
6474 /* Free up the aspath_hash.
6476 hash_free(aggregate
->aspath_hash
);
6479 bgp_aggregate_free(aggregate
);
6480 bgp_unlock_node(rn
);
6481 bgp_unlock_node(rn
);
6486 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6487 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6490 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6493 struct bgp_node
*rn
;
6494 struct bgp_aggregate
*aggregate
;
6496 /* Convert string to prefix structure. */
6497 ret
= str2prefix(prefix_str
, &p
);
6499 vty_out(vty
, "Malformed prefix\n");
6500 return CMD_WARNING_CONFIG_FAILED
;
6504 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6505 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6506 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6508 return CMD_WARNING_CONFIG_FAILED
;
6511 /* Old configuration check. */
6512 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6513 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6516 vty_out(vty
, "There is already same aggregate network.\n");
6517 /* try to remove the old entry */
6518 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6520 vty_out(vty
, "Error deleting aggregate.\n");
6521 bgp_unlock_node(rn
);
6522 return CMD_WARNING_CONFIG_FAILED
;
6526 /* Make aggregate address structure. */
6527 aggregate
= bgp_aggregate_new();
6528 aggregate
->summary_only
= summary_only
;
6529 aggregate
->as_set
= as_set
;
6530 aggregate
->safi
= safi
;
6533 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6534 route_map_counter_decrement(aggregate
->rmap
.map
);
6535 aggregate
->rmap
.name
=
6536 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6537 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6538 route_map_counter_increment(aggregate
->rmap
.map
);
6540 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6542 /* Aggregate address insert into BGP routing table. */
6543 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6548 DEFUN (aggregate_address
,
6549 aggregate_address_cmd
,
6550 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6551 "Configure BGP aggregate entries\n"
6552 "Aggregate prefix\n"
6553 "Generate AS set path information\n"
6554 "Filter more specific routes from updates\n"
6555 "Filter more specific routes from updates\n"
6556 "Generate AS set path information\n"
6557 "Apply route map to aggregate network\n"
6558 "Name of route map\n")
6561 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6562 char *prefix
= argv
[idx
]->arg
;
6565 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6567 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6568 ? AGGREGATE_SUMMARY_ONLY
6572 argv_find(argv
, argc
, "WORD", &idx
);
6574 rmap
= argv
[idx
]->arg
;
6576 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6577 rmap
, summary_only
, as_set
);
6580 DEFUN (aggregate_address_mask
,
6581 aggregate_address_mask_cmd
,
6582 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6583 "Configure BGP aggregate entries\n"
6584 "Aggregate address\n"
6586 "Generate AS set path information\n"
6587 "Filter more specific routes from updates\n"
6588 "Filter more specific routes from updates\n"
6589 "Generate AS set path information\n"
6590 "Apply route map to aggregate network\n"
6591 "Name of route map\n")
6594 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6595 char *prefix
= argv
[idx
]->arg
;
6596 char *mask
= argv
[idx
+ 1]->arg
;
6600 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6602 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6603 ? AGGREGATE_SUMMARY_ONLY
6606 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6608 rmap
= argv
[idx
]->arg
;
6610 char prefix_str
[BUFSIZ
];
6611 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6614 vty_out(vty
, "%% Inconsistent address and mask\n");
6615 return CMD_WARNING_CONFIG_FAILED
;
6618 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6619 rmap
, summary_only
, as_set
);
6622 DEFUN (no_aggregate_address
,
6623 no_aggregate_address_cmd
,
6624 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6626 "Configure BGP aggregate entries\n"
6627 "Aggregate prefix\n"
6628 "Generate AS set path information\n"
6629 "Filter more specific routes from updates\n"
6630 "Filter more specific routes from updates\n"
6631 "Generate AS set path information\n"
6632 "Apply route map to aggregate network\n"
6633 "Name of route map\n")
6636 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6637 char *prefix
= argv
[idx
]->arg
;
6638 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6641 DEFUN (no_aggregate_address_mask
,
6642 no_aggregate_address_mask_cmd
,
6643 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6645 "Configure BGP aggregate entries\n"
6646 "Aggregate address\n"
6648 "Generate AS set path information\n"
6649 "Filter more specific routes from updates\n"
6650 "Filter more specific routes from updates\n"
6651 "Generate AS set path information\n"
6652 "Apply route map to aggregate network\n"
6653 "Name of route map\n")
6656 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6657 char *prefix
= argv
[idx
]->arg
;
6658 char *mask
= argv
[idx
+ 1]->arg
;
6660 char prefix_str
[BUFSIZ
];
6661 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6664 vty_out(vty
, "%% Inconsistent address and mask\n");
6665 return CMD_WARNING_CONFIG_FAILED
;
6668 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6671 DEFUN (ipv6_aggregate_address
,
6672 ipv6_aggregate_address_cmd
,
6673 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6674 "Configure BGP aggregate entries\n"
6675 "Aggregate prefix\n"
6676 "Generate AS set path information\n"
6677 "Filter more specific routes from updates\n"
6678 "Filter more specific routes from updates\n"
6679 "Generate AS set path information\n"
6680 "Apply route map to aggregate network\n"
6681 "Name of route map\n")
6684 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6685 char *prefix
= argv
[idx
]->arg
;
6689 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6692 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6693 ? AGGREGATE_SUMMARY_ONLY
6696 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6698 rmap
= argv
[idx
]->arg
;
6700 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6704 DEFUN (no_ipv6_aggregate_address
,
6705 no_ipv6_aggregate_address_cmd
,
6706 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6708 "Configure BGP aggregate entries\n"
6709 "Aggregate prefix\n"
6710 "Generate AS set path information\n"
6711 "Filter more specific routes from updates\n"
6712 "Filter more specific routes from updates\n"
6713 "Generate AS set path information\n"
6714 "Apply route map to aggregate network\n"
6715 "Name of route map\n")
6718 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6719 char *prefix
= argv
[idx
]->arg
;
6720 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6723 /* Redistribute route treatment. */
6724 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6725 const union g_addr
*nexthop
, ifindex_t ifindex
,
6726 enum nexthop_types_t nhtype
, uint32_t metric
,
6727 uint8_t type
, unsigned short instance
,
6730 struct bgp_path_info
*new;
6731 struct bgp_path_info
*bpi
;
6732 struct bgp_path_info rmap_path
;
6733 struct bgp_node
*bn
;
6735 struct attr
*new_attr
;
6737 route_map_result_t ret
;
6738 struct bgp_redist
*red
;
6740 /* Make default attribute. */
6741 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6743 * This must not be NULL to satisfy Coverity SA
6745 assert(attr
.aspath
);
6748 case NEXTHOP_TYPE_IFINDEX
:
6750 case NEXTHOP_TYPE_IPV4
:
6751 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6752 attr
.nexthop
= nexthop
->ipv4
;
6754 case NEXTHOP_TYPE_IPV6
:
6755 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6756 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6757 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6759 case NEXTHOP_TYPE_BLACKHOLE
:
6760 switch (p
->family
) {
6762 attr
.nexthop
.s_addr
= INADDR_ANY
;
6765 memset(&attr
.mp_nexthop_global
, 0,
6766 sizeof(attr
.mp_nexthop_global
));
6767 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6772 attr
.nh_ifindex
= ifindex
;
6775 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6778 afi
= family2afi(p
->family
);
6780 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6782 struct attr attr_new
;
6784 /* Copy attribute for modification. */
6785 bgp_attr_dup(&attr_new
, &attr
);
6787 if (red
->redist_metric_flag
)
6788 attr_new
.med
= red
->redist_metric
;
6790 /* Apply route-map. */
6791 if (red
->rmap
.name
) {
6792 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6793 rmap_path
.peer
= bgp
->peer_self
;
6794 rmap_path
.attr
= &attr_new
;
6796 SET_FLAG(bgp
->peer_self
->rmap_type
,
6797 PEER_RMAP_TYPE_REDISTRIBUTE
);
6799 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6802 bgp
->peer_self
->rmap_type
= 0;
6804 if (ret
== RMAP_DENYMATCH
) {
6805 /* Free uninterned attribute. */
6806 bgp_attr_flush(&attr_new
);
6808 /* Unintern original. */
6809 aspath_unintern(&attr
.aspath
);
6810 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6815 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6816 bgp_attr_add_gshut_community(&attr_new
);
6818 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6819 SAFI_UNICAST
, p
, NULL
);
6821 new_attr
= bgp_attr_intern(&attr_new
);
6823 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6825 if (bpi
->peer
== bgp
->peer_self
6826 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6830 /* Ensure the (source route) type is updated. */
6832 if (attrhash_cmp(bpi
->attr
, new_attr
)
6833 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6834 bgp_attr_unintern(&new_attr
);
6835 aspath_unintern(&attr
.aspath
);
6836 bgp_unlock_node(bn
);
6839 /* The attribute is changed. */
6840 bgp_path_info_set_flag(bn
, bpi
,
6841 BGP_PATH_ATTR_CHANGED
);
6843 /* Rewrite BGP route information. */
6844 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6845 bgp_path_info_restore(bn
, bpi
);
6847 bgp_aggregate_decrement(
6848 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6849 bgp_attr_unintern(&bpi
->attr
);
6850 bpi
->attr
= new_attr
;
6851 bpi
->uptime
= bgp_clock();
6853 /* Process change. */
6854 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6856 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6857 bgp_unlock_node(bn
);
6858 aspath_unintern(&attr
.aspath
);
6860 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6862 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6864 vpn_leak_from_vrf_update(
6865 bgp_get_default(), bgp
, bpi
);
6871 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6872 bgp
->peer_self
, new_attr
, bn
);
6873 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6875 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6876 bgp_path_info_add(bn
, new);
6877 bgp_unlock_node(bn
);
6878 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6880 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6881 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6883 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6887 /* Unintern original. */
6888 aspath_unintern(&attr
.aspath
);
6891 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6892 unsigned short instance
)
6895 struct bgp_node
*rn
;
6896 struct bgp_path_info
*pi
;
6897 struct bgp_redist
*red
;
6899 afi
= family2afi(p
->family
);
6901 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6903 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6904 SAFI_UNICAST
, p
, NULL
);
6906 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6907 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6911 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6912 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6914 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6917 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6918 bgp_path_info_delete(rn
, pi
);
6919 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6921 bgp_unlock_node(rn
);
6925 /* Withdraw specified route type's route. */
6926 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6927 unsigned short instance
)
6929 struct bgp_node
*rn
;
6930 struct bgp_path_info
*pi
;
6931 struct bgp_table
*table
;
6933 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6935 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6936 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6937 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6938 && pi
->instance
== instance
)
6942 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6943 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6945 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6948 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6950 bgp_path_info_delete(rn
, pi
);
6951 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6956 /* Static function to display route. */
6957 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6964 if (p
->family
== AF_INET
) {
6968 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6971 json_object_string_add(json
, "prefix",
6972 inet_ntop(p
->family
,
6975 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6976 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6977 json_object_string_add(json
, "network", buf2
);
6979 } else if (p
->family
== AF_ETHERNET
) {
6980 prefix2str(p
, buf
, PREFIX_STRLEN
);
6981 len
= vty_out(vty
, "%s", buf
);
6982 } else if (p
->family
== AF_EVPN
) {
6986 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6989 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6990 } else if (p
->family
== AF_FLOWSPEC
) {
6991 route_vty_out_flowspec(vty
, p
, NULL
,
6993 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6994 NLRI_STRING_FORMAT_MIN
, json
);
6999 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7002 json_object_string_add(json
, "prefix",
7003 inet_ntop(p
->family
,
7006 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7007 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7008 json_object_string_add(json
, "network", buf2
);
7015 vty_out(vty
, "\n%*s", 20, " ");
7017 vty_out(vty
, "%*s", len
, " ");
7021 enum bgp_display_type
{
7025 /* Print the short form route status for a bgp_path_info */
7026 static void route_vty_short_status_out(struct vty
*vty
,
7027 struct bgp_path_info
*path
,
7028 json_object
*json_path
)
7032 /* Route status display. */
7033 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7034 json_object_boolean_true_add(json_path
, "removed");
7036 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7037 json_object_boolean_true_add(json_path
, "stale");
7039 if (path
->extra
&& path
->extra
->suppress
)
7040 json_object_boolean_true_add(json_path
, "suppressed");
7042 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7043 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7044 json_object_boolean_true_add(json_path
, "valid");
7047 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7048 json_object_boolean_true_add(json_path
, "history");
7050 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7051 json_object_boolean_true_add(json_path
, "damped");
7053 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7054 json_object_boolean_true_add(json_path
, "bestpath");
7056 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7057 json_object_boolean_true_add(json_path
, "multipath");
7059 /* Internal route. */
7060 if ((path
->peer
->as
)
7061 && (path
->peer
->as
== path
->peer
->local_as
))
7062 json_object_string_add(json_path
, "pathFrom",
7065 json_object_string_add(json_path
, "pathFrom",
7071 /* Route status display. */
7072 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7074 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7076 else if (path
->extra
&& path
->extra
->suppress
)
7078 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7079 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7085 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7087 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7089 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7091 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7096 /* Internal route. */
7097 if (path
->peer
&& (path
->peer
->as
)
7098 && (path
->peer
->as
== path
->peer
->local_as
))
7104 static char *bgp_nexthop_fqdn(struct peer
*peer
)
7106 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
))
7107 return peer
->hostname
;
7111 /* called from terminal list command */
7112 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7113 struct bgp_path_info
*path
, int display
, safi_t safi
,
7114 json_object
*json_paths
)
7117 json_object
*json_path
= NULL
;
7118 json_object
*json_nexthops
= NULL
;
7119 json_object
*json_nexthop_global
= NULL
;
7120 json_object
*json_nexthop_ll
= NULL
;
7121 json_object
*json_ext_community
= NULL
;
7122 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7124 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7125 bool nexthop_othervrf
= false;
7126 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7127 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7128 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
7131 json_path
= json_object_new_object();
7133 /* short status lead text */
7134 route_vty_short_status_out(vty
, path
, json_path
);
7137 /* print prefix and mask */
7139 route_vty_out_route(p
, vty
, json_path
);
7141 vty_out(vty
, "%*s", 17, " ");
7143 route_vty_out_route(p
, vty
, json_path
);
7146 /* Print attribute */
7150 * If vrf id of nexthop is different from that of prefix,
7151 * set up printable string to append
7153 if (path
->extra
&& path
->extra
->bgp_orig
) {
7154 const char *self
= "";
7159 nexthop_othervrf
= true;
7160 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7162 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7163 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7164 "@%s%s", VRFID_NONE_STR
, self
);
7166 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7167 path
->extra
->bgp_orig
->vrf_id
, self
);
7169 if (path
->extra
->bgp_orig
->inst_type
7170 != BGP_INSTANCE_TYPE_DEFAULT
)
7172 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7174 const char *self
= "";
7179 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7183 * For ENCAP and EVPN routes, nexthop address family is not
7184 * neccessarily the same as the prefix address family.
7185 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7186 * EVPN routes are also exchanged with a MP nexthop. Currently,
7188 * is only IPv4, the value will be present in either
7190 * attr->mp_nexthop_global_in
7192 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7195 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7199 sprintf(nexthop
, "%s",
7200 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7204 sprintf(nexthop
, "%s",
7205 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7209 sprintf(nexthop
, "?");
7214 json_nexthop_global
= json_object_new_object();
7216 json_object_string_add(
7217 json_nexthop_global
, "afi",
7218 nexthop_fqdn
? "fqdn"
7219 : (af
== AF_INET
) ? "ip" : "ipv6");
7220 json_object_string_add(
7221 json_nexthop_global
,
7222 nexthop_fqdn
? "fqdn"
7223 : (af
== AF_INET
) ? "ip" : "ipv6",
7224 nexthop_fqdn
? nexthop_fqdn
: nexthop
);
7225 json_object_boolean_true_add(json_nexthop_global
,
7228 vty_out(vty
, "%s%s",
7229 nexthop_fqdn
? nexthop_fqdn
: nexthop
,
7231 } else if (safi
== SAFI_EVPN
) {
7233 json_nexthop_global
= json_object_new_object();
7235 json_object_string_add(
7236 json_nexthop_global
,
7237 nexthop_fqdn
? "fqdn" : "ip",
7238 nexthop_fqdn
? nexthop_fqdn
7239 : inet_ntoa(attr
->nexthop
));
7240 json_object_string_add(json_nexthop_global
, "afi",
7242 json_object_boolean_true_add(json_nexthop_global
,
7245 vty_out(vty
, "%-16s%s",
7246 nexthop_fqdn
?: inet_ntoa(attr
->nexthop
),
7248 } else if (safi
== SAFI_FLOWSPEC
) {
7249 if (attr
->nexthop
.s_addr
!= 0) {
7251 json_nexthop_global
= json_object_new_object();
7252 json_object_string_add(
7253 json_nexthop_global
,
7254 nexthop_fqdn
? "fqdn" : "ip",
7257 : inet_ntoa(attr
->nexthop
));
7258 json_object_string_add(json_nexthop_global
,
7260 json_object_boolean_true_add(
7261 json_nexthop_global
,
7264 vty_out(vty
, "%-16s",
7267 : inet_ntoa(attr
->nexthop
));
7270 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7272 json_nexthop_global
= json_object_new_object();
7274 json_object_string_add(json_nexthop_global
,
7275 nexthop_fqdn
? "fqdn" : "ip",
7278 : inet_ntoa(attr
->nexthop
));
7280 json_object_string_add(json_nexthop_global
, "afi",
7282 json_object_boolean_true_add(json_nexthop_global
,
7287 snprintf(buf
, sizeof(buf
), "%s%s",
7288 nexthop_fqdn
? nexthop_fqdn
7289 : inet_ntoa(attr
->nexthop
),
7291 vty_out(vty
, "%-16s", buf
);
7296 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7301 json_nexthop_global
= json_object_new_object();
7302 json_object_string_add(
7303 json_nexthop_global
,
7304 nexthop_fqdn
? "fqdn" : "ip",
7307 : inet_ntop(AF_INET6
,
7308 &attr
->mp_nexthop_global
,
7310 json_object_string_add(json_nexthop_global
, "afi",
7312 json_object_string_add(json_nexthop_global
, "scope",
7315 /* We display both LL & GL if both have been
7317 if ((attr
->mp_nexthop_len
7318 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7319 || (path
->peer
->conf_if
)) {
7320 json_nexthop_ll
= json_object_new_object();
7321 json_object_string_add(
7323 nexthop_fqdn
? "fqdn" : "ip",
7328 &attr
->mp_nexthop_local
,
7330 json_object_string_add(json_nexthop_ll
, "afi",
7332 json_object_string_add(json_nexthop_ll
, "scope",
7335 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7336 &attr
->mp_nexthop_local
)
7338 && !attr
->mp_nexthop_prefer_global
)
7339 json_object_boolean_true_add(
7340 json_nexthop_ll
, "used");
7342 json_object_boolean_true_add(
7343 json_nexthop_global
, "used");
7345 json_object_boolean_true_add(
7346 json_nexthop_global
, "used");
7348 /* Display LL if LL/Global both in table unless
7349 * prefer-global is set */
7350 if (((attr
->mp_nexthop_len
7351 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7352 && !attr
->mp_nexthop_prefer_global
)
7353 || (path
->peer
->conf_if
)) {
7354 if (path
->peer
->conf_if
) {
7355 len
= vty_out(vty
, "%s",
7356 path
->peer
->conf_if
);
7357 len
= 16 - len
; /* len of IPv6
7363 vty_out(vty
, "\n%*s", 36, " ");
7365 vty_out(vty
, "%*s", len
, " ");
7373 &attr
->mp_nexthop_local
,
7379 vty_out(vty
, "\n%*s", 36, " ");
7381 vty_out(vty
, "%*s", len
, " ");
7390 &attr
->mp_nexthop_global
,
7396 vty_out(vty
, "\n%*s", 36, " ");
7398 vty_out(vty
, "%*s", len
, " ");
7404 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7408 * Adding "metric" field to match with corresponding
7409 * CLI. "med" will be deprecated in future.
7411 json_object_int_add(json_path
, "med", attr
->med
);
7412 json_object_int_add(json_path
, "metric", attr
->med
);
7414 vty_out(vty
, "%10u", attr
->med
);
7415 else if (!json_paths
)
7419 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7423 * Adding "locPrf" field to match with corresponding
7424 * CLI. "localPref" will be deprecated in future.
7426 json_object_int_add(json_path
, "localpref",
7428 json_object_int_add(json_path
, "locPrf",
7431 vty_out(vty
, "%7u", attr
->local_pref
);
7432 else if (!json_paths
)
7436 json_object_int_add(json_path
, "weight", attr
->weight
);
7438 vty_out(vty
, "%7u ", attr
->weight
);
7442 json_object_string_add(
7443 json_path
, "peerId",
7444 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7452 * Adding "path" field to match with corresponding
7453 * CLI. "aspath" will be deprecated in future.
7455 json_object_string_add(json_path
, "aspath",
7457 json_object_string_add(json_path
, "path",
7460 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7465 json_object_string_add(json_path
, "origin",
7466 bgp_origin_long_str
[attr
->origin
]);
7468 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7471 if (safi
== SAFI_EVPN
&&
7472 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7473 json_ext_community
= json_object_new_object();
7474 json_object_string_add(json_ext_community
,
7476 attr
->ecommunity
->str
);
7477 json_object_object_add(json_path
,
7478 "extendedCommunity",
7479 json_ext_community
);
7483 json_object_boolean_true_add(json_path
,
7484 "announceNexthopSelf");
7485 if (nexthop_othervrf
) {
7486 json_object_string_add(json_path
, "nhVrfName",
7489 json_object_int_add(json_path
, "nhVrfId",
7490 ((nexthop_vrfid
== VRF_UNKNOWN
)
7492 : (int)nexthop_vrfid
));
7497 if (json_nexthop_global
|| json_nexthop_ll
) {
7498 json_nexthops
= json_object_new_array();
7500 if (json_nexthop_global
)
7501 json_object_array_add(json_nexthops
,
7502 json_nexthop_global
);
7504 if (json_nexthop_ll
)
7505 json_object_array_add(json_nexthops
,
7508 json_object_object_add(json_path
, "nexthops",
7512 json_object_array_add(json_paths
, json_path
);
7516 if (safi
== SAFI_EVPN
&&
7517 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7518 vty_out(vty
, "%*s", 20, " ");
7519 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7523 /* prints an additional line, indented, with VNC info, if
7525 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7526 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7531 /* called from terminal list command */
7532 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7533 safi_t safi
, bool use_json
, json_object
*json_ar
)
7535 json_object
*json_status
= NULL
;
7536 json_object
*json_net
= NULL
;
7539 /* Route status display. */
7541 json_status
= json_object_new_object();
7542 json_net
= json_object_new_object();
7549 /* print prefix and mask */
7551 if (safi
== SAFI_EVPN
)
7552 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7553 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7554 json_object_string_add(
7555 json_net
, "addrPrefix",
7556 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7558 json_object_int_add(json_net
, "prefixLen",
7560 prefix2str(p
, buff
, PREFIX_STRLEN
);
7561 json_object_string_add(json_net
, "network", buff
);
7564 route_vty_out_route(p
, vty
, NULL
);
7566 /* Print attribute */
7569 if (p
->family
== AF_INET
7570 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7571 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7572 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7573 json_object_string_add(
7574 json_net
, "nextHop",
7576 attr
->mp_nexthop_global_in
));
7578 json_object_string_add(
7579 json_net
, "nextHop",
7580 inet_ntoa(attr
->nexthop
));
7581 } else if (p
->family
== AF_INET6
7582 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7585 json_object_string_add(
7586 json_net
, "nextHopGlobal",
7588 &attr
->mp_nexthop_global
, buf
,
7590 } else if (p
->family
== AF_EVPN
&&
7591 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7592 json_object_string_add(json_net
,
7593 "nextHop", inet_ntoa(
7594 attr
->mp_nexthop_global_in
));
7597 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7598 json_object_int_add(json_net
, "metric",
7601 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7604 * Adding "locPrf" field to match with
7605 * corresponding CLI. "localPref" will be
7606 * deprecated in future.
7608 json_object_int_add(json_net
, "localPref",
7610 json_object_int_add(json_net
, "locPrf",
7614 json_object_int_add(json_net
, "weight", attr
->weight
);
7620 * Adding "path" field to match with
7621 * corresponding CLI. "localPref" will be
7622 * deprecated in future.
7624 json_object_string_add(json_net
, "asPath",
7626 json_object_string_add(json_net
, "path",
7631 json_object_string_add(json_net
, "bgpOriginCode",
7632 bgp_origin_str
[attr
->origin
]);
7634 if (p
->family
== AF_INET
7635 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7636 || safi
== SAFI_EVPN
7637 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7638 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7639 || safi
== SAFI_EVPN
)
7640 vty_out(vty
, "%-16s",
7642 attr
->mp_nexthop_global_in
));
7644 vty_out(vty
, "%-16s",
7645 inet_ntoa(attr
->nexthop
));
7646 } else if (p
->family
== AF_INET6
7647 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7654 &attr
->mp_nexthop_global
, buf
,
7658 vty_out(vty
, "\n%*s", 36, " ");
7660 vty_out(vty
, "%*s", len
, " ");
7663 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7664 vty_out(vty
, "%10u", attr
->med
);
7668 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7669 vty_out(vty
, "%7u", attr
->local_pref
);
7673 vty_out(vty
, "%7u ", attr
->weight
);
7677 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7680 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7684 json_object_boolean_true_add(json_status
, "*");
7685 json_object_boolean_true_add(json_status
, ">");
7686 json_object_object_add(json_net
, "appliedStatusSymbols",
7689 prefix2str(p
, buff
, PREFIX_STRLEN
);
7690 json_object_object_add(json_ar
, buff
, json_net
);
7695 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7696 struct bgp_path_info
*path
, int display
, safi_t safi
,
7699 json_object
*json_out
= NULL
;
7701 mpls_label_t label
= MPLS_INVALID_LABEL
;
7707 json_out
= json_object_new_object();
7709 /* short status lead text */
7710 route_vty_short_status_out(vty
, path
, json_out
);
7712 /* print prefix and mask */
7715 route_vty_out_route(p
, vty
, NULL
);
7717 vty_out(vty
, "%*s", 17, " ");
7720 /* Print attribute */
7722 if (((p
->family
== AF_INET
)
7723 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7724 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7725 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7726 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7727 || safi
== SAFI_EVPN
) {
7729 json_object_string_add(
7730 json_out
, "mpNexthopGlobalIn",
7731 inet_ntoa(attr
->mp_nexthop_global_in
));
7733 vty_out(vty
, "%-16s",
7734 inet_ntoa(attr
->mp_nexthop_global_in
));
7737 json_object_string_add(
7738 json_out
, "nexthop",
7739 inet_ntoa(attr
->nexthop
));
7741 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
7743 } else if (((p
->family
== AF_INET6
)
7744 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7745 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7746 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7749 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7751 json_object_string_add(
7752 json_out
, "mpNexthopGlobalIn",
7754 &attr
->mp_nexthop_global
,
7755 buf_a
, sizeof(buf_a
)));
7759 &attr
->mp_nexthop_global
,
7760 buf_a
, sizeof(buf_a
)));
7761 } else if (attr
->mp_nexthop_len
7762 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7763 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
7764 &attr
->mp_nexthop_global
,
7765 &attr
->mp_nexthop_local
);
7767 json_object_string_add(json_out
,
7768 "mpNexthopGlobalLocal",
7771 vty_out(vty
, "%s", buf_a
);
7775 label
= decode_label(&path
->extra
->label
[0]);
7777 if (bgp_is_valid_label(&label
)) {
7779 json_object_int_add(json_out
, "notag", label
);
7780 json_object_array_add(json
, json_out
);
7782 vty_out(vty
, "notag/%d", label
);
7788 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7789 struct bgp_path_info
*path
, int display
,
7790 json_object
*json_paths
)
7793 char buf
[BUFSIZ
] = {0};
7794 json_object
*json_path
= NULL
;
7795 json_object
*json_nexthop
= NULL
;
7796 json_object
*json_overlay
= NULL
;
7802 json_path
= json_object_new_object();
7803 json_overlay
= json_object_new_object();
7804 json_nexthop
= json_object_new_object();
7807 /* short status lead text */
7808 route_vty_short_status_out(vty
, path
, json_path
);
7810 /* print prefix and mask */
7812 route_vty_out_route(p
, vty
, json_path
);
7814 vty_out(vty
, "%*s", 17, " ");
7816 /* Print attribute */
7819 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7823 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
7825 vty_out(vty
, "%-16s", buf
);
7827 json_object_string_add(json_nexthop
, "ip", buf
);
7829 json_object_string_add(json_nexthop
, "afi", "ipv4");
7831 json_object_object_add(json_path
, "nexthop",
7836 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
7837 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
7839 vty_out(vty
, "%s(%s)", buf
, buf1
);
7841 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
7843 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
7846 json_object_string_add(json_nexthop
, "afi", "ipv6");
7848 json_object_object_add(json_path
, "nexthop",
7856 json_object_string_add(json_nexthop
, "Error",
7857 "Unsupported address-family");
7861 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7864 vty_out(vty
, "%s", str
);
7866 json_object_string_add(json_overlay
, "esi", str
);
7868 XFREE(MTYPE_TMP
, str
);
7870 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7871 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
7873 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7874 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7879 vty_out(vty
, "/%s", buf
);
7881 json_object_string_add(json_overlay
, "gw", buf
);
7883 if (attr
->ecommunity
) {
7885 struct ecommunity_val
*routermac
= ecommunity_lookup(
7886 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7887 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7890 mac
= ecom_mac2str((char *)routermac
->val
);
7893 vty_out(vty
, "/%s", (char *)mac
);
7895 json_object_string_add(json_overlay
, "rmac",
7898 XFREE(MTYPE_TMP
, mac
);
7905 json_object_object_add(json_path
, "overlay", json_overlay
);
7907 json_object_array_add(json_paths
, json_path
);
7911 /* dampening route */
7912 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7913 struct bgp_path_info
*path
, int display
, afi_t afi
,
7914 safi_t safi
, bool use_json
, json_object
*json
)
7918 char timebuf
[BGP_UPTIME_LEN
];
7920 /* short status lead text */
7921 route_vty_short_status_out(vty
, path
, json
);
7923 /* print prefix and mask */
7926 route_vty_out_route(p
, vty
, NULL
);
7928 vty_out(vty
, "%*s", 17, " ");
7931 len
= vty_out(vty
, "%s", path
->peer
->host
);
7935 vty_out(vty
, "\n%*s", 34, " ");
7938 json_object_int_add(json
, "peerHost", len
);
7940 vty_out(vty
, "%*s", len
, " ");
7944 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
7945 safi
, use_json
, json
);
7948 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7949 BGP_UPTIME_LEN
, afi
, safi
,
7952 /* Print attribute */
7958 json_object_string_add(json
, "asPath",
7961 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7966 json_object_string_add(json
, "origin",
7967 bgp_origin_str
[attr
->origin
]);
7969 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7976 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7977 struct bgp_path_info
*path
, int display
, afi_t afi
,
7978 safi_t safi
, bool use_json
, json_object
*json
)
7981 struct bgp_damp_info
*bdi
;
7982 char timebuf
[BGP_UPTIME_LEN
];
7988 bdi
= path
->extra
->damp_info
;
7990 /* short status lead text */
7991 route_vty_short_status_out(vty
, path
, json
);
7993 /* print prefix and mask */
7996 route_vty_out_route(p
, vty
, NULL
);
7998 vty_out(vty
, "%*s", 17, " ");
8001 len
= vty_out(vty
, "%s", path
->peer
->host
);
8005 vty_out(vty
, "\n%*s", 33, " ");
8008 json_object_int_add(json
, "peerHost", len
);
8010 vty_out(vty
, "%*s", len
, " ");
8013 len
= vty_out(vty
, "%d", bdi
->flap
);
8020 json_object_int_add(json
, "bdiFlap", len
);
8022 vty_out(vty
, "%*s", len
, " ");
8026 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8029 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8030 BGP_UPTIME_LEN
, 0, NULL
));
8032 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8033 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8035 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8036 BGP_UPTIME_LEN
, afi
, safi
,
8040 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8041 BGP_UPTIME_LEN
, afi
,
8042 safi
, use_json
, json
));
8045 vty_out(vty
, "%*s ", 8, " ");
8048 /* Print attribute */
8054 json_object_string_add(json
, "asPath",
8057 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8062 json_object_string_add(json
, "origin",
8063 bgp_origin_str
[attr
->origin
]);
8065 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8071 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8072 int *first
, const char *header
,
8073 json_object
*json_adv_to
)
8075 char buf1
[INET6_ADDRSTRLEN
];
8076 json_object
*json_peer
= NULL
;
8079 /* 'advertised-to' is a dictionary of peers we have advertised
8081 * prefix too. The key is the peer's IP or swpX, the value is
8083 * hostname if we know it and "" if not.
8085 json_peer
= json_object_new_object();
8088 json_object_string_add(json_peer
, "hostname",
8092 json_object_object_add(json_adv_to
, peer
->conf_if
,
8095 json_object_object_add(
8097 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8101 vty_out(vty
, "%s", header
);
8106 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8108 vty_out(vty
, " %s(%s)", peer
->hostname
,
8111 vty_out(vty
, " %s(%s)", peer
->hostname
,
8112 sockunion2str(&peer
->su
, buf1
,
8116 vty_out(vty
, " %s", peer
->conf_if
);
8119 sockunion2str(&peer
->su
, buf1
,
8125 static void route_vty_out_tx_ids(struct vty
*vty
,
8126 struct bgp_addpath_info_data
*d
)
8130 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8131 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8132 d
->addpath_tx_id
[i
],
8133 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8137 static const char *bgp_path_selection_reason2str(
8138 enum bgp_path_selection_reason reason
)
8141 case bgp_path_selection_none
:
8142 return "Nothing to Select";
8144 case bgp_path_selection_first
:
8145 return "First path received";
8147 case bgp_path_selection_evpn_sticky_mac
:
8148 return "EVPN Sticky Mac";
8150 case bgp_path_selection_evpn_seq
:
8151 return "EVPN sequence number";
8153 case bgp_path_selection_evpn_lower_ip
:
8154 return "EVPN lower IP";
8156 case bgp_path_selection_weight
:
8159 case bgp_path_selection_local_pref
:
8160 return "Local Pref";
8162 case bgp_path_selection_local_route
:
8163 return "Local Route";
8165 case bgp_path_selection_confed_as_path
:
8166 return "Confederation based AS Path";
8168 case bgp_path_selection_as_path
:
8171 case bgp_path_selection_origin
:
8174 case bgp_path_selection_med
:
8177 case bgp_path_selection_peer
:
8180 case bgp_path_selection_confed
:
8181 return "Confed Peer Type";
8183 case bgp_path_selection_igp_metric
:
8184 return "IGP Metric";
8186 case bgp_path_selection_older
:
8187 return "Older Path";
8189 case bgp_path_selection_router_id
:
8192 case bgp_path_selection_cluster_length
:
8193 return "Cluser length";
8195 case bgp_path_selection_stale
:
8196 return "Path Staleness";
8198 case bgp_path_selection_local_configured
:
8199 return "Locally configured route";
8201 case bgp_path_selection_neighbor_ip
:
8202 return "Neighbor IP";
8204 case bgp_path_selection_default
:
8205 return "Nothing left to compare";
8208 return "Invalid (internal error)";
8211 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8212 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8213 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8215 char buf
[INET6_ADDRSTRLEN
];
8217 char buf2
[EVPN_ROUTE_STRLEN
];
8219 int sockunion_vty_out(struct vty
*, union sockunion
*);
8221 json_object
*json_bestpath
= NULL
;
8222 json_object
*json_cluster_list
= NULL
;
8223 json_object
*json_cluster_list_list
= NULL
;
8224 json_object
*json_ext_community
= NULL
;
8225 json_object
*json_last_update
= NULL
;
8226 json_object
*json_pmsi
= NULL
;
8227 json_object
*json_nexthop_global
= NULL
;
8228 json_object
*json_nexthop_ll
= NULL
;
8229 json_object
*json_nexthops
= NULL
;
8230 json_object
*json_path
= NULL
;
8231 json_object
*json_peer
= NULL
;
8232 json_object
*json_string
= NULL
;
8233 json_object
*json_adv_to
= NULL
;
8235 struct listnode
*node
, *nnode
;
8237 int addpath_capable
;
8239 unsigned int first_as
;
8241 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8243 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
8246 json_path
= json_object_new_object();
8247 json_peer
= json_object_new_object();
8248 json_nexthop_global
= json_object_new_object();
8256 if (path
->extra
&& path
->extra
->num_labels
) {
8257 bgp_evpn_label2str(path
->extra
->label
,
8258 path
->extra
->num_labels
, tag_buf
,
8261 if (safi
== SAFI_EVPN
) {
8263 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8264 buf2
, sizeof(buf2
));
8265 vty_out(vty
, " Route %s", buf2
);
8266 if (tag_buf
[0] != '\0')
8267 vty_out(vty
, " VNI %s", tag_buf
);
8271 json_object_string_add(json_path
, "VNI",
8276 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8277 struct bgp_path_info
*parent_ri
;
8278 struct bgp_node
*rn
, *prn
;
8280 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8281 rn
= parent_ri
->net
;
8282 if (rn
&& rn
->prn
) {
8284 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8285 buf1
, sizeof(buf1
));
8286 if (is_pi_family_evpn(parent_ri
)) {
8287 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8288 buf2
, sizeof(buf2
));
8289 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8291 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8298 /* Line1 display AS-path, Aggregator */
8301 if (!attr
->aspath
->json
)
8302 aspath_str_update(attr
->aspath
, true);
8303 json_object_lock(attr
->aspath
->json
);
8304 json_object_object_add(json_path
, "aspath",
8305 attr
->aspath
->json
);
8307 if (attr
->aspath
->segments
)
8308 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8310 vty_out(vty
, " Local");
8314 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8316 json_object_boolean_true_add(json_path
, "removed");
8318 vty_out(vty
, ", (removed)");
8321 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8323 json_object_boolean_true_add(json_path
, "stale");
8325 vty_out(vty
, ", (stale)");
8328 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8330 json_object_int_add(json_path
, "aggregatorAs",
8331 attr
->aggregator_as
);
8332 json_object_string_add(
8333 json_path
, "aggregatorId",
8334 inet_ntoa(attr
->aggregator_addr
));
8336 vty_out(vty
, ", (aggregated by %u %s)",
8337 attr
->aggregator_as
,
8338 inet_ntoa(attr
->aggregator_addr
));
8342 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8343 PEER_FLAG_REFLECTOR_CLIENT
)) {
8345 json_object_boolean_true_add(json_path
,
8346 "rxedFromRrClient");
8348 vty_out(vty
, ", (Received from a RR-client)");
8351 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8352 PEER_FLAG_RSERVER_CLIENT
)) {
8354 json_object_boolean_true_add(json_path
,
8355 "rxedFromRsClient");
8357 vty_out(vty
, ", (Received from a RS-client)");
8360 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8362 json_object_boolean_true_add(json_path
,
8363 "dampeningHistoryEntry");
8365 vty_out(vty
, ", (history entry)");
8366 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8368 json_object_boolean_true_add(json_path
,
8369 "dampeningSuppressed");
8371 vty_out(vty
, ", (suppressed due to dampening)");
8377 /* Line2 display Next-hop, Neighbor, Router-id */
8378 /* Display the nexthop */
8379 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8380 || bn
->p
.family
== AF_EVPN
)
8381 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8382 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8383 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8384 || safi
== SAFI_EVPN
) {
8386 json_object_string_add(
8387 json_nexthop_global
,
8388 nexthop_fqdn
? "fqdn" : "ip",
8392 attr
->mp_nexthop_global_in
));
8398 attr
->mp_nexthop_global_in
));
8401 json_object_string_add(
8402 json_nexthop_global
,
8403 nexthop_fqdn
? "fqdn" : "ip",
8406 : inet_ntoa(attr
->nexthop
));
8411 : inet_ntoa(attr
->nexthop
));
8415 json_object_string_add(json_nexthop_global
, "afi",
8419 json_object_string_add(
8420 json_nexthop_global
,
8421 nexthop_fqdn
? "fqdn" : "ip",
8424 : inet_ntop(AF_INET6
,
8425 &attr
->mp_nexthop_global
,
8426 buf
, INET6_ADDRSTRLEN
));
8427 json_object_string_add(json_nexthop_global
, "afi",
8429 json_object_string_add(json_nexthop_global
, "scope",
8435 : inet_ntop(AF_INET6
,
8436 &attr
->mp_nexthop_global
,
8437 buf
, INET6_ADDRSTRLEN
));
8441 /* Display the IGP cost or 'inaccessible' */
8442 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8444 json_object_boolean_false_add(json_nexthop_global
,
8447 vty_out(vty
, " (inaccessible)");
8449 if (path
->extra
&& path
->extra
->igpmetric
) {
8451 json_object_int_add(json_nexthop_global
,
8453 path
->extra
->igpmetric
);
8455 vty_out(vty
, " (metric %u)",
8456 path
->extra
->igpmetric
);
8459 /* IGP cost is 0, display this only for json */
8462 json_object_int_add(json_nexthop_global
,
8467 json_object_boolean_true_add(json_nexthop_global
,
8471 /* Display peer "from" output */
8472 /* This path was originated locally */
8473 if (path
->peer
== bgp
->peer_self
) {
8475 if (safi
== SAFI_EVPN
8476 || (bn
->p
.family
== AF_INET
8477 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8479 json_object_string_add(json_peer
, "peerId",
8482 vty_out(vty
, " from 0.0.0.0 ");
8485 json_object_string_add(json_peer
, "peerId",
8488 vty_out(vty
, " from :: ");
8492 json_object_string_add(json_peer
, "routerId",
8493 inet_ntoa(bgp
->router_id
));
8495 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8498 /* We RXed this path from one of our peers */
8502 json_object_string_add(json_peer
, "peerId",
8503 sockunion2str(&path
->peer
->su
,
8506 json_object_string_add(json_peer
, "routerId",
8508 &path
->peer
->remote_id
,
8509 buf1
, sizeof(buf1
)));
8511 if (path
->peer
->hostname
)
8512 json_object_string_add(json_peer
, "hostname",
8513 path
->peer
->hostname
);
8515 if (path
->peer
->domainname
)
8516 json_object_string_add(json_peer
, "domainname",
8517 path
->peer
->domainname
);
8519 if (path
->peer
->conf_if
)
8520 json_object_string_add(json_peer
, "interface",
8521 path
->peer
->conf_if
);
8523 if (path
->peer
->conf_if
) {
8524 if (path
->peer
->hostname
8525 && bgp_flag_check(path
->peer
->bgp
,
8526 BGP_FLAG_SHOW_HOSTNAME
))
8527 vty_out(vty
, " from %s(%s)",
8528 path
->peer
->hostname
,
8529 path
->peer
->conf_if
);
8531 vty_out(vty
, " from %s",
8532 path
->peer
->conf_if
);
8534 if (path
->peer
->hostname
8535 && bgp_flag_check(path
->peer
->bgp
,
8536 BGP_FLAG_SHOW_HOSTNAME
))
8537 vty_out(vty
, " from %s(%s)",
8538 path
->peer
->hostname
,
8541 vty_out(vty
, " from %s",
8542 sockunion2str(&path
->peer
->su
,
8547 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8548 vty_out(vty
, " (%s)",
8549 inet_ntoa(attr
->originator_id
));
8551 vty_out(vty
, " (%s)",
8553 &path
->peer
->remote_id
, buf1
,
8559 * Note when vrfid of nexthop is different from that of prefix
8561 if (path
->extra
&& path
->extra
->bgp_orig
) {
8562 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8567 if (path
->extra
->bgp_orig
->inst_type
8568 == BGP_INSTANCE_TYPE_DEFAULT
)
8569 vn
= VRF_DEFAULT_NAME
;
8571 vn
= path
->extra
->bgp_orig
->name
;
8573 json_object_string_add(json_path
, "nhVrfName", vn
);
8575 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8576 json_object_int_add(json_path
, "nhVrfId", -1);
8578 json_object_int_add(json_path
, "nhVrfId",
8579 (int)nexthop_vrfid
);
8582 if (nexthop_vrfid
== VRF_UNKNOWN
)
8583 vty_out(vty
, " vrf ?");
8585 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8591 json_object_boolean_true_add(json_path
,
8592 "announceNexthopSelf");
8594 vty_out(vty
, " announce-nh-self");
8601 /* display the link-local nexthop */
8602 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8604 json_nexthop_ll
= json_object_new_object();
8605 json_object_string_add(
8606 json_nexthop_ll
, nexthop_fqdn
? "fqdn" : "ip",
8609 : inet_ntop(AF_INET6
,
8610 &attr
->mp_nexthop_local
,
8611 buf
, INET6_ADDRSTRLEN
));
8612 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8613 json_object_string_add(json_nexthop_ll
, "scope",
8616 json_object_boolean_true_add(json_nexthop_ll
,
8619 if (!attr
->mp_nexthop_prefer_global
)
8620 json_object_boolean_true_add(json_nexthop_ll
,
8623 json_object_boolean_true_add(
8624 json_nexthop_global
, "used");
8626 vty_out(vty
, " (%s) %s\n",
8627 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8628 buf
, INET6_ADDRSTRLEN
),
8629 attr
->mp_nexthop_prefer_global
8634 /* If we do not have a link-local nexthop then we must flag the
8638 json_object_boolean_true_add(json_nexthop_global
,
8642 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8643 * Int/Ext/Local, Atomic, best */
8645 json_object_string_add(json_path
, "origin",
8646 bgp_origin_long_str
[attr
->origin
]);
8648 vty_out(vty
, " Origin %s",
8649 bgp_origin_long_str
[attr
->origin
]);
8651 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8654 * Adding "metric" field to match with
8655 * corresponding CLI. "med" will be
8656 * deprecated in future.
8658 json_object_int_add(json_path
, "med", attr
->med
);
8659 json_object_int_add(json_path
, "metric", attr
->med
);
8661 vty_out(vty
, ", metric %u", attr
->med
);
8664 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8666 json_object_int_add(json_path
, "localpref",
8669 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8672 if (attr
->weight
!= 0) {
8674 json_object_int_add(json_path
, "weight", attr
->weight
);
8676 vty_out(vty
, ", weight %u", attr
->weight
);
8679 if (attr
->tag
!= 0) {
8681 json_object_int_add(json_path
, "tag", attr
->tag
);
8683 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
8686 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8688 json_object_boolean_false_add(json_path
, "valid");
8690 vty_out(vty
, ", invalid");
8691 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8693 json_object_boolean_true_add(json_path
, "valid");
8695 vty_out(vty
, ", valid");
8698 if (path
->peer
!= bgp
->peer_self
) {
8699 if (path
->peer
->as
== path
->peer
->local_as
) {
8700 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
8702 json_object_string_add(
8706 vty_out(vty
, ", confed-internal");
8709 json_object_string_add(
8710 json_peer
, "type", "internal");
8712 vty_out(vty
, ", internal");
8715 if (bgp_confederation_peers_check(bgp
,
8718 json_object_string_add(
8722 vty_out(vty
, ", confed-external");
8725 json_object_string_add(
8726 json_peer
, "type", "external");
8728 vty_out(vty
, ", external");
8731 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8733 json_object_boolean_true_add(json_path
, "aggregated");
8734 json_object_boolean_true_add(json_path
, "local");
8736 vty_out(vty
, ", aggregated, local");
8738 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8740 json_object_boolean_true_add(json_path
, "sourced");
8742 vty_out(vty
, ", sourced");
8745 json_object_boolean_true_add(json_path
, "sourced");
8746 json_object_boolean_true_add(json_path
, "local");
8748 vty_out(vty
, ", sourced, local");
8752 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8754 json_object_boolean_true_add(json_path
,
8757 vty_out(vty
, ", atomic-aggregate");
8760 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8761 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8762 && bgp_path_info_mpath_count(path
))) {
8764 json_object_boolean_true_add(json_path
, "multipath");
8766 vty_out(vty
, ", multipath");
8769 // Mark the bestpath(s)
8770 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8771 first_as
= aspath_get_first_as(attr
->aspath
);
8775 json_bestpath
= json_object_new_object();
8776 json_object_int_add(json_bestpath
, "bestpathFromAs",
8780 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
8782 vty_out(vty
, ", bestpath-from-AS Local");
8786 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8789 json_bestpath
= json_object_new_object();
8790 json_object_boolean_true_add(json_bestpath
, "overall");
8791 json_object_string_add(
8792 json_bestpath
, "selectionReason",
8793 bgp_path_selection_reason2str(bn
->reason
));
8795 vty_out(vty
, ", best");
8796 vty_out(vty
, " (%s)",
8797 bgp_path_selection_reason2str(bn
->reason
));
8802 json_object_object_add(json_path
, "bestpath", json_bestpath
);
8807 /* Line 4 display Community */
8808 if (attr
->community
) {
8810 if (!attr
->community
->json
)
8811 community_str(attr
->community
, true);
8812 json_object_lock(attr
->community
->json
);
8813 json_object_object_add(json_path
, "community",
8814 attr
->community
->json
);
8816 vty_out(vty
, " Community: %s\n",
8817 attr
->community
->str
);
8821 /* Line 5 display Extended-community */
8822 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8824 json_ext_community
= json_object_new_object();
8825 json_object_string_add(json_ext_community
, "string",
8826 attr
->ecommunity
->str
);
8827 json_object_object_add(json_path
, "extendedCommunity",
8828 json_ext_community
);
8830 vty_out(vty
, " Extended Community: %s\n",
8831 attr
->ecommunity
->str
);
8835 /* Line 6 display Large community */
8836 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8838 if (!attr
->lcommunity
->json
)
8839 lcommunity_str(attr
->lcommunity
, true);
8840 json_object_lock(attr
->lcommunity
->json
);
8841 json_object_object_add(json_path
, "largeCommunity",
8842 attr
->lcommunity
->json
);
8844 vty_out(vty
, " Large Community: %s\n",
8845 attr
->lcommunity
->str
);
8849 /* Line 7 display Originator, Cluster-id */
8850 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8851 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8852 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8854 json_object_string_add(
8855 json_path
, "originatorId",
8856 inet_ntoa(attr
->originator_id
));
8858 vty_out(vty
, " Originator: %s",
8859 inet_ntoa(attr
->originator_id
));
8862 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8866 json_cluster_list
= json_object_new_object();
8867 json_cluster_list_list
=
8868 json_object_new_array();
8870 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8872 json_string
= json_object_new_string(
8873 inet_ntoa(attr
->cluster
8875 json_object_array_add(
8876 json_cluster_list_list
,
8881 * struct cluster_list does not have
8882 * "str" variable like aspath and community
8883 * do. Add this someday if someone asks
8885 * json_object_string_add(json_cluster_list,
8886 * "string", attr->cluster->str);
8888 json_object_object_add(json_cluster_list
,
8890 json_cluster_list_list
);
8891 json_object_object_add(json_path
, "clusterList",
8894 vty_out(vty
, ", Cluster list: ");
8896 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8899 inet_ntoa(attr
->cluster
8909 if (path
->extra
&& path
->extra
->damp_info
)
8910 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
8913 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8914 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
8915 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8918 json_object_int_add(json_path
, "remoteLabel", label
);
8920 vty_out(vty
, " Remote label: %d\n", label
);
8924 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8926 json_object_int_add(json_path
, "labelIndex",
8929 vty_out(vty
, " Label Index: %d\n",
8933 /* Line 8 display Addpath IDs */
8934 if (path
->addpath_rx_id
8935 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8937 json_object_int_add(json_path
, "addpathRxId",
8938 path
->addpath_rx_id
);
8940 /* Keep backwards compatibility with the old API
8941 * by putting TX All's ID in the old field
8943 json_object_int_add(
8944 json_path
, "addpathTxId",
8946 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
8948 /* ... but create a specific field for each
8951 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8952 json_object_int_add(
8954 bgp_addpath_names(i
)->id_json_name
,
8955 path
->tx_addpath
.addpath_tx_id
[i
]);
8958 vty_out(vty
, " AddPath ID: RX %u, ",
8959 path
->addpath_rx_id
);
8961 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8965 /* If we used addpath to TX a non-bestpath we need to display
8966 * "Advertised to" on a path-by-path basis
8968 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8971 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8973 bgp_addpath_encode_tx(peer
, afi
, safi
);
8974 has_adj
= bgp_adj_out_lookup(
8976 bgp_addpath_id_for_peer(peer
, afi
, safi
,
8977 &path
->tx_addpath
));
8979 if ((addpath_capable
&& has_adj
)
8980 || (!addpath_capable
&& has_adj
8981 && CHECK_FLAG(path
->flags
,
8982 BGP_PATH_SELECTED
))) {
8983 if (json_path
&& !json_adv_to
)
8984 json_adv_to
= json_object_new_object();
8986 route_vty_out_advertised_to(
8988 " Advertised to:", json_adv_to
);
8994 json_object_object_add(
8995 json_path
, "advertisedTo", json_adv_to
);
9004 /* Line 9 display Uptime */
9005 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9007 json_last_update
= json_object_new_object();
9008 json_object_int_add(json_last_update
, "epoch", tbuf
);
9009 json_object_string_add(json_last_update
, "string",
9011 json_object_object_add(json_path
, "lastUpdate",
9014 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9016 /* Line 10 display PMSI tunnel attribute, if present */
9017 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9019 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9020 PMSI_TNLTYPE_STR_DEFAULT
);
9023 json_pmsi
= json_object_new_object();
9024 json_object_string_add(json_pmsi
, "tunnelType", str
);
9025 json_object_int_add(json_pmsi
, "label",
9026 label2vni(&attr
->label
));
9027 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9029 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9030 str
, label2vni(&attr
->label
));
9033 /* We've constructed the json object for this path, add it to the json
9037 if (json_nexthop_global
|| json_nexthop_ll
) {
9038 json_nexthops
= json_object_new_array();
9040 if (json_nexthop_global
)
9041 json_object_array_add(json_nexthops
,
9042 json_nexthop_global
);
9044 if (json_nexthop_ll
)
9045 json_object_array_add(json_nexthops
,
9048 json_object_object_add(json_path
, "nexthops",
9052 json_object_object_add(json_path
, "peer", json_peer
);
9053 json_object_array_add(json_paths
, json_path
);
9057 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9058 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9059 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9061 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9062 const char *prefix_list_str
, afi_t afi
,
9063 safi_t safi
, enum bgp_show_type type
);
9064 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9065 const char *filter
, afi_t afi
, safi_t safi
,
9066 enum bgp_show_type type
);
9067 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9068 const char *rmap_str
, afi_t afi
, safi_t safi
,
9069 enum bgp_show_type type
);
9070 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9071 const char *com
, int exact
, afi_t afi
,
9073 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9074 const char *prefix
, afi_t afi
, safi_t safi
,
9075 enum bgp_show_type type
);
9076 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9077 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
9078 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9079 const char *comstr
, int exact
, afi_t afi
,
9080 safi_t safi
, bool use_json
);
9083 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9084 struct bgp_table
*table
, enum bgp_show_type type
,
9085 void *output_arg
, bool use_json
, char *rd
,
9086 int is_last
, unsigned long *output_cum
,
9087 unsigned long *total_cum
,
9088 unsigned long *json_header_depth
)
9090 struct bgp_path_info
*pi
;
9091 struct bgp_node
*rn
;
9094 unsigned long output_count
= 0;
9095 unsigned long total_count
= 0;
9098 json_object
*json_paths
= NULL
;
9101 if (output_cum
&& *output_cum
!= 0)
9104 if (use_json
&& !*json_header_depth
) {
9106 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9107 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9108 " \"localAS\": %u,\n \"routes\": { ",
9109 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9110 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9113 table
->version
, inet_ntoa(bgp
->router_id
),
9114 bgp
->default_local_pref
, bgp
->as
);
9115 *json_header_depth
= 2;
9117 vty_out(vty
, " \"routeDistinguishers\" : {");
9118 ++*json_header_depth
;
9122 if (use_json
&& rd
) {
9123 vty_out(vty
, " \"%s\" : { ", rd
);
9126 /* Start processing of routes. */
9127 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9128 pi
= bgp_node_get_bgp_path_info(rn
);
9134 json_paths
= json_object_new_array();
9138 for (; pi
; pi
= pi
->next
) {
9140 if (type
== bgp_show_type_flap_statistics
9141 || type
== bgp_show_type_flap_neighbor
9142 || type
== bgp_show_type_dampend_paths
9143 || type
== bgp_show_type_damp_neighbor
) {
9144 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9147 if (type
== bgp_show_type_regexp
) {
9148 regex_t
*regex
= output_arg
;
9150 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9154 if (type
== bgp_show_type_prefix_list
) {
9155 struct prefix_list
*plist
= output_arg
;
9157 if (prefix_list_apply(plist
, &rn
->p
)
9161 if (type
== bgp_show_type_filter_list
) {
9162 struct as_list
*as_list
= output_arg
;
9164 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9165 != AS_FILTER_PERMIT
)
9168 if (type
== bgp_show_type_route_map
) {
9169 struct route_map
*rmap
= output_arg
;
9170 struct bgp_path_info path
;
9171 struct attr dummy_attr
;
9172 route_map_result_t ret
;
9174 bgp_attr_dup(&dummy_attr
, pi
->attr
);
9176 path
.peer
= pi
->peer
;
9177 path
.attr
= &dummy_attr
;
9179 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9181 if (ret
== RMAP_DENYMATCH
)
9184 if (type
== bgp_show_type_neighbor
9185 || type
== bgp_show_type_flap_neighbor
9186 || type
== bgp_show_type_damp_neighbor
) {
9187 union sockunion
*su
= output_arg
;
9189 if (pi
->peer
== NULL
9190 || pi
->peer
->su_remote
== NULL
9191 || !sockunion_same(pi
->peer
->su_remote
, su
))
9194 if (type
== bgp_show_type_cidr_only
) {
9195 uint32_t destination
;
9197 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9198 if (IN_CLASSC(destination
)
9199 && rn
->p
.prefixlen
== 24)
9201 if (IN_CLASSB(destination
)
9202 && rn
->p
.prefixlen
== 16)
9204 if (IN_CLASSA(destination
)
9205 && rn
->p
.prefixlen
== 8)
9208 if (type
== bgp_show_type_prefix_longer
) {
9210 if (!prefix_match(p
, &rn
->p
))
9213 if (type
== bgp_show_type_community_all
) {
9214 if (!pi
->attr
->community
)
9217 if (type
== bgp_show_type_community
) {
9218 struct community
*com
= output_arg
;
9220 if (!pi
->attr
->community
9221 || !community_match(pi
->attr
->community
,
9225 if (type
== bgp_show_type_community_exact
) {
9226 struct community
*com
= output_arg
;
9228 if (!pi
->attr
->community
9229 || !community_cmp(pi
->attr
->community
, com
))
9232 if (type
== bgp_show_type_community_list
) {
9233 struct community_list
*list
= output_arg
;
9235 if (!community_list_match(pi
->attr
->community
,
9239 if (type
== bgp_show_type_community_list_exact
) {
9240 struct community_list
*list
= output_arg
;
9242 if (!community_list_exact_match(
9243 pi
->attr
->community
, list
))
9246 if (type
== bgp_show_type_lcommunity
) {
9247 struct lcommunity
*lcom
= output_arg
;
9249 if (!pi
->attr
->lcommunity
9250 || !lcommunity_match(pi
->attr
->lcommunity
,
9255 if (type
== bgp_show_type_lcommunity_exact
) {
9256 struct lcommunity
*lcom
= output_arg
;
9258 if (!pi
->attr
->lcommunity
9259 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9263 if (type
== bgp_show_type_lcommunity_list
) {
9264 struct community_list
*list
= output_arg
;
9266 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9271 == bgp_show_type_lcommunity_list_exact
) {
9272 struct community_list
*list
= output_arg
;
9274 if (!lcommunity_list_exact_match(
9275 pi
->attr
->lcommunity
, list
))
9278 if (type
== bgp_show_type_lcommunity_all
) {
9279 if (!pi
->attr
->lcommunity
)
9282 if (type
== bgp_show_type_dampend_paths
9283 || type
== bgp_show_type_damp_neighbor
) {
9284 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9285 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9289 if (!use_json
&& header
) {
9290 vty_out(vty
, "BGP table version is %" PRIu64
9291 ", local router ID is %s, vrf id ",
9293 inet_ntoa(bgp
->router_id
));
9294 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9295 vty_out(vty
, "%s", VRFID_NONE_STR
);
9297 vty_out(vty
, "%u", bgp
->vrf_id
);
9299 vty_out(vty
, "Default local pref %u, ",
9300 bgp
->default_local_pref
);
9301 vty_out(vty
, "local AS %u\n", bgp
->as
);
9302 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9303 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9304 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9305 if (type
== bgp_show_type_dampend_paths
9306 || type
== bgp_show_type_damp_neighbor
)
9307 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9308 else if (type
== bgp_show_type_flap_statistics
9309 || type
== bgp_show_type_flap_neighbor
)
9310 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9312 vty_out(vty
, BGP_SHOW_HEADER
);
9315 if (rd
!= NULL
&& !display
&& !output_count
) {
9318 "Route Distinguisher: %s\n",
9321 if (type
== bgp_show_type_dampend_paths
9322 || type
== bgp_show_type_damp_neighbor
)
9323 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9324 safi
, use_json
, json_paths
);
9325 else if (type
== bgp_show_type_flap_statistics
9326 || type
== bgp_show_type_flap_neighbor
)
9327 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9328 safi
, use_json
, json_paths
);
9330 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9342 if (p
->family
== AF_FLOWSPEC
) {
9343 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9345 bgp_fs_nlri_get_string((unsigned char *)
9346 p
->u
.prefix_flowspec
.ptr
,
9347 p
->u
.prefix_flowspec
9350 NLRI_STRING_FORMAT_MIN
,
9353 vty_out(vty
, "\"%s/%d\": ",
9355 p
->u
.prefix_flowspec
.prefixlen
);
9357 vty_out(vty
, ",\"%s/%d\": ",
9359 p
->u
.prefix_flowspec
.prefixlen
);
9361 prefix2str(p
, buf2
, sizeof(buf2
));
9363 vty_out(vty
, "\"%s\": ", buf2
);
9365 vty_out(vty
, ",\"%s\": ", buf2
);
9368 json_object_to_json_string(json_paths
));
9369 json_object_free(json_paths
);
9376 output_count
+= *output_cum
;
9377 *output_cum
= output_count
;
9380 total_count
+= *total_cum
;
9381 *total_cum
= total_count
;
9385 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9389 for (i
= 0; i
< *json_header_depth
; ++i
)
9390 vty_out(vty
, " } ");
9395 /* No route is displayed */
9396 if (output_count
== 0) {
9397 if (type
== bgp_show_type_normal
)
9399 "No BGP prefixes displayed, %ld exist\n",
9403 "\nDisplayed %ld routes and %ld total paths\n",
9404 output_count
, total_count
);
9411 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9412 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9413 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9415 struct bgp_node
*rn
, *next
;
9416 unsigned long output_cum
= 0;
9417 unsigned long total_cum
= 0;
9418 unsigned long json_header_depth
= 0;
9419 struct bgp_table
*itable
;
9422 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9424 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9425 next
= bgp_route_next(rn
);
9426 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9429 itable
= bgp_node_get_bgp_table_info(rn
);
9430 if (itable
!= NULL
) {
9431 struct prefix_rd prd
;
9432 char rd
[RD_ADDRSTRLEN
];
9434 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9435 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9436 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9437 use_json
, rd
, next
== NULL
, &output_cum
,
9438 &total_cum
, &json_header_depth
);
9444 if (output_cum
== 0)
9445 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9449 "\nDisplayed %ld routes and %ld total paths\n",
9450 output_cum
, total_cum
);
9454 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9455 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9457 struct bgp_table
*table
;
9458 unsigned long json_header_depth
= 0;
9461 bgp
= bgp_get_default();
9466 vty_out(vty
, "No BGP process is configured\n");
9468 vty_out(vty
, "{}\n");
9472 table
= bgp
->rib
[afi
][safi
];
9473 /* use MPLS and ENCAP specific shows until they are merged */
9474 if (safi
== SAFI_MPLS_VPN
) {
9475 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9476 output_arg
, use_json
);
9479 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9480 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9481 output_arg
, use_json
,
9484 /* labeled-unicast routes live in the unicast table */
9485 else if (safi
== SAFI_LABELED_UNICAST
)
9486 safi
= SAFI_UNICAST
;
9488 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9489 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9492 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9493 safi_t safi
, bool use_json
)
9495 struct listnode
*node
, *nnode
;
9498 bool route_output
= false;
9501 vty_out(vty
, "{\n");
9503 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9504 route_output
= true;
9507 vty_out(vty
, ",\n");
9511 vty_out(vty
, "\"%s\":",
9512 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9516 vty_out(vty
, "\nInstance %s:\n",
9517 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9521 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9526 vty_out(vty
, "}\n");
9527 else if (!route_output
)
9528 vty_out(vty
, "%% BGP instance not found\n");
9531 /* Header of detailed BGP route information */
9532 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9533 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9534 afi_t afi
, safi_t safi
, json_object
*json
)
9536 struct bgp_path_info
*pi
;
9539 struct listnode
*node
, *nnode
;
9540 char buf1
[RD_ADDRSTRLEN
];
9541 char buf2
[INET6_ADDRSTRLEN
];
9542 char buf3
[EVPN_ROUTE_STRLEN
];
9543 char prefix_str
[BUFSIZ
];
9548 int route_filter_translated_v4
= 0;
9549 int route_filter_v4
= 0;
9550 int route_filter_translated_v6
= 0;
9551 int route_filter_v6
= 0;
9554 int accept_own_nexthop
= 0;
9557 int no_advertise
= 0;
9561 int has_valid_label
= 0;
9562 mpls_label_t label
= 0;
9563 json_object
*json_adv_to
= NULL
;
9566 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9568 if (has_valid_label
)
9569 label
= label_pton(&rn
->local_label
);
9571 if (safi
== SAFI_EVPN
) {
9574 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9575 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9576 : "", prd
? ":" : "",
9577 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9578 buf3
, sizeof(buf3
)));
9580 json_object_string_add(json
, "rd",
9581 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9583 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9587 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9588 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9589 ? prefix_rd2str(prd
, buf1
,
9592 safi
== SAFI_MPLS_VPN
? ":" : "",
9593 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9598 json_object_string_add(json
, "prefix",
9599 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9602 if (has_valid_label
) {
9604 json_object_int_add(json
, "localLabel", label
);
9606 vty_out(vty
, "Local label: %d\n", label
);
9610 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9611 vty_out(vty
, "not allocated\n");
9613 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9615 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9617 if (pi
->extra
&& pi
->extra
->suppress
)
9620 if (pi
->attr
->community
== NULL
)
9623 no_advertise
+= community_include(
9624 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9625 no_export
+= community_include(pi
->attr
->community
,
9626 COMMUNITY_NO_EXPORT
);
9627 local_as
+= community_include(pi
->attr
->community
,
9628 COMMUNITY_LOCAL_AS
);
9629 accept_own
+= community_include(pi
->attr
->community
,
9630 COMMUNITY_ACCEPT_OWN
);
9631 route_filter_translated_v4
+= community_include(
9632 pi
->attr
->community
,
9633 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9634 route_filter_translated_v6
+= community_include(
9635 pi
->attr
->community
,
9636 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9637 route_filter_v4
+= community_include(
9638 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9639 route_filter_v6
+= community_include(
9640 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9641 llgr_stale
+= community_include(pi
->attr
->community
,
9642 COMMUNITY_LLGR_STALE
);
9643 no_llgr
+= community_include(pi
->attr
->community
,
9645 accept_own_nexthop
+=
9646 community_include(pi
->attr
->community
,
9647 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9648 blackhole
+= community_include(pi
->attr
->community
,
9649 COMMUNITY_BLACKHOLE
);
9650 no_peer
+= community_include(pi
->attr
->community
,
9656 vty_out(vty
, "Paths: (%d available", count
);
9658 vty_out(vty
, ", best #%d", best
);
9659 if (safi
== SAFI_UNICAST
) {
9660 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9661 vty_out(vty
, ", table %s",
9664 vty_out(vty
, ", vrf %s",
9668 vty_out(vty
, ", no best path");
9672 ", accept own local route exported and imported in different VRF");
9673 else if (route_filter_translated_v4
)
9675 ", mark translated RTs for VPNv4 route filtering");
9676 else if (route_filter_v4
)
9678 ", attach RT as-is for VPNv4 route filtering");
9679 else if (route_filter_translated_v6
)
9681 ", mark translated RTs for VPNv6 route filtering");
9682 else if (route_filter_v6
)
9684 ", attach RT as-is for VPNv6 route filtering");
9685 else if (llgr_stale
)
9687 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9690 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9691 else if (accept_own_nexthop
)
9693 ", accept local nexthop");
9695 vty_out(vty
, ", inform peer to blackhole prefix");
9697 vty_out(vty
, ", not advertised to EBGP peer");
9698 else if (no_advertise
)
9699 vty_out(vty
, ", not advertised to any peer");
9701 vty_out(vty
, ", not advertised outside local AS");
9704 ", inform EBGP peer not to advertise to their EBGP peers");
9708 ", Advertisements suppressed by an aggregate.");
9709 vty_out(vty
, ")\n");
9712 /* If we are not using addpath then we can display Advertised to and
9714 * show what peers we advertised the bestpath to. If we are using
9716 * though then we must display Advertised to on a path-by-path basis. */
9717 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9718 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9719 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9720 if (json
&& !json_adv_to
)
9721 json_adv_to
= json_object_new_object();
9723 route_vty_out_advertised_to(
9725 " Advertised to non peer-group peers:\n ",
9732 json_object_object_add(json
, "advertisedTo",
9737 vty_out(vty
, " Not advertised to any peer");
9743 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
9744 struct bgp_node
*bgp_node
, struct vty
*vty
,
9745 struct bgp
*bgp
, afi_t afi
,
9746 safi_t safi
, json_object
*json
,
9747 enum bgp_path_type pathtype
, int *display
)
9749 struct bgp_path_info
*pi
;
9751 char rdbuf
[RD_ADDRSTRLEN
];
9752 json_object
*json_header
= NULL
;
9753 json_object
*json_paths
= NULL
;
9755 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
9758 if (json
&& !json_paths
) {
9759 /* Instantiate json_paths only if path is valid */
9760 json_paths
= json_object_new_array();
9762 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
9763 json_header
= json_object_new_object();
9769 route_vty_out_detail_header(
9770 vty
, bgp
, bgp_node
, pfx_rd
,
9771 AFI_IP
, safi
, json_header
);
9776 if (pathtype
== BGP_PATH_SHOW_ALL
9777 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9778 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
9779 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9780 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
9781 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
9782 route_vty_out_detail(vty
, bgp
, bgp_node
,
9787 if (json
&& json_paths
) {
9788 json_object_object_add(json_header
, "paths", json_paths
);
9791 json_object_object_add(json
, rdbuf
, json_header
);
9795 /* Display specified route of BGP table. */
9796 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9797 struct bgp_table
*rib
, const char *ip_str
,
9798 afi_t afi
, safi_t safi
,
9799 struct prefix_rd
*prd
, int prefix_check
,
9800 enum bgp_path_type pathtype
, bool use_json
)
9804 struct prefix match
;
9805 struct bgp_node
*rn
;
9806 struct bgp_node
*rm
;
9807 struct bgp_table
*table
;
9808 json_object
*json
= NULL
;
9809 json_object
*json_paths
= NULL
;
9811 /* Check IP address argument. */
9812 ret
= str2prefix(ip_str
, &match
);
9814 vty_out(vty
, "address is malformed\n");
9818 match
.family
= afi2family(afi
);
9821 json
= json_object_new_object();
9823 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
9824 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9825 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9827 table
= bgp_node_get_bgp_table_info(rn
);
9831 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9835 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9836 bgp_unlock_node(rm
);
9840 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9841 vty
, bgp
, afi
, safi
, json
,
9842 pathtype
, &display
);
9844 bgp_unlock_node(rm
);
9846 } else if (safi
== SAFI_EVPN
) {
9847 struct bgp_node
*longest_pfx
;
9848 bool is_exact_pfxlen_match
= FALSE
;
9850 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9851 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9853 table
= bgp_node_get_bgp_table_info(rn
);
9858 is_exact_pfxlen_match
= FALSE
;
9860 * Search through all the prefixes for a match. The
9861 * pfx's are enumerated in ascending order of pfxlens.
9862 * So, the last pfx match is the longest match. Set
9863 * is_exact_pfxlen_match when we get exact pfxlen match
9865 for (rm
= bgp_table_top(table
); rm
;
9866 rm
= bgp_route_next(rm
)) {
9868 * Get prefixlen of the ip-prefix within type5
9871 if (evpn_type5_prefix_match(&rm
->p
,
9872 &match
) && rm
->info
) {
9875 bgp_evpn_get_type5_prefixlen(&rm
->p
);
9876 if (type5_pfxlen
== match
.prefixlen
) {
9877 is_exact_pfxlen_match
= TRUE
;
9878 bgp_unlock_node(rm
);
9887 if (prefix_check
&& !is_exact_pfxlen_match
)
9893 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9894 vty
, bgp
, afi
, safi
, json
,
9895 pathtype
, &display
);
9897 bgp_unlock_node(rm
);
9899 } else if (safi
== SAFI_FLOWSPEC
) {
9901 json_paths
= json_object_new_array();
9903 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9904 &match
, prefix_check
,
9908 if (use_json
&& display
)
9909 json_object_object_add(json
, "paths", json_paths
);
9911 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9913 || rn
->p
.prefixlen
== match
.prefixlen
) {
9914 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
9916 pathtype
, &display
);
9919 bgp_unlock_node(rn
);
9924 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9925 json
, JSON_C_TO_STRING_PRETTY
|
9926 JSON_C_TO_STRING_NOSLASHESCAPE
));
9927 json_object_free(json
);
9930 vty_out(vty
, "%% Network not in table\n");
9938 /* Display specified route of Main RIB */
9939 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9940 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9941 int prefix_check
, enum bgp_path_type pathtype
,
9945 bgp
= bgp_get_default();
9948 vty_out(vty
, "No BGP process is configured\n");
9950 vty_out(vty
, "{}\n");
9955 /* labeled-unicast routes live in the unicast table */
9956 if (safi
== SAFI_LABELED_UNICAST
)
9957 safi
= SAFI_UNICAST
;
9959 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9960 afi
, safi
, prd
, prefix_check
, pathtype
,
9964 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9965 struct cmd_token
**argv
, bool exact
, afi_t afi
,
9966 safi_t safi
, bool uj
)
9968 struct lcommunity
*lcom
;
9974 b
= buffer_new(1024);
9975 for (i
= 0; i
< argc
; i
++) {
9977 buffer_putc(b
, ' ');
9979 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9981 buffer_putstr(b
, argv
[i
]->arg
);
9985 buffer_putc(b
, '\0');
9987 str
= buffer_getstr(b
);
9990 lcom
= lcommunity_str2com(str
);
9991 XFREE(MTYPE_TMP
, str
);
9993 vty_out(vty
, "%% Large-community malformed\n");
9997 return bgp_show(vty
, bgp
, afi
, safi
,
9998 (exact
? bgp_show_type_lcommunity_exact
9999 : bgp_show_type_lcommunity
),
10003 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10004 const char *lcom
, bool exact
, afi_t afi
,
10005 safi_t safi
, bool uj
)
10007 struct community_list
*list
;
10009 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10010 LARGE_COMMUNITY_LIST_MASTER
);
10011 if (list
== NULL
) {
10012 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10014 return CMD_WARNING
;
10017 return bgp_show(vty
, bgp
, afi
, safi
,
10018 (exact
? bgp_show_type_lcommunity_list_exact
10019 : bgp_show_type_lcommunity_list
),
10023 DEFUN (show_ip_bgp_large_community_list
,
10024 show_ip_bgp_large_community_list_cmd
,
10025 "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]",
10029 BGP_INSTANCE_HELP_STR
10031 BGP_SAFI_WITH_LABEL_HELP_STR
10032 "Display routes matching the large-community-list\n"
10033 "large-community-list number\n"
10034 "large-community-list name\n"
10035 "Exact match of the large-communities\n"
10039 afi_t afi
= AFI_IP6
;
10040 safi_t safi
= SAFI_UNICAST
;
10042 bool exact_match
= 0;
10044 if (argv_find(argv
, argc
, "ip", &idx
))
10046 if (argv_find(argv
, argc
, "view", &idx
)
10047 || argv_find(argv
, argc
, "vrf", &idx
))
10048 vrf
= argv
[++idx
]->arg
;
10049 if (argv_find(argv
, argc
, "ipv4", &idx
)
10050 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10051 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10052 if (argv_find(argv
, argc
, "unicast", &idx
)
10053 || argv_find(argv
, argc
, "multicast", &idx
))
10054 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10057 bool uj
= use_json(argc
, argv
);
10059 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10061 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10062 return CMD_WARNING
;
10065 argv_find(argv
, argc
, "large-community-list", &idx
);
10067 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10069 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10072 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10073 exact_match
, afi
, safi
, uj
);
10075 DEFUN (show_ip_bgp_large_community
,
10076 show_ip_bgp_large_community_cmd
,
10077 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10081 BGP_INSTANCE_HELP_STR
10083 BGP_SAFI_WITH_LABEL_HELP_STR
10084 "Display routes matching the large-communities\n"
10085 "List of large-community numbers\n"
10086 "Exact match of the large-communities\n"
10090 afi_t afi
= AFI_IP6
;
10091 safi_t safi
= SAFI_UNICAST
;
10093 bool exact_match
= 0;
10095 if (argv_find(argv
, argc
, "ip", &idx
))
10097 if (argv_find(argv
, argc
, "view", &idx
)
10098 || argv_find(argv
, argc
, "vrf", &idx
))
10099 vrf
= argv
[++idx
]->arg
;
10100 if (argv_find(argv
, argc
, "ipv4", &idx
)
10101 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10102 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10103 if (argv_find(argv
, argc
, "unicast", &idx
)
10104 || argv_find(argv
, argc
, "multicast", &idx
))
10105 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10108 bool uj
= use_json(argc
, argv
);
10110 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10112 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10113 return CMD_WARNING
;
10116 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10117 if (argv_find(argv
, argc
, "exact-match", &idx
))
10119 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10120 exact_match
, afi
, safi
, uj
);
10122 return bgp_show(vty
, bgp
, afi
, safi
,
10123 bgp_show_type_lcommunity_all
, NULL
, uj
);
10126 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10130 /* BGP route print out function without JSON */
10131 DEFUN (show_ip_bgp
,
10133 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10134 <dampening <parameters>\
10139 |community-list <(1-500)|WORD> [exact-match]\
10140 |A.B.C.D/M longer-prefixes\
10141 |X:X::X:X/M longer-prefixes\
10146 BGP_INSTANCE_HELP_STR
10148 BGP_SAFI_WITH_LABEL_HELP_STR
10149 "Display detailed information about dampening\n"
10150 "Display detail of configured dampening parameters\n"
10151 "Display routes matching the route-map\n"
10152 "A route-map to match on\n"
10153 "Display routes conforming to the prefix-list\n"
10154 "Prefix-list name\n"
10155 "Display routes conforming to the filter-list\n"
10156 "Regular expression access list name\n"
10157 "BGP RIB advertisement statistics\n"
10158 "Display routes matching the community-list\n"
10159 "community-list number\n"
10160 "community-list name\n"
10161 "Exact match of the communities\n"
10163 "Display route and more specific routes\n"
10165 "Display route and more specific routes\n")
10167 afi_t afi
= AFI_IP6
;
10168 safi_t safi
= SAFI_UNICAST
;
10169 int exact_match
= 0;
10170 struct bgp
*bgp
= NULL
;
10173 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10176 return CMD_WARNING
;
10178 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10179 if (argv_find(argv
, argc
, "parameters", &idx
))
10180 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10183 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10184 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10185 safi
, bgp_show_type_prefix_list
);
10187 if (argv_find(argv
, argc
, "filter-list", &idx
))
10188 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10189 safi
, bgp_show_type_filter_list
);
10191 if (argv_find(argv
, argc
, "statistics", &idx
))
10192 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10194 if (argv_find(argv
, argc
, "route-map", &idx
))
10195 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10196 safi
, bgp_show_type_route_map
);
10198 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10199 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10200 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10202 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10203 exact_match
, afi
, safi
);
10205 /* prefix-longer */
10206 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10207 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10208 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10210 bgp_show_type_prefix_longer
);
10212 return CMD_WARNING
;
10215 /* BGP route print out function with JSON */
10216 DEFUN (show_ip_bgp_json
,
10217 show_ip_bgp_json_cmd
,
10218 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10220 |dampening <flap-statistics|dampened-paths>\
10221 |community [AA:NN|local-AS|no-advertise|no-export\
10222 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10223 |accept-own|accept-own-nexthop|route-filter-v6\
10224 |route-filter-v4|route-filter-translated-v6\
10225 |route-filter-translated-v4] [exact-match]\
10230 BGP_INSTANCE_HELP_STR
10232 BGP_SAFI_WITH_LABEL_HELP_STR
10233 "Display only routes with non-natural netmasks\n"
10234 "Display detailed information about dampening\n"
10235 "Display flap statistics of routes\n"
10236 "Display paths suppressed due to dampening\n"
10237 "Display routes matching the communities\n"
10239 "Do not send outside local AS (well-known community)\n"
10240 "Do not advertise to any peer (well-known community)\n"
10241 "Do not export to next AS (well-known community)\n"
10242 "Graceful shutdown (well-known community)\n"
10243 "Do not export to any peer (well-known community)\n"
10244 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10245 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10246 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10247 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10248 "Should accept VPN route with local nexthop (well-known community)\n"
10249 "RT VPNv6 route filtering (well-known community)\n"
10250 "RT VPNv4 route filtering (well-known community)\n"
10251 "RT translated VPNv6 route filtering (well-known community)\n"
10252 "RT translated VPNv4 route filtering (well-known community)\n"
10253 "Exact match of the communities\n"
10256 afi_t afi
= AFI_IP6
;
10257 safi_t safi
= SAFI_UNICAST
;
10258 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10259 struct bgp
*bgp
= NULL
;
10261 int exact_match
= 0;
10262 bool uj
= use_json(argc
, argv
);
10267 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10270 return CMD_WARNING
;
10272 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10273 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10276 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10277 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10278 return bgp_show(vty
, bgp
, afi
, safi
,
10279 bgp_show_type_dampend_paths
, NULL
, uj
);
10280 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10281 return bgp_show(vty
, bgp
, afi
, safi
,
10282 bgp_show_type_flap_statistics
, NULL
,
10286 if (argv_find(argv
, argc
, "community", &idx
)) {
10287 char *maybecomm
= NULL
;
10288 char *community
= NULL
;
10290 if (idx
+ 1 < argc
) {
10291 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10292 maybecomm
= argv
[idx
+ 1]->arg
;
10294 maybecomm
= argv
[idx
+ 1]->text
;
10297 if (maybecomm
&& !strmatch(maybecomm
, "json")
10298 && !strmatch(maybecomm
, "exact-match"))
10299 community
= maybecomm
;
10301 if (argv_find(argv
, argc
, "exact-match", &idx
))
10305 return bgp_show_community(vty
, bgp
, community
,
10306 exact_match
, afi
, safi
, uj
);
10308 return (bgp_show(vty
, bgp
, afi
, safi
,
10309 bgp_show_type_community_all
, NULL
,
10313 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10316 DEFUN (show_ip_bgp_route
,
10317 show_ip_bgp_route_cmd
,
10318 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10319 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10323 BGP_INSTANCE_HELP_STR
10325 BGP_SAFI_WITH_LABEL_HELP_STR
10326 "Network in the BGP routing table to display\n"
10328 "Network in the BGP routing table to display\n"
10330 "Display only the bestpath\n"
10331 "Display only multipaths\n"
10334 int prefix_check
= 0;
10336 afi_t afi
= AFI_IP6
;
10337 safi_t safi
= SAFI_UNICAST
;
10338 char *prefix
= NULL
;
10339 struct bgp
*bgp
= NULL
;
10340 enum bgp_path_type path_type
;
10341 bool uj
= use_json(argc
, argv
);
10345 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10348 return CMD_WARNING
;
10352 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10353 return CMD_WARNING
;
10356 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10357 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10358 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10360 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10361 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10364 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10365 && afi
!= AFI_IP6
) {
10367 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10368 return CMD_WARNING
;
10370 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10371 && afi
!= AFI_IP
) {
10373 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10374 return CMD_WARNING
;
10377 prefix
= argv
[idx
]->arg
;
10379 /* [<bestpath|multipath>] */
10380 if (argv_find(argv
, argc
, "bestpath", &idx
))
10381 path_type
= BGP_PATH_SHOW_BESTPATH
;
10382 else if (argv_find(argv
, argc
, "multipath", &idx
))
10383 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10385 path_type
= BGP_PATH_SHOW_ALL
;
10387 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10391 DEFUN (show_ip_bgp_regexp
,
10392 show_ip_bgp_regexp_cmd
,
10393 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10397 BGP_INSTANCE_HELP_STR
10399 BGP_SAFI_WITH_LABEL_HELP_STR
10400 "Display routes matching the AS path regular expression\n"
10401 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10403 afi_t afi
= AFI_IP6
;
10404 safi_t safi
= SAFI_UNICAST
;
10405 struct bgp
*bgp
= NULL
;
10408 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10411 return CMD_WARNING
;
10413 // get index of regex
10414 argv_find(argv
, argc
, "regexp", &idx
);
10417 char *regstr
= argv_concat(argv
, argc
, idx
);
10418 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10419 bgp_show_type_regexp
);
10420 XFREE(MTYPE_TMP
, regstr
);
10424 DEFUN (show_ip_bgp_instance_all
,
10425 show_ip_bgp_instance_all_cmd
,
10426 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10430 BGP_INSTANCE_ALL_HELP_STR
10432 BGP_SAFI_WITH_LABEL_HELP_STR
10435 afi_t afi
= AFI_IP
;
10436 safi_t safi
= SAFI_UNICAST
;
10437 struct bgp
*bgp
= NULL
;
10439 bool uj
= use_json(argc
, argv
);
10444 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10447 return CMD_WARNING
;
10449 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10450 return CMD_SUCCESS
;
10453 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10454 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10459 if (!config_bgp_aspath_validate(regstr
)) {
10460 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10462 return CMD_WARNING_CONFIG_FAILED
;
10465 regex
= bgp_regcomp(regstr
);
10467 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10468 return CMD_WARNING
;
10471 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10472 bgp_regex_free(regex
);
10476 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10477 const char *prefix_list_str
, afi_t afi
,
10478 safi_t safi
, enum bgp_show_type type
)
10480 struct prefix_list
*plist
;
10482 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10483 if (plist
== NULL
) {
10484 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10486 return CMD_WARNING
;
10489 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10492 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10493 const char *filter
, afi_t afi
, safi_t safi
,
10494 enum bgp_show_type type
)
10496 struct as_list
*as_list
;
10498 as_list
= as_list_lookup(filter
);
10499 if (as_list
== NULL
) {
10500 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10502 return CMD_WARNING
;
10505 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10508 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10509 const char *rmap_str
, afi_t afi
, safi_t safi
,
10510 enum bgp_show_type type
)
10512 struct route_map
*rmap
;
10514 rmap
= route_map_lookup_by_name(rmap_str
);
10516 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10517 return CMD_WARNING
;
10520 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10523 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10524 const char *comstr
, int exact
, afi_t afi
,
10525 safi_t safi
, bool use_json
)
10527 struct community
*com
;
10530 com
= community_str2com(comstr
);
10532 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10533 return CMD_WARNING
;
10536 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10537 (exact
? bgp_show_type_community_exact
10538 : bgp_show_type_community
),
10540 community_free(&com
);
10545 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10546 const char *com
, int exact
, afi_t afi
,
10549 struct community_list
*list
;
10551 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10552 if (list
== NULL
) {
10553 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10554 return CMD_WARNING
;
10557 return bgp_show(vty
, bgp
, afi
, safi
,
10558 (exact
? bgp_show_type_community_list_exact
10559 : bgp_show_type_community_list
),
10563 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10564 const char *prefix
, afi_t afi
, safi_t safi
,
10565 enum bgp_show_type type
)
10572 ret
= str2prefix(prefix
, p
);
10574 vty_out(vty
, "%% Malformed Prefix\n");
10575 return CMD_WARNING
;
10578 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10584 BGP_STATS_MAXBITLEN
= 0,
10586 BGP_STATS_PREFIXES
,
10588 BGP_STATS_UNAGGREGATEABLE
,
10589 BGP_STATS_MAX_AGGREGATEABLE
,
10590 BGP_STATS_AGGREGATES
,
10592 BGP_STATS_ASPATH_COUNT
,
10593 BGP_STATS_ASPATH_MAXHOPS
,
10594 BGP_STATS_ASPATH_TOTHOPS
,
10595 BGP_STATS_ASPATH_MAXSIZE
,
10596 BGP_STATS_ASPATH_TOTSIZE
,
10597 BGP_STATS_ASN_HIGHEST
,
10601 static const char *table_stats_strs
[] = {
10602 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10603 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10604 [BGP_STATS_RIB
] = "Total Advertisements",
10605 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10606 [BGP_STATS_MAX_AGGREGATEABLE
] =
10607 "Maximum aggregateable prefixes",
10608 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10609 [BGP_STATS_SPACE
] = "Address space advertised",
10610 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10611 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10612 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10613 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10614 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10615 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10616 [BGP_STATS_MAX
] = NULL
,
10619 struct bgp_table_stats
{
10620 struct bgp_table
*table
;
10621 unsigned long long counts
[BGP_STATS_MAX
];
10622 double total_space
;
10626 #define TALLY_SIGFIG 100000
10627 static unsigned long
10628 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10630 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10631 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10632 unsigned long ret
= newtot
/ count
;
10634 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10641 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10642 struct bgp_table_stats
*ts
, unsigned int space
)
10644 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10645 struct bgp_path_info
*pi
;
10650 if (!bgp_node_has_bgp_path_info_data(rn
))
10653 ts
->counts
[BGP_STATS_PREFIXES
]++;
10654 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10657 ts
->counts
[BGP_STATS_AVGPLEN
]
10658 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10659 ts
->counts
[BGP_STATS_AVGPLEN
],
10663 /* check if the prefix is included by any other announcements */
10664 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10665 prn
= bgp_node_parent_nolock(prn
);
10667 if (prn
== NULL
|| prn
== top
) {
10668 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10669 /* announced address space */
10671 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10672 } else if (bgp_node_has_bgp_path_info_data(prn
))
10673 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10676 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10677 ts
->counts
[BGP_STATS_RIB
]++;
10679 if (CHECK_FLAG(pi
->attr
->flag
,
10680 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
10681 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10683 /* as-path stats */
10684 if (pi
->attr
->aspath
) {
10685 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10686 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10687 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10689 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10691 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10692 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10694 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10695 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10697 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10698 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10700 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10701 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10702 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10704 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10705 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10706 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10709 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10710 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10715 static int bgp_table_stats_walker(struct thread
*t
)
10717 struct bgp_node
*rn
, *nrn
;
10718 struct bgp_node
*top
;
10719 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10720 unsigned int space
= 0;
10722 if (!(top
= bgp_table_top(ts
->table
)))
10725 switch (ts
->table
->afi
) {
10727 space
= IPV4_MAX_BITLEN
;
10730 space
= IPV6_MAX_BITLEN
;
10736 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10738 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10739 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10740 struct bgp_table
*table
;
10742 table
= bgp_node_get_bgp_table_info(rn
);
10746 top
= bgp_table_top(table
);
10747 for (nrn
= bgp_table_top(table
); nrn
;
10748 nrn
= bgp_route_next(nrn
))
10749 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10751 bgp_table_stats_rn(rn
, top
, ts
, space
);
10758 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10761 struct bgp_table_stats ts
;
10764 if (!bgp
->rib
[afi
][safi
]) {
10765 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10767 return CMD_WARNING
;
10770 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
10772 /* labeled-unicast routes live in the unicast table */
10773 if (safi
== SAFI_LABELED_UNICAST
)
10774 safi
= SAFI_UNICAST
;
10776 memset(&ts
, 0, sizeof(ts
));
10777 ts
.table
= bgp
->rib
[afi
][safi
];
10778 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10780 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10781 if (!table_stats_strs
[i
])
10786 case BGP_STATS_ASPATH_AVGHOPS
:
10787 case BGP_STATS_ASPATH_AVGSIZE
:
10788 case BGP_STATS_AVGPLEN
:
10789 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10790 vty_out (vty
, "%12.2f",
10791 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10794 case BGP_STATS_ASPATH_TOTHOPS
:
10795 case BGP_STATS_ASPATH_TOTSIZE
:
10796 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10797 vty_out(vty
, "%12.2f",
10799 ? (float)ts
.counts
[i
]
10801 [BGP_STATS_ASPATH_COUNT
]
10804 case BGP_STATS_TOTPLEN
:
10805 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10806 vty_out(vty
, "%12.2f",
10808 ? (float)ts
.counts
[i
]
10810 [BGP_STATS_PREFIXES
]
10813 case BGP_STATS_SPACE
:
10814 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10815 vty_out(vty
, "%12g\n", ts
.total_space
);
10817 if (afi
== AFI_IP6
) {
10818 vty_out(vty
, "%30s: ", "/32 equivalent ");
10819 vty_out(vty
, "%12g\n",
10820 ts
.total_space
* pow(2.0, -128 + 32));
10821 vty_out(vty
, "%30s: ", "/48 equivalent ");
10822 vty_out(vty
, "%12g\n",
10823 ts
.total_space
* pow(2.0, -128 + 48));
10825 vty_out(vty
, "%30s: ", "% announced ");
10826 vty_out(vty
, "%12.2f\n",
10827 ts
.total_space
* 100. * pow(2.0, -32));
10828 vty_out(vty
, "%30s: ", "/8 equivalent ");
10829 vty_out(vty
, "%12.2f\n",
10830 ts
.total_space
* pow(2.0, -32 + 8));
10831 vty_out(vty
, "%30s: ", "/24 equivalent ");
10832 vty_out(vty
, "%12.2f\n",
10833 ts
.total_space
* pow(2.0, -32 + 24));
10837 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10838 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10841 vty_out(vty
, "\n");
10843 return CMD_SUCCESS
;
10855 PCOUNT_PFCNT
, /* the figure we display to users */
10859 static const char *pcount_strs
[] = {
10860 [PCOUNT_ADJ_IN
] = "Adj-in",
10861 [PCOUNT_DAMPED
] = "Damped",
10862 [PCOUNT_REMOVED
] = "Removed",
10863 [PCOUNT_HISTORY
] = "History",
10864 [PCOUNT_STALE
] = "Stale",
10865 [PCOUNT_VALID
] = "Valid",
10866 [PCOUNT_ALL
] = "All RIB",
10867 [PCOUNT_COUNTED
] = "PfxCt counted",
10868 [PCOUNT_PFCNT
] = "Useable",
10869 [PCOUNT_MAX
] = NULL
,
10872 struct peer_pcounts
{
10873 unsigned int count
[PCOUNT_MAX
];
10874 const struct peer
*peer
;
10875 const struct bgp_table
*table
;
10878 static int bgp_peer_count_walker(struct thread
*t
)
10880 struct bgp_node
*rn
;
10881 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10882 const struct peer
*peer
= pc
->peer
;
10884 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10885 struct bgp_adj_in
*ain
;
10886 struct bgp_path_info
*pi
;
10888 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10889 if (ain
->peer
== peer
)
10890 pc
->count
[PCOUNT_ADJ_IN
]++;
10892 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10894 if (pi
->peer
!= peer
)
10897 pc
->count
[PCOUNT_ALL
]++;
10899 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10900 pc
->count
[PCOUNT_DAMPED
]++;
10901 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10902 pc
->count
[PCOUNT_HISTORY
]++;
10903 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10904 pc
->count
[PCOUNT_REMOVED
]++;
10905 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10906 pc
->count
[PCOUNT_STALE
]++;
10907 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10908 pc
->count
[PCOUNT_VALID
]++;
10909 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10910 pc
->count
[PCOUNT_PFCNT
]++;
10912 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10913 pc
->count
[PCOUNT_COUNTED
]++;
10914 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10916 EC_LIB_DEVELOPMENT
,
10917 "Attempting to count but flags say it is unusable");
10919 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10921 EC_LIB_DEVELOPMENT
,
10922 "Not counted but flags say we should");
10929 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10930 safi_t safi
, bool use_json
)
10932 struct peer_pcounts pcounts
= {.peer
= peer
};
10934 json_object
*json
= NULL
;
10935 json_object
*json_loop
= NULL
;
10938 json
= json_object_new_object();
10939 json_loop
= json_object_new_object();
10942 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10943 || !peer
->bgp
->rib
[afi
][safi
]) {
10945 json_object_string_add(
10947 "No such neighbor or address family");
10948 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10949 json_object_free(json
);
10951 vty_out(vty
, "%% No such neighbor or address family\n");
10953 return CMD_WARNING
;
10956 memset(&pcounts
, 0, sizeof(pcounts
));
10957 pcounts
.peer
= peer
;
10958 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10960 /* in-place call via thread subsystem so as to record execution time
10961 * stats for the thread-walk (i.e. ensure this can't be blamed on
10962 * on just vty_read()).
10964 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10967 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10968 json_object_string_add(json
, "multiProtocol",
10969 get_afi_safi_str(afi
, safi
, true));
10970 json_object_int_add(json
, "pfxCounter",
10971 peer
->pcount
[afi
][safi
]);
10973 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10974 json_object_int_add(json_loop
, pcount_strs
[i
],
10977 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10979 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10980 json_object_string_add(json
, "pfxctDriftFor",
10982 json_object_string_add(
10983 json
, "recommended",
10984 "Please report this bug, with the above command output");
10986 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10987 json
, JSON_C_TO_STRING_PRETTY
));
10988 json_object_free(json
);
10992 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10993 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10994 peer
->hostname
, peer
->host
,
10995 get_afi_safi_str(afi
, safi
, false));
10997 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10998 get_afi_safi_str(afi
, safi
, false));
11001 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
11002 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11004 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11005 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
11008 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11009 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
11011 "Please report this bug, with the above command output\n");
11015 return CMD_SUCCESS
;
11018 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11019 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11020 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11021 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11025 BGP_INSTANCE_HELP_STR
11028 "Detailed information on TCP and BGP neighbor connections\n"
11029 "Neighbor to display information about\n"
11030 "Neighbor to display information about\n"
11031 "Neighbor on BGP configured interface\n"
11032 "Display detailed prefix count information\n"
11035 afi_t afi
= AFI_IP6
;
11036 safi_t safi
= SAFI_UNICAST
;
11039 struct bgp
*bgp
= NULL
;
11040 bool uj
= use_json(argc
, argv
);
11045 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11048 return CMD_WARNING
;
11050 argv_find(argv
, argc
, "neighbors", &idx
);
11051 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11053 return CMD_WARNING
;
11055 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11058 #ifdef KEEP_OLD_VPN_COMMANDS
11059 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11060 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11061 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11066 "Display information about all VPNv4 NLRIs\n"
11067 "Detailed information on TCP and BGP neighbor connections\n"
11068 "Neighbor to display information about\n"
11069 "Neighbor to display information about\n"
11070 "Neighbor on BGP configured interface\n"
11071 "Display detailed prefix count information\n"
11076 bool uj
= use_json(argc
, argv
);
11078 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11080 return CMD_WARNING
;
11082 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11085 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11086 show_ip_bgp_vpn_all_route_prefix_cmd
,
11087 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11092 "Display information about all VPNv4 NLRIs\n"
11093 "Network in the BGP routing table to display\n"
11094 "Network in the BGP routing table to display\n"
11098 char *network
= NULL
;
11099 struct bgp
*bgp
= bgp_get_default();
11101 vty_out(vty
, "Can't find default instance\n");
11102 return CMD_WARNING
;
11105 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11106 network
= argv
[idx
]->arg
;
11107 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11108 network
= argv
[idx
]->arg
;
11110 vty_out(vty
, "Unable to figure out Network\n");
11111 return CMD_WARNING
;
11114 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11115 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11117 #endif /* KEEP_OLD_VPN_COMMANDS */
11119 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11120 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11121 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11126 "Network in the BGP routing table to display\n"
11127 "Network in the BGP routing table to display\n"
11128 "Network in the BGP routing table to display\n"
11129 "Network in the BGP routing table to display\n"
11133 char *network
= NULL
;
11134 int prefix_check
= 0;
11136 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11137 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11138 network
= argv
[idx
]->arg
;
11139 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11140 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11141 network
= argv
[idx
]->arg
;
11144 vty_out(vty
, "Unable to figure out Network\n");
11145 return CMD_WARNING
;
11147 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11148 prefix_check
, BGP_PATH_SHOW_ALL
,
11149 use_json(argc
, argv
));
11152 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11153 safi_t safi
, enum bgp_show_adj_route_type type
,
11154 const char *rmap_name
, bool use_json
,
11157 struct bgp_table
*table
;
11158 struct bgp_adj_in
*ain
;
11159 struct bgp_adj_out
*adj
;
11160 unsigned long output_count
;
11161 unsigned long filtered_count
;
11162 struct bgp_node
*rn
;
11168 struct update_subgroup
*subgrp
;
11169 json_object
*json_scode
= NULL
;
11170 json_object
*json_ocode
= NULL
;
11171 json_object
*json_ar
= NULL
;
11172 struct peer_af
*paf
;
11173 bool route_filtered
;
11176 json_scode
= json_object_new_object();
11177 json_ocode
= json_object_new_object();
11178 json_ar
= json_object_new_object();
11180 json_object_string_add(json_scode
, "suppressed", "s");
11181 json_object_string_add(json_scode
, "damped", "d");
11182 json_object_string_add(json_scode
, "history", "h");
11183 json_object_string_add(json_scode
, "valid", "*");
11184 json_object_string_add(json_scode
, "best", ">");
11185 json_object_string_add(json_scode
, "multipath", "=");
11186 json_object_string_add(json_scode
, "internal", "i");
11187 json_object_string_add(json_scode
, "ribFailure", "r");
11188 json_object_string_add(json_scode
, "stale", "S");
11189 json_object_string_add(json_scode
, "removed", "R");
11191 json_object_string_add(json_ocode
, "igp", "i");
11192 json_object_string_add(json_ocode
, "egp", "e");
11193 json_object_string_add(json_ocode
, "incomplete", "?");
11200 json_object_string_add(json
, "alert", "no BGP");
11201 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11202 json_object_free(json
);
11204 vty_out(vty
, "%% No bgp\n");
11208 /* labeled-unicast routes live in the unicast table */
11209 if (safi
== SAFI_LABELED_UNICAST
)
11210 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11212 table
= bgp
->rib
[afi
][safi
];
11214 output_count
= filtered_count
= 0;
11215 subgrp
= peer_subgroup(peer
, afi
, safi
);
11217 if (type
== bgp_show_adj_route_advertised
&& subgrp
11218 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11220 json_object_int_add(json
, "bgpTableVersion",
11222 json_object_string_add(json
, "bgpLocalRouterId",
11223 inet_ntoa(bgp
->router_id
));
11224 json_object_int_add(json
, "defaultLocPrf",
11225 bgp
->default_local_pref
);
11226 json_object_int_add(json
, "localAS", bgp
->as
);
11227 json_object_object_add(json
, "bgpStatusCodes",
11229 json_object_object_add(json
, "bgpOriginCodes",
11231 json_object_string_add(
11232 json
, "bgpOriginatingDefaultNetwork",
11233 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11235 vty_out(vty
, "BGP table version is %" PRIu64
11236 ", local router ID is %s, vrf id ",
11237 table
->version
, inet_ntoa(bgp
->router_id
));
11238 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11239 vty_out(vty
, "%s", VRFID_NONE_STR
);
11241 vty_out(vty
, "%u", bgp
->vrf_id
);
11242 vty_out(vty
, "\n");
11243 vty_out(vty
, "Default local pref %u, ",
11244 bgp
->default_local_pref
);
11245 vty_out(vty
, "local AS %u\n", bgp
->as
);
11246 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11247 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11248 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11250 vty_out(vty
, "Originating default network %s\n\n",
11251 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11256 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11257 if (type
== bgp_show_adj_route_received
11258 || type
== bgp_show_adj_route_filtered
) {
11259 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11260 if (ain
->peer
!= peer
)
11265 json_object_int_add(
11266 json
, "bgpTableVersion",
11268 json_object_string_add(
11270 "bgpLocalRouterId",
11273 json_object_int_add(json
,
11275 bgp
->default_local_pref
);
11276 json_object_int_add(json
,
11277 "localAS", bgp
->as
);
11278 json_object_object_add(
11279 json
, "bgpStatusCodes",
11281 json_object_object_add(
11282 json
, "bgpOriginCodes",
11286 "BGP table version is 0, local router ID is %s, vrf id ",
11289 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11295 vty_out(vty
, "\n");
11297 "Default local pref %u, ",
11298 bgp
->default_local_pref
);
11299 vty_out(vty
, "local AS %u\n",
11302 BGP_SHOW_SCODE_HEADER
);
11304 BGP_SHOW_NCODE_HEADER
);
11306 BGP_SHOW_OCODE_HEADER
);
11312 vty_out(vty
, BGP_SHOW_HEADER
);
11316 bgp_attr_dup(&attr
, ain
->attr
);
11317 route_filtered
= false;
11319 /* Filter prefix using distribute list,
11320 * filter list or prefix list
11322 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11323 safi
)) == FILTER_DENY
)
11324 route_filtered
= true;
11326 /* Filter prefix using route-map */
11327 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11328 afi
, safi
, rmap_name
, NULL
, 0,
11331 if (type
== bgp_show_adj_route_filtered
&&
11332 !route_filtered
&& ret
!= RMAP_DENY
) {
11333 bgp_attr_undup(&attr
, ain
->attr
);
11337 if (type
== bgp_show_adj_route_received
&&
11338 (route_filtered
|| ret
== RMAP_DENY
))
11341 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11342 use_json
, json_ar
);
11343 bgp_attr_undup(&attr
, ain
->attr
);
11346 } else if (type
== bgp_show_adj_route_advertised
) {
11347 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11348 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11349 if (paf
->peer
!= peer
|| !adj
->attr
)
11354 json_object_int_add(
11358 json_object_string_add(
11360 "bgpLocalRouterId",
11363 json_object_int_add(
11364 json
, "defaultLocPrf",
11365 bgp
->default_local_pref
11367 json_object_int_add(
11370 json_object_object_add(
11374 json_object_object_add(
11380 "BGP table version is %" PRIu64
11381 ", local router ID is %s, vrf id ",
11394 vty_out(vty
, "\n");
11396 "Default local pref %u, ",
11397 bgp
->default_local_pref
11403 BGP_SHOW_SCODE_HEADER
);
11405 BGP_SHOW_NCODE_HEADER
);
11407 BGP_SHOW_OCODE_HEADER
);
11418 bgp_attr_dup(&attr
, adj
->attr
);
11419 ret
= bgp_output_modifier(
11420 peer
, &rn
->p
, &attr
, afi
, safi
,
11423 if (ret
!= RMAP_DENY
) {
11424 route_vty_out_tmp(vty
, &rn
->p
,
11433 bgp_attr_undup(&attr
, adj
->attr
);
11439 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11440 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11441 json_object_int_add(json
, "filteredPrefixCounter",
11444 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11445 json
, JSON_C_TO_STRING_PRETTY
));
11446 json_object_free(json
);
11447 } else if (output_count
> 0) {
11448 if (filtered_count
> 0)
11450 "\nTotal number of prefixes %ld (%ld filtered)\n",
11451 output_count
, filtered_count
);
11453 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11458 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11459 safi_t safi
, enum bgp_show_adj_route_type type
,
11460 const char *rmap_name
, bool use_json
)
11462 json_object
*json
= NULL
;
11465 json
= json_object_new_object();
11467 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11469 json_object_string_add(
11471 "No such neighbor or address family");
11472 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11473 json_object_free(json
);
11475 vty_out(vty
, "%% No such neighbor or address family\n");
11477 return CMD_WARNING
;
11480 if ((type
== bgp_show_adj_route_received
11481 || type
== bgp_show_adj_route_filtered
)
11482 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11483 PEER_FLAG_SOFT_RECONFIG
)) {
11485 json_object_string_add(
11487 "Inbound soft reconfiguration not enabled");
11488 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11489 json_object_free(json
);
11492 "%% Inbound soft reconfiguration not enabled\n");
11494 return CMD_WARNING
;
11497 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11499 return CMD_SUCCESS
;
11502 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11503 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11504 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11505 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11509 BGP_INSTANCE_HELP_STR
11511 BGP_SAFI_WITH_LABEL_HELP_STR
11512 "Detailed information on TCP and BGP neighbor connections\n"
11513 "Neighbor to display information about\n"
11514 "Neighbor to display information about\n"
11515 "Neighbor on BGP configured interface\n"
11516 "Display the routes advertised to a BGP neighbor\n"
11517 "Display the received routes from neighbor\n"
11518 "Display the filtered routes received from neighbor\n"
11519 "Route-map to modify the attributes\n"
11520 "Name of the route map\n"
11523 afi_t afi
= AFI_IP6
;
11524 safi_t safi
= SAFI_UNICAST
;
11525 char *rmap_name
= NULL
;
11526 char *peerstr
= NULL
;
11527 struct bgp
*bgp
= NULL
;
11529 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11531 bool uj
= use_json(argc
, argv
);
11536 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11539 return CMD_WARNING
;
11541 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11542 argv_find(argv
, argc
, "neighbors", &idx
);
11543 peerstr
= argv
[++idx
]->arg
;
11545 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11547 return CMD_WARNING
;
11549 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11550 type
= bgp_show_adj_route_advertised
;
11551 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11552 type
= bgp_show_adj_route_received
;
11553 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11554 type
= bgp_show_adj_route_filtered
;
11556 if (argv_find(argv
, argc
, "route-map", &idx
))
11557 rmap_name
= argv
[++idx
]->arg
;
11559 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11562 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11563 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11564 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11570 "Address Family modifier\n"
11571 "Detailed information on TCP and BGP neighbor connections\n"
11572 "Neighbor to display information about\n"
11573 "Neighbor to display information about\n"
11574 "Neighbor on BGP configured interface\n"
11575 "Display information received from a BGP neighbor\n"
11576 "Display the prefixlist filter\n"
11579 afi_t afi
= AFI_IP6
;
11580 safi_t safi
= SAFI_UNICAST
;
11581 char *peerstr
= NULL
;
11584 union sockunion su
;
11590 /* show [ip] bgp */
11591 if (argv_find(argv
, argc
, "ip", &idx
))
11593 /* [<ipv4|ipv6> [unicast]] */
11594 if (argv_find(argv
, argc
, "ipv4", &idx
))
11596 if (argv_find(argv
, argc
, "ipv6", &idx
))
11598 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11599 argv_find(argv
, argc
, "neighbors", &idx
);
11600 peerstr
= argv
[++idx
]->arg
;
11602 bool uj
= use_json(argc
, argv
);
11604 ret
= str2sockunion(peerstr
, &su
);
11606 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11609 vty_out(vty
, "{}\n");
11612 "%% Malformed address or name: %s\n",
11614 return CMD_WARNING
;
11617 peer
= peer_lookup(NULL
, &su
);
11620 vty_out(vty
, "{}\n");
11622 vty_out(vty
, "No peer\n");
11623 return CMD_WARNING
;
11627 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11628 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11631 vty_out(vty
, "Address Family: %s\n",
11632 get_afi_safi_str(afi
, safi
, false));
11633 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11636 vty_out(vty
, "{}\n");
11638 vty_out(vty
, "No functional output\n");
11641 return CMD_SUCCESS
;
11644 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11645 afi_t afi
, safi_t safi
,
11646 enum bgp_show_type type
, bool use_json
)
11648 /* labeled-unicast routes live in the unicast table */
11649 if (safi
== SAFI_LABELED_UNICAST
)
11650 safi
= SAFI_UNICAST
;
11652 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11654 json_object
*json_no
= NULL
;
11655 json_no
= json_object_new_object();
11656 json_object_string_add(
11657 json_no
, "warning",
11658 "No such neighbor or address family");
11659 vty_out(vty
, "%s\n",
11660 json_object_to_json_string(json_no
));
11661 json_object_free(json_no
);
11663 vty_out(vty
, "%% No such neighbor or address family\n");
11664 return CMD_WARNING
;
11667 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11670 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11671 show_ip_bgp_flowspec_routes_detailed_cmd
,
11672 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11676 BGP_INSTANCE_HELP_STR
11679 "Detailed information on flowspec entries\n"
11682 afi_t afi
= AFI_IP
;
11683 safi_t safi
= SAFI_UNICAST
;
11684 struct bgp
*bgp
= NULL
;
11686 bool uj
= use_json(argc
, argv
);
11691 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11694 return CMD_WARNING
;
11696 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11699 DEFUN (show_ip_bgp_neighbor_routes
,
11700 show_ip_bgp_neighbor_routes_cmd
,
11701 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11702 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11706 BGP_INSTANCE_HELP_STR
11708 BGP_SAFI_WITH_LABEL_HELP_STR
11709 "Detailed information on TCP and BGP neighbor connections\n"
11710 "Neighbor to display information about\n"
11711 "Neighbor to display information about\n"
11712 "Neighbor on BGP configured interface\n"
11713 "Display flap statistics of the routes learned from neighbor\n"
11714 "Display the dampened routes received from neighbor\n"
11715 "Display routes learned from neighbor\n"
11718 char *peerstr
= NULL
;
11719 struct bgp
*bgp
= NULL
;
11720 afi_t afi
= AFI_IP6
;
11721 safi_t safi
= SAFI_UNICAST
;
11723 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11725 bool uj
= use_json(argc
, argv
);
11730 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11733 return CMD_WARNING
;
11735 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11736 argv_find(argv
, argc
, "neighbors", &idx
);
11737 peerstr
= argv
[++idx
]->arg
;
11739 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11741 return CMD_WARNING
;
11743 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11744 sh_type
= bgp_show_type_flap_neighbor
;
11745 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11746 sh_type
= bgp_show_type_damp_neighbor
;
11747 else if (argv_find(argv
, argc
, "routes", &idx
))
11748 sh_type
= bgp_show_type_neighbor
;
11750 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11753 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11755 struct bgp_distance
{
11756 /* Distance value for the IP source prefix. */
11759 /* Name of the access-list to be matched. */
11763 DEFUN (show_bgp_afi_vpn_rd_route
,
11764 show_bgp_afi_vpn_rd_route_cmd
,
11765 "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]",
11769 "Address Family modifier\n"
11770 "Display information for a route distinguisher\n"
11771 "Route Distinguisher\n"
11772 "Network in the BGP routing table to display\n"
11773 "Network in the BGP routing table to display\n"
11777 struct prefix_rd prd
;
11778 afi_t afi
= AFI_MAX
;
11781 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11782 vty_out(vty
, "%% Malformed Address Family\n");
11783 return CMD_WARNING
;
11786 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11788 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11789 return CMD_WARNING
;
11792 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11793 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11796 static struct bgp_distance
*bgp_distance_new(void)
11798 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11801 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11803 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11806 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11807 const char *ip_str
, const char *access_list_str
)
11814 struct bgp_node
*rn
;
11815 struct bgp_distance
*bdistance
;
11817 afi
= bgp_node_afi(vty
);
11818 safi
= bgp_node_safi(vty
);
11820 ret
= str2prefix(ip_str
, &p
);
11822 vty_out(vty
, "Malformed prefix\n");
11823 return CMD_WARNING_CONFIG_FAILED
;
11826 distance
= atoi(distance_str
);
11828 /* Get BGP distance node. */
11829 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11830 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11832 bgp_unlock_node(rn
);
11834 bdistance
= bgp_distance_new();
11835 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11838 /* Set distance value. */
11839 bdistance
->distance
= distance
;
11841 /* Reset access-list configuration. */
11842 if (bdistance
->access_list
) {
11843 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11844 bdistance
->access_list
= NULL
;
11846 if (access_list_str
)
11847 bdistance
->access_list
=
11848 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11850 return CMD_SUCCESS
;
11853 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11854 const char *ip_str
, const char *access_list_str
)
11861 struct bgp_node
*rn
;
11862 struct bgp_distance
*bdistance
;
11864 afi
= bgp_node_afi(vty
);
11865 safi
= bgp_node_safi(vty
);
11867 ret
= str2prefix(ip_str
, &p
);
11869 vty_out(vty
, "Malformed prefix\n");
11870 return CMD_WARNING_CONFIG_FAILED
;
11873 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11874 (struct prefix
*)&p
);
11876 vty_out(vty
, "Can't find specified prefix\n");
11877 return CMD_WARNING_CONFIG_FAILED
;
11880 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11881 distance
= atoi(distance_str
);
11883 if (bdistance
->distance
!= distance
) {
11884 vty_out(vty
, "Distance does not match configured\n");
11885 return CMD_WARNING_CONFIG_FAILED
;
11888 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11889 bgp_distance_free(bdistance
);
11891 bgp_node_set_bgp_path_info(rn
, NULL
);
11892 bgp_unlock_node(rn
);
11893 bgp_unlock_node(rn
);
11895 return CMD_SUCCESS
;
11898 /* Apply BGP information to distance method. */
11899 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11900 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11902 struct bgp_node
*rn
;
11905 struct bgp_distance
*bdistance
;
11906 struct access_list
*alist
;
11907 struct bgp_static
*bgp_static
;
11912 peer
= pinfo
->peer
;
11914 if (pinfo
->attr
->distance
)
11915 return pinfo
->attr
->distance
;
11917 /* Check source address. */
11918 sockunion2hostprefix(&peer
->su
, &q
);
11919 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11921 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11922 bgp_unlock_node(rn
);
11924 if (bdistance
->access_list
) {
11925 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11927 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11928 return bdistance
->distance
;
11930 return bdistance
->distance
;
11933 /* Backdoor check. */
11934 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11936 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11937 bgp_unlock_node(rn
);
11939 if (bgp_static
->backdoor
) {
11940 if (bgp
->distance_local
[afi
][safi
])
11941 return bgp
->distance_local
[afi
][safi
];
11943 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11947 if (peer
->sort
== BGP_PEER_EBGP
) {
11948 if (bgp
->distance_ebgp
[afi
][safi
])
11949 return bgp
->distance_ebgp
[afi
][safi
];
11950 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11952 if (bgp
->distance_ibgp
[afi
][safi
])
11953 return bgp
->distance_ibgp
[afi
][safi
];
11954 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11958 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
11959 * we should tell ZEBRA update the routes for a specific
11960 * AFI/SAFI to reflect changes in RIB.
11962 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
11964 safi_t update_safi
)
11969 FOREACH_AFI_SAFI (afi
, safi
) {
11970 if (!bgp_fibupd_safi(safi
))
11973 if (afi
!= update_afi
&& safi
!= update_safi
)
11976 if (BGP_DEBUG(zebra
, ZEBRA
))
11978 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
11979 __func__
, afi
, safi
);
11980 bgp_zebra_announce_table(bgp
, afi
, safi
);
11984 DEFUN (bgp_distance
,
11986 "distance bgp (1-255) (1-255) (1-255)",
11987 "Define an administrative distance\n"
11989 "Distance for routes external to the AS\n"
11990 "Distance for routes internal to the AS\n"
11991 "Distance for local routes\n")
11993 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11994 int idx_number
= 2;
11995 int idx_number_2
= 3;
11996 int idx_number_3
= 4;
11997 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
11998 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
11999 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
12003 afi
= bgp_node_afi(vty
);
12004 safi
= bgp_node_safi(vty
);
12006 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
12007 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
12008 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
12009 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
12010 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
12011 bgp
->distance_local
[afi
][safi
] = distance_local
;
12012 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12014 return CMD_SUCCESS
;
12017 DEFUN (no_bgp_distance
,
12018 no_bgp_distance_cmd
,
12019 "no distance bgp [(1-255) (1-255) (1-255)]",
12021 "Define an administrative distance\n"
12023 "Distance for routes external to the AS\n"
12024 "Distance for routes internal to the AS\n"
12025 "Distance for local routes\n")
12027 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12031 afi
= bgp_node_afi(vty
);
12032 safi
= bgp_node_safi(vty
);
12034 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12035 || bgp
->distance_ibgp
[afi
][safi
] != 0
12036 || bgp
->distance_local
[afi
][safi
] != 0) {
12037 bgp
->distance_ebgp
[afi
][safi
] = 0;
12038 bgp
->distance_ibgp
[afi
][safi
] = 0;
12039 bgp
->distance_local
[afi
][safi
] = 0;
12040 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12042 return CMD_SUCCESS
;
12046 DEFUN (bgp_distance_source
,
12047 bgp_distance_source_cmd
,
12048 "distance (1-255) A.B.C.D/M",
12049 "Define an administrative distance\n"
12050 "Administrative distance\n"
12051 "IP source prefix\n")
12053 int idx_number
= 1;
12054 int idx_ipv4_prefixlen
= 2;
12055 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12056 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12057 return CMD_SUCCESS
;
12060 DEFUN (no_bgp_distance_source
,
12061 no_bgp_distance_source_cmd
,
12062 "no distance (1-255) A.B.C.D/M",
12064 "Define an administrative distance\n"
12065 "Administrative distance\n"
12066 "IP source prefix\n")
12068 int idx_number
= 2;
12069 int idx_ipv4_prefixlen
= 3;
12070 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12071 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12072 return CMD_SUCCESS
;
12075 DEFUN (bgp_distance_source_access_list
,
12076 bgp_distance_source_access_list_cmd
,
12077 "distance (1-255) A.B.C.D/M WORD",
12078 "Define an administrative distance\n"
12079 "Administrative distance\n"
12080 "IP source prefix\n"
12081 "Access list name\n")
12083 int idx_number
= 1;
12084 int idx_ipv4_prefixlen
= 2;
12086 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12087 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12088 return CMD_SUCCESS
;
12091 DEFUN (no_bgp_distance_source_access_list
,
12092 no_bgp_distance_source_access_list_cmd
,
12093 "no distance (1-255) A.B.C.D/M WORD",
12095 "Define an administrative distance\n"
12096 "Administrative distance\n"
12097 "IP source prefix\n"
12098 "Access list name\n")
12100 int idx_number
= 2;
12101 int idx_ipv4_prefixlen
= 3;
12103 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12104 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12105 return CMD_SUCCESS
;
12108 DEFUN (ipv6_bgp_distance_source
,
12109 ipv6_bgp_distance_source_cmd
,
12110 "distance (1-255) X:X::X:X/M",
12111 "Define an administrative distance\n"
12112 "Administrative distance\n"
12113 "IP source prefix\n")
12115 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12116 return CMD_SUCCESS
;
12119 DEFUN (no_ipv6_bgp_distance_source
,
12120 no_ipv6_bgp_distance_source_cmd
,
12121 "no distance (1-255) X:X::X:X/M",
12123 "Define an administrative distance\n"
12124 "Administrative distance\n"
12125 "IP source prefix\n")
12127 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12128 return CMD_SUCCESS
;
12131 DEFUN (ipv6_bgp_distance_source_access_list
,
12132 ipv6_bgp_distance_source_access_list_cmd
,
12133 "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_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12140 return CMD_SUCCESS
;
12143 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12144 no_ipv6_bgp_distance_source_access_list_cmd
,
12145 "no distance (1-255) X:X::X:X/M WORD",
12147 "Define an administrative distance\n"
12148 "Administrative distance\n"
12149 "IP source prefix\n"
12150 "Access list name\n")
12152 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12153 return CMD_SUCCESS
;
12156 DEFUN (bgp_damp_set
,
12158 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12159 "BGP Specific commands\n"
12160 "Enable route-flap dampening\n"
12161 "Half-life time for the penalty\n"
12162 "Value to start reusing a route\n"
12163 "Value to start suppressing a route\n"
12164 "Maximum duration to suppress a stable route\n")
12166 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12167 int idx_half_life
= 2;
12169 int idx_suppress
= 4;
12170 int idx_max_suppress
= 5;
12171 int half
= DEFAULT_HALF_LIFE
* 60;
12172 int reuse
= DEFAULT_REUSE
;
12173 int suppress
= DEFAULT_SUPPRESS
;
12174 int max
= 4 * half
;
12177 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12178 reuse
= atoi(argv
[idx_reuse
]->arg
);
12179 suppress
= atoi(argv
[idx_suppress
]->arg
);
12180 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12181 } else if (argc
== 3) {
12182 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12186 if (suppress
< reuse
) {
12188 "Suppress value cannot be less than reuse value \n");
12192 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12193 reuse
, suppress
, max
);
12196 DEFUN (bgp_damp_unset
,
12197 bgp_damp_unset_cmd
,
12198 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12200 "BGP Specific commands\n"
12201 "Enable route-flap dampening\n"
12202 "Half-life time for the penalty\n"
12203 "Value to start reusing a route\n"
12204 "Value to start suppressing a route\n"
12205 "Maximum duration to suppress a stable route\n")
12207 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12208 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12211 /* Display specified route of BGP table. */
12212 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12213 const char *ip_str
, afi_t afi
, safi_t safi
,
12214 struct prefix_rd
*prd
, int prefix_check
)
12217 struct prefix match
;
12218 struct bgp_node
*rn
;
12219 struct bgp_node
*rm
;
12220 struct bgp_path_info
*pi
;
12221 struct bgp_path_info
*pi_temp
;
12223 struct bgp_table
*table
;
12225 /* BGP structure lookup. */
12227 bgp
= bgp_lookup_by_name(view_name
);
12229 vty_out(vty
, "%% Can't find BGP instance %s\n",
12231 return CMD_WARNING
;
12234 bgp
= bgp_get_default();
12236 vty_out(vty
, "%% No BGP process is configured\n");
12237 return CMD_WARNING
;
12241 /* Check IP address argument. */
12242 ret
= str2prefix(ip_str
, &match
);
12244 vty_out(vty
, "%% address is malformed\n");
12245 return CMD_WARNING
;
12248 match
.family
= afi2family(afi
);
12250 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12251 || (safi
== SAFI_EVPN
)) {
12252 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12253 rn
= bgp_route_next(rn
)) {
12254 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12256 table
= bgp_node_get_bgp_table_info(rn
);
12259 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12263 || rm
->p
.prefixlen
== match
.prefixlen
) {
12264 pi
= bgp_node_get_bgp_path_info(rm
);
12266 if (pi
->extra
&& pi
->extra
->damp_info
) {
12267 pi_temp
= pi
->next
;
12268 bgp_damp_info_free(
12269 pi
->extra
->damp_info
,
12277 bgp_unlock_node(rm
);
12280 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12283 || rn
->p
.prefixlen
== match
.prefixlen
) {
12284 pi
= bgp_node_get_bgp_path_info(rn
);
12286 if (pi
->extra
&& pi
->extra
->damp_info
) {
12287 pi_temp
= pi
->next
;
12288 bgp_damp_info_free(
12289 pi
->extra
->damp_info
,
12297 bgp_unlock_node(rn
);
12301 return CMD_SUCCESS
;
12304 DEFUN (clear_ip_bgp_dampening
,
12305 clear_ip_bgp_dampening_cmd
,
12306 "clear ip bgp dampening",
12310 "Clear route flap dampening information\n")
12312 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
12313 return CMD_SUCCESS
;
12316 DEFUN (clear_ip_bgp_dampening_prefix
,
12317 clear_ip_bgp_dampening_prefix_cmd
,
12318 "clear ip bgp dampening A.B.C.D/M",
12322 "Clear route flap dampening information\n"
12325 int idx_ipv4_prefixlen
= 4;
12326 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12327 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12330 DEFUN (clear_ip_bgp_dampening_address
,
12331 clear_ip_bgp_dampening_address_cmd
,
12332 "clear ip bgp dampening A.B.C.D",
12336 "Clear route flap dampening information\n"
12337 "Network to clear damping information\n")
12340 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12341 SAFI_UNICAST
, NULL
, 0);
12344 DEFUN (clear_ip_bgp_dampening_address_mask
,
12345 clear_ip_bgp_dampening_address_mask_cmd
,
12346 "clear ip bgp dampening A.B.C.D A.B.C.D",
12350 "Clear route flap dampening information\n"
12351 "Network to clear damping information\n"
12355 int idx_ipv4_2
= 5;
12357 char prefix_str
[BUFSIZ
];
12359 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12362 vty_out(vty
, "%% Inconsistent address and mask\n");
12363 return CMD_WARNING
;
12366 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12370 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12372 struct vty
*vty
= arg
;
12373 struct peer
*peer
= bucket
->data
;
12374 char buf
[SU_ADDRSTRLEN
];
12376 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12377 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12380 DEFUN (show_bgp_peerhash
,
12381 show_bgp_peerhash_cmd
,
12382 "show bgp peerhash",
12385 "Display information about the BGP peerhash\n")
12387 struct list
*instances
= bm
->bgp
;
12388 struct listnode
*node
;
12391 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12392 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12393 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12397 return CMD_SUCCESS
;
12400 /* also used for encap safi */
12401 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12402 afi_t afi
, safi_t safi
)
12404 struct bgp_node
*prn
;
12405 struct bgp_node
*rn
;
12406 struct bgp_table
*table
;
12408 struct prefix_rd
*prd
;
12409 struct bgp_static
*bgp_static
;
12410 mpls_label_t label
;
12411 char buf
[SU_ADDRSTRLEN
];
12412 char rdbuf
[RD_ADDRSTRLEN
];
12414 /* Network configuration. */
12415 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12416 prn
= bgp_route_next(prn
)) {
12417 table
= bgp_node_get_bgp_table_info(prn
);
12421 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12422 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12423 if (bgp_static
== NULL
)
12427 prd
= (struct prefix_rd
*)&prn
->p
;
12429 /* "network" configuration display. */
12430 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12431 label
= decode_label(&bgp_static
->label
);
12433 vty_out(vty
, " network %s/%d rd %s",
12434 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12436 p
->prefixlen
, rdbuf
);
12437 if (safi
== SAFI_MPLS_VPN
)
12438 vty_out(vty
, " label %u", label
);
12440 if (bgp_static
->rmap
.name
)
12441 vty_out(vty
, " route-map %s",
12442 bgp_static
->rmap
.name
);
12444 if (bgp_static
->backdoor
)
12445 vty_out(vty
, " backdoor");
12447 vty_out(vty
, "\n");
12452 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12453 afi_t afi
, safi_t safi
)
12455 struct bgp_node
*prn
;
12456 struct bgp_node
*rn
;
12457 struct bgp_table
*table
;
12459 struct prefix_rd
*prd
;
12460 struct bgp_static
*bgp_static
;
12461 char buf
[PREFIX_STRLEN
* 2];
12462 char buf2
[SU_ADDRSTRLEN
];
12463 char rdbuf
[RD_ADDRSTRLEN
];
12465 /* Network configuration. */
12466 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12467 prn
= bgp_route_next(prn
)) {
12468 table
= bgp_node_get_bgp_table_info(prn
);
12472 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12473 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12474 if (bgp_static
== NULL
)
12477 char *macrouter
= NULL
;
12480 if (bgp_static
->router_mac
)
12481 macrouter
= prefix_mac2str(
12482 bgp_static
->router_mac
, NULL
, 0);
12483 if (bgp_static
->eth_s_id
)
12484 esi
= esi2str(bgp_static
->eth_s_id
);
12486 prd
= (struct prefix_rd
*)&prn
->p
;
12488 /* "network" configuration display. */
12489 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12490 if (p
->u
.prefix_evpn
.route_type
== 5) {
12491 char local_buf
[PREFIX_STRLEN
];
12492 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12493 struct prefix_evpn
*)p
)
12497 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12498 local_buf
, PREFIX_STRLEN
);
12499 sprintf(buf
, "%s/%u", local_buf
,
12500 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12502 prefix2str(p
, buf
, sizeof(buf
));
12505 if (bgp_static
->gatewayIp
.family
== AF_INET
12506 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12507 inet_ntop(bgp_static
->gatewayIp
.family
,
12508 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12511 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12513 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12514 decode_label(&bgp_static
->label
), esi
, buf2
,
12517 XFREE(MTYPE_TMP
, macrouter
);
12518 XFREE(MTYPE_TMP
, esi
);
12523 /* Configuration of static route announcement and aggregate
12525 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12528 struct bgp_node
*rn
;
12530 struct bgp_static
*bgp_static
;
12531 struct bgp_aggregate
*bgp_aggregate
;
12532 char buf
[SU_ADDRSTRLEN
];
12534 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12535 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12539 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12540 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12544 /* Network configuration. */
12545 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12546 rn
= bgp_route_next(rn
)) {
12547 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12548 if (bgp_static
== NULL
)
12553 vty_out(vty
, " network %s/%d",
12554 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12557 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12558 vty_out(vty
, " label-index %u",
12559 bgp_static
->label_index
);
12561 if (bgp_static
->rmap
.name
)
12562 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12564 if (bgp_static
->backdoor
)
12565 vty_out(vty
, " backdoor");
12567 vty_out(vty
, "\n");
12570 /* Aggregate-address configuration. */
12571 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12572 rn
= bgp_route_next(rn
)) {
12573 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12574 if (bgp_aggregate
== NULL
)
12579 vty_out(vty
, " aggregate-address %s/%d",
12580 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12583 if (bgp_aggregate
->as_set
)
12584 vty_out(vty
, " as-set");
12586 if (bgp_aggregate
->summary_only
)
12587 vty_out(vty
, " summary-only");
12589 if (bgp_aggregate
->rmap
.name
)
12590 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12592 vty_out(vty
, "\n");
12596 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12599 struct bgp_node
*rn
;
12600 struct bgp_distance
*bdistance
;
12602 /* Distance configuration. */
12603 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12604 && bgp
->distance_local
[afi
][safi
]
12605 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12606 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12607 || bgp
->distance_local
[afi
][safi
]
12608 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12609 vty_out(vty
, " distance bgp %d %d %d\n",
12610 bgp
->distance_ebgp
[afi
][safi
],
12611 bgp
->distance_ibgp
[afi
][safi
],
12612 bgp
->distance_local
[afi
][safi
]);
12615 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12616 rn
= bgp_route_next(rn
)) {
12617 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12618 if (bdistance
!= NULL
) {
12619 char buf
[PREFIX_STRLEN
];
12621 vty_out(vty
, " distance %d %s %s\n",
12622 bdistance
->distance
,
12623 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12624 bdistance
->access_list
? bdistance
->access_list
12630 /* Allocate routing table structure and install commands. */
12631 void bgp_route_init(void)
12636 /* Init BGP distance table. */
12637 FOREACH_AFI_SAFI (afi
, safi
)
12638 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12640 /* IPv4 BGP commands. */
12641 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12642 install_element(BGP_NODE
, &bgp_network_cmd
);
12643 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12645 install_element(BGP_NODE
, &aggregate_address_cmd
);
12646 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12647 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12648 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12650 /* IPv4 unicast configuration. */
12651 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12652 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12653 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12655 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12656 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12657 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12658 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12660 /* IPv4 multicast configuration. */
12661 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12662 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12663 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12664 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12665 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12666 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12667 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12669 /* IPv4 labeled-unicast configuration. */
12670 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12671 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12672 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12673 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12674 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12676 install_element(VIEW_NODE
,
12677 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12678 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12679 install_element(VIEW_NODE
,
12680 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12681 #ifdef KEEP_OLD_VPN_COMMANDS
12682 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12683 #endif /* KEEP_OLD_VPN_COMMANDS */
12684 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12685 install_element(VIEW_NODE
,
12686 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
12688 /* BGP dampening clear commands */
12689 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12690 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12692 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12693 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12696 install_element(ENABLE_NODE
,
12697 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12698 #ifdef KEEP_OLD_VPN_COMMANDS
12699 install_element(ENABLE_NODE
,
12700 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12701 #endif /* KEEP_OLD_VPN_COMMANDS */
12703 /* New config IPv6 BGP commands. */
12704 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12705 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12706 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12708 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12709 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12711 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12713 install_element(BGP_NODE
, &bgp_distance_cmd
);
12714 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12715 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12716 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12717 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12718 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12719 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12720 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12721 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12722 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12723 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12724 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12725 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12726 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12727 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12728 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12729 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12730 install_element(BGP_IPV4M_NODE
,
12731 &no_bgp_distance_source_access_list_cmd
);
12732 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12733 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12734 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12735 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12736 install_element(BGP_IPV6_NODE
,
12737 &ipv6_bgp_distance_source_access_list_cmd
);
12738 install_element(BGP_IPV6_NODE
,
12739 &no_ipv6_bgp_distance_source_access_list_cmd
);
12740 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12741 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12742 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12743 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12744 install_element(BGP_IPV6M_NODE
,
12745 &ipv6_bgp_distance_source_access_list_cmd
);
12746 install_element(BGP_IPV6M_NODE
,
12747 &no_ipv6_bgp_distance_source_access_list_cmd
);
12749 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12750 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12751 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12752 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12754 /* IPv4 Multicast Mode */
12755 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12756 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12758 /* Large Communities */
12759 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12760 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12762 /* show bgp ipv4 flowspec detailed */
12763 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12765 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12768 void bgp_route_finish(void)
12773 FOREACH_AFI_SAFI (afi
, safi
) {
12774 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12775 bgp_distance_table
[afi
][safi
] = NULL
;