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 (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3458 && peer
->ttl
== BGP_DEFAULT_TTL
3459 && !CHECK_FLAG(peer
->flags
,
3460 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3462 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3467 struct bgp
*bgp_nexthop
= bgp
;
3469 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3470 bgp_nexthop
= pi
->extra
->bgp_orig
;
3472 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3474 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3475 pi
, NULL
, connected
)
3476 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3477 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3479 if (BGP_DEBUG(nht
, NHT
)) {
3480 char buf1
[INET6_ADDRSTRLEN
];
3482 (const void *)&attr_new
3484 buf1
, INET6_ADDRSTRLEN
);
3485 zlog_debug("%s(%s): NH unresolved",
3486 __FUNCTION__
, buf1
);
3488 bgp_path_info_unset_flag(rn
, pi
,
3492 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3495 if (safi
== SAFI_MPLS_VPN
) {
3496 struct bgp_node
*prn
= NULL
;
3497 struct bgp_table
*table
= NULL
;
3499 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3500 (struct prefix
*)prd
);
3501 if (bgp_node_has_bgp_path_info_data(prn
)) {
3502 table
= bgp_node_get_bgp_table_info(prn
);
3504 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3505 bgp
, prd
, table
, p
, pi
);
3507 bgp_unlock_node(prn
);
3511 /* If this is an EVPN route and some attribute has changed,
3513 * route for import. If the extended community has changed, we
3515 * have done the un-import earlier and the import would result
3517 * route getting injected into appropriate L2 VNIs. If it is
3519 * some other attribute change, the import will result in
3521 * the attributes for the route in the VNI(s).
3523 if (safi
== SAFI_EVPN
&& !same_attr
&&
3524 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3525 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3527 /* Process change. */
3528 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3530 bgp_process(bgp
, rn
, afi
, safi
);
3531 bgp_unlock_node(rn
);
3533 if (SAFI_UNICAST
== safi
3534 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3535 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3537 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3539 if ((SAFI_MPLS_VPN
== safi
)
3540 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3542 vpn_leak_to_vrf_update(bgp
, pi
);
3546 if (SAFI_MPLS_VPN
== safi
) {
3547 mpls_label_t label_decoded
= decode_label(label
);
3549 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3550 type
, sub_type
, &label_decoded
);
3552 if (SAFI_ENCAP
== safi
) {
3553 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3554 type
, sub_type
, NULL
);
3559 } // End of implicit withdraw
3561 /* Received Logging. */
3562 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3563 if (!peer
->rcvd_attr_printed
) {
3564 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3565 peer
->rcvd_attr_str
);
3566 peer
->rcvd_attr_printed
= 1;
3569 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3570 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3572 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3575 /* Make new BGP info. */
3576 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3578 /* Update MPLS label */
3579 if (has_valid_label
) {
3580 extra
= bgp_path_info_extra_get(new);
3581 if (extra
->label
!= label
) {
3582 memcpy(&extra
->label
, label
,
3583 num_labels
* sizeof(mpls_label_t
));
3584 extra
->num_labels
= num_labels
;
3586 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3587 bgp_set_valid_label(&extra
->label
[0]);
3590 /* Update Overlay Index */
3591 if (afi
== AFI_L2VPN
) {
3592 overlay_index_update(new->attr
,
3593 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3594 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3596 /* Nexthop reachability check. */
3597 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3598 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3599 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
3600 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3601 && peer
->ttl
== BGP_DEFAULT_TTL
3602 && !CHECK_FLAG(peer
->flags
,
3603 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3604 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3609 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
3611 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
3613 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3614 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3616 if (BGP_DEBUG(nht
, NHT
)) {
3617 char buf1
[INET6_ADDRSTRLEN
];
3619 (const void *)&attr_new
->nexthop
,
3620 buf1
, INET6_ADDRSTRLEN
);
3621 zlog_debug("%s(%s): NH unresolved",
3622 __FUNCTION__
, buf1
);
3624 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3627 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3630 new->addpath_rx_id
= addpath_id
;
3632 /* Increment prefix */
3633 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3635 /* Register new BGP information. */
3636 bgp_path_info_add(rn
, new);
3638 /* route_node_get lock */
3639 bgp_unlock_node(rn
);
3642 if (safi
== SAFI_MPLS_VPN
) {
3643 struct bgp_node
*prn
= NULL
;
3644 struct bgp_table
*table
= NULL
;
3646 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3647 if (bgp_node_has_bgp_path_info_data(prn
)) {
3648 table
= bgp_node_get_bgp_table_info(prn
);
3650 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3651 bgp
, prd
, table
, p
, new);
3653 bgp_unlock_node(prn
);
3657 /* If maximum prefix count is configured and current prefix
3659 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3662 /* If this is an EVPN route, process for import. */
3663 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
3664 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3666 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3668 /* Process change. */
3669 bgp_process(bgp
, rn
, afi
, safi
);
3671 if (SAFI_UNICAST
== safi
3672 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3673 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3674 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3676 if ((SAFI_MPLS_VPN
== safi
)
3677 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3679 vpn_leak_to_vrf_update(bgp
, new);
3682 if (SAFI_MPLS_VPN
== safi
) {
3683 mpls_label_t label_decoded
= decode_label(label
);
3685 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3686 sub_type
, &label_decoded
);
3688 if (SAFI_ENCAP
== safi
) {
3689 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3696 /* This BGP update is filtered. Log the reason then update BGP
3699 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3701 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3702 if (!peer
->rcvd_attr_printed
) {
3703 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3704 peer
->rcvd_attr_str
);
3705 peer
->rcvd_attr_printed
= 1;
3708 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3709 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3711 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3712 peer
->host
, pfx_buf
, reason
);
3716 /* If this is an EVPN route, un-import it as it is now filtered.
3718 if (safi
== SAFI_EVPN
)
3719 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3721 if (SAFI_UNICAST
== safi
3722 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3723 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3725 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3727 if ((SAFI_MPLS_VPN
== safi
)
3728 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3730 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3733 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3736 bgp_unlock_node(rn
);
3740 * Filtered update is treated as an implicit withdrawal (see
3742 * a few lines above)
3744 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3745 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3753 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3754 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3755 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3756 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3759 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3760 struct bgp_node
*rn
;
3761 struct bgp_path_info
*pi
;
3764 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3765 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3773 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3775 /* If peer is soft reconfiguration enabled. Record input packet for
3776 * further calculation.
3778 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3779 * routes that are filtered. This tanks out Quagga RS pretty badly due
3781 * the iteration over all RS clients.
3782 * Since we need to remove the entry from adj_in anyway, do that first
3784 * if there was no entry, we don't need to do anything more.
3786 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3787 && peer
!= bgp
->peer_self
)
3788 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3789 peer
->stat_pfx_dup_withdraw
++;
3791 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3792 bgp_debug_rdpfxpath2str(
3793 afi
, safi
, prd
, p
, label
, num_labels
,
3794 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3797 "%s withdrawing route %s not in adj-in",
3798 peer
->host
, pfx_buf
);
3800 bgp_unlock_node(rn
);
3804 /* Lookup withdrawn route. */
3805 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3806 if (pi
->peer
== peer
&& pi
->type
== type
3807 && pi
->sub_type
== sub_type
3808 && pi
->addpath_rx_id
== addpath_id
)
3812 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3813 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3814 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3816 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3820 /* Withdraw specified route from routing table. */
3821 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3822 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3823 if (SAFI_UNICAST
== safi
3824 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3825 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3826 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3828 if ((SAFI_MPLS_VPN
== safi
)
3829 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3831 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3833 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3834 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3835 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3837 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3840 /* Unlock bgp_node_get() lock. */
3841 bgp_unlock_node(rn
);
3846 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3849 struct update_subgroup
*subgrp
;
3850 subgrp
= peer_subgroup(peer
, afi
, safi
);
3851 subgroup_default_originate(subgrp
, withdraw
);
3856 * bgp_stop_announce_route_timer
3858 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3860 if (!paf
->t_announce_route
)
3863 THREAD_TIMER_OFF(paf
->t_announce_route
);
3867 * bgp_announce_route_timer_expired
3869 * Callback that is invoked when the route announcement timer for a
3872 static int bgp_announce_route_timer_expired(struct thread
*t
)
3874 struct peer_af
*paf
;
3877 paf
= THREAD_ARG(t
);
3880 if (peer
->status
!= Established
)
3883 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3886 peer_af_announce_route(paf
, 1);
3891 * bgp_announce_route
3893 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3895 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3897 struct peer_af
*paf
;
3898 struct update_subgroup
*subgrp
;
3900 paf
= peer_af_find(peer
, afi
, safi
);
3903 subgrp
= PAF_SUBGRP(paf
);
3906 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3907 * or a refresh has already been triggered.
3909 if (!subgrp
|| paf
->t_announce_route
)
3913 * Start a timer to stagger/delay the announce. This serves
3914 * two purposes - announcement can potentially be combined for
3915 * multiple peers and the announcement doesn't happen in the
3918 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3919 (subgrp
->peer_count
== 1)
3920 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3921 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3922 &paf
->t_announce_route
);
3926 * Announce routes from all AF tables to a peer.
3928 * This should ONLY be called when there is a need to refresh the
3929 * routes to the peer based on a policy change for this peer alone
3930 * or a route refresh request received from the peer.
3931 * The operation will result in splitting the peer from its existing
3932 * subgroups and putting it in new subgroups.
3934 void bgp_announce_route_all(struct peer
*peer
)
3939 FOREACH_AFI_SAFI (afi
, safi
)
3940 bgp_announce_route(peer
, afi
, safi
);
3943 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3944 struct bgp_table
*table
,
3945 struct prefix_rd
*prd
)
3948 struct bgp_node
*rn
;
3949 struct bgp_adj_in
*ain
;
3952 table
= peer
->bgp
->rib
[afi
][safi
];
3954 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3955 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3956 if (ain
->peer
!= peer
)
3959 struct bgp_path_info
*pi
;
3960 uint32_t num_labels
= 0;
3961 mpls_label_t
*label_pnt
= NULL
;
3962 struct bgp_route_evpn evpn
;
3964 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
3966 if (pi
->peer
== peer
)
3969 if (pi
&& pi
->extra
)
3970 num_labels
= pi
->extra
->num_labels
;
3972 label_pnt
= &pi
->extra
->label
[0];
3974 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3977 memset(&evpn
, 0, sizeof(evpn
));
3979 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3980 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3981 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3982 num_labels
, 1, &evpn
);
3985 bgp_unlock_node(rn
);
3991 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3993 struct bgp_node
*rn
;
3994 struct bgp_table
*table
;
3996 if (peer
->status
!= Established
)
3999 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4000 && (safi
!= SAFI_EVPN
))
4001 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4003 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4004 rn
= bgp_route_next(rn
)) {
4005 table
= bgp_node_get_bgp_table_info(rn
);
4006 if (table
!= NULL
) {
4007 struct prefix_rd prd
;
4009 prd
.family
= AF_UNSPEC
;
4011 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
4013 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
4020 struct bgp_clear_node_queue
{
4021 struct bgp_node
*rn
;
4024 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4026 struct bgp_clear_node_queue
*cnq
= data
;
4027 struct bgp_node
*rn
= cnq
->rn
;
4028 struct peer
*peer
= wq
->spec
.data
;
4029 struct bgp_path_info
*pi
;
4031 afi_t afi
= bgp_node_table(rn
)->afi
;
4032 safi_t safi
= bgp_node_table(rn
)->safi
;
4037 /* It is possible that we have multiple paths for a prefix from a peer
4038 * if that peer is using AddPath.
4040 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4041 if (pi
->peer
!= peer
)
4044 /* graceful restart STALE flag set. */
4045 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4046 && peer
->nsf
[afi
][safi
]
4047 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4048 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4049 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4051 /* If this is an EVPN route, process for
4053 if (safi
== SAFI_EVPN
)
4054 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
4056 /* Handle withdraw for VRF route-leaking and L3VPN */
4057 if (SAFI_UNICAST
== safi
4058 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4059 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4060 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4063 if (SAFI_MPLS_VPN
== safi
&&
4064 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4065 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4068 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4074 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4076 struct bgp_clear_node_queue
*cnq
= data
;
4077 struct bgp_node
*rn
= cnq
->rn
;
4078 struct bgp_table
*table
= bgp_node_table(rn
);
4080 bgp_unlock_node(rn
);
4081 bgp_table_unlock(table
);
4082 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4085 static void bgp_clear_node_complete(struct work_queue
*wq
)
4087 struct peer
*peer
= wq
->spec
.data
;
4089 /* Tickle FSM to start moving again */
4090 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4092 peer_unlock(peer
); /* bgp_clear_route */
4095 static void bgp_clear_node_queue_init(struct peer
*peer
)
4097 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4099 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4100 #undef CLEAR_QUEUE_NAME_LEN
4102 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4103 peer
->clear_node_queue
->spec
.hold
= 10;
4104 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4105 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4106 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4107 peer
->clear_node_queue
->spec
.max_retries
= 0;
4109 /* we only 'lock' this peer reference when the queue is actually active
4111 peer
->clear_node_queue
->spec
.data
= peer
;
4114 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4115 struct bgp_table
*table
)
4117 struct bgp_node
*rn
;
4118 int force
= bm
->process_main_queue
? 0 : 1;
4121 table
= peer
->bgp
->rib
[afi
][safi
];
4123 /* If still no table => afi/safi isn't configured at all or smth. */
4127 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4128 struct bgp_path_info
*pi
, *next
;
4129 struct bgp_adj_in
*ain
;
4130 struct bgp_adj_in
*ain_next
;
4132 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4133 * queued for every clearing peer, regardless of whether it is
4134 * relevant to the peer at hand.
4136 * Overview: There are 3 different indices which need to be
4137 * scrubbed, potentially, when a peer is removed:
4139 * 1 peer's routes visible via the RIB (ie accepted routes)
4140 * 2 peer's routes visible by the (optional) peer's adj-in index
4141 * 3 other routes visible by the peer's adj-out index
4143 * 3 there is no hurry in scrubbing, once the struct peer is
4144 * removed from bgp->peer, we could just GC such deleted peer's
4145 * adj-outs at our leisure.
4147 * 1 and 2 must be 'scrubbed' in some way, at least made
4148 * invisible via RIB index before peer session is allowed to be
4149 * brought back up. So one needs to know when such a 'search' is
4154 * - there'd be a single global queue or a single RIB walker
4155 * - rather than tracking which route_nodes still need to be
4156 * examined on a peer basis, we'd track which peers still
4159 * Given that our per-peer prefix-counts now should be reliable,
4160 * this may actually be achievable. It doesn't seem to be a huge
4161 * problem at this time,
4163 * It is possible that we have multiple paths for a prefix from
4165 * if that peer is using AddPath.
4169 ain_next
= ain
->next
;
4171 if (ain
->peer
== peer
) {
4172 bgp_adj_in_remove(rn
, ain
);
4173 bgp_unlock_node(rn
);
4179 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4181 if (pi
->peer
!= peer
)
4185 bgp_path_info_reap(rn
, pi
);
4187 struct bgp_clear_node_queue
*cnq
;
4189 /* both unlocked in bgp_clear_node_queue_del */
4190 bgp_table_lock(bgp_node_table(rn
));
4193 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4194 sizeof(struct bgp_clear_node_queue
));
4196 work_queue_add(peer
->clear_node_queue
, cnq
);
4204 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4206 struct bgp_node
*rn
;
4207 struct bgp_table
*table
;
4209 if (peer
->clear_node_queue
== NULL
)
4210 bgp_clear_node_queue_init(peer
);
4212 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4213 * Idle until it receives a Clearing_Completed event. This protects
4214 * against peers which flap faster than we can we clear, which could
4217 * a) race with routes from the new session being installed before
4218 * clear_route_node visits the node (to delete the route of that
4220 * b) resource exhaustion, clear_route_node likely leads to an entry
4221 * on the process_main queue. Fast-flapping could cause that queue
4225 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4226 * the unlock will happen upon work-queue completion; other wise, the
4227 * unlock happens at the end of this function.
4229 if (!peer
->clear_node_queue
->thread
)
4232 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4233 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4235 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4236 rn
= bgp_route_next(rn
)) {
4237 table
= bgp_node_get_bgp_table_info(rn
);
4241 bgp_clear_route_table(peer
, afi
, safi
, table
);
4244 /* unlock if no nodes got added to the clear-node-queue. */
4245 if (!peer
->clear_node_queue
->thread
)
4249 void bgp_clear_route_all(struct peer
*peer
)
4254 FOREACH_AFI_SAFI (afi
, safi
)
4255 bgp_clear_route(peer
, afi
, safi
);
4258 rfapiProcessPeerDown(peer
);
4262 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4264 struct bgp_table
*table
;
4265 struct bgp_node
*rn
;
4266 struct bgp_adj_in
*ain
;
4267 struct bgp_adj_in
*ain_next
;
4269 table
= peer
->bgp
->rib
[afi
][safi
];
4271 /* It is possible that we have multiple paths for a prefix from a peer
4272 * if that peer is using AddPath.
4274 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4278 ain_next
= ain
->next
;
4280 if (ain
->peer
== peer
) {
4281 bgp_adj_in_remove(rn
, ain
);
4282 bgp_unlock_node(rn
);
4290 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4292 struct bgp_node
*rn
;
4293 struct bgp_path_info
*pi
;
4294 struct bgp_table
*table
;
4296 if (safi
== SAFI_MPLS_VPN
) {
4297 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4298 rn
= bgp_route_next(rn
)) {
4299 struct bgp_node
*rm
;
4301 /* look for neighbor in tables */
4302 table
= bgp_node_get_bgp_table_info(rn
);
4306 for (rm
= bgp_table_top(table
); rm
;
4307 rm
= bgp_route_next(rm
))
4308 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4310 if (pi
->peer
!= peer
)
4312 if (!CHECK_FLAG(pi
->flags
,
4316 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4321 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4322 rn
= bgp_route_next(rn
))
4323 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4325 if (pi
->peer
!= peer
)
4327 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4329 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4335 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4337 if (peer
->sort
== BGP_PEER_EBGP
4338 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4339 || FILTER_LIST_OUT_NAME(filter
)
4340 || DISTRIBUTE_OUT_NAME(filter
)))
4345 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4347 if (peer
->sort
== BGP_PEER_EBGP
4348 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4349 || FILTER_LIST_IN_NAME(filter
)
4350 || DISTRIBUTE_IN_NAME(filter
)))
4355 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4358 struct bgp_node
*rn
;
4359 struct bgp_path_info
*pi
;
4360 struct bgp_path_info
*next
;
4362 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4363 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4366 /* Unimport EVPN routes from VRFs */
4367 if (safi
== SAFI_EVPN
)
4368 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4372 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4373 && pi
->type
== ZEBRA_ROUTE_BGP
4374 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4375 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4376 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4378 if (bgp_fibupd_safi(safi
))
4379 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4381 bgp_path_info_reap(rn
, pi
);
4386 /* Delete all kernel routes. */
4387 void bgp_cleanup_routes(struct bgp
*bgp
)
4390 struct bgp_node
*rn
;
4391 struct bgp_table
*table
;
4393 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4394 if (afi
== AFI_L2VPN
)
4396 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4399 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4401 if (afi
!= AFI_L2VPN
) {
4403 safi
= SAFI_MPLS_VPN
;
4404 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4405 rn
= bgp_route_next(rn
)) {
4406 table
= bgp_node_get_bgp_table_info(rn
);
4407 if (table
!= NULL
) {
4408 bgp_cleanup_table(bgp
, table
, safi
);
4409 bgp_table_finish(&table
);
4410 bgp_node_set_bgp_table_info(rn
, NULL
);
4411 bgp_unlock_node(rn
);
4415 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4416 rn
= bgp_route_next(rn
)) {
4417 table
= bgp_node_get_bgp_table_info(rn
);
4418 if (table
!= NULL
) {
4419 bgp_cleanup_table(bgp
, table
, safi
);
4420 bgp_table_finish(&table
);
4421 bgp_node_set_bgp_table_info(rn
, NULL
);
4422 bgp_unlock_node(rn
);
4427 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4428 rn
= bgp_route_next(rn
)) {
4429 table
= bgp_node_get_bgp_table_info(rn
);
4430 if (table
!= NULL
) {
4431 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4432 bgp_table_finish(&table
);
4433 bgp_node_set_bgp_table_info(rn
, NULL
);
4434 bgp_unlock_node(rn
);
4439 void bgp_reset(void)
4442 bgp_zclient_reset();
4443 access_list_reset();
4444 prefix_list_reset();
4447 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4449 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4450 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4451 PEER_CAP_ADDPATH_AF_TX_RCV
));
4454 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4456 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4457 struct bgp_nlri
*packet
)
4466 int addpath_encoded
;
4467 uint32_t addpath_id
;
4470 lim
= pnt
+ packet
->length
;
4472 safi
= packet
->safi
;
4474 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4476 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4477 syntactic validity. If the field is syntactically incorrect,
4478 then the Error Subcode is set to Invalid Network Field. */
4479 for (; pnt
< lim
; pnt
+= psize
) {
4480 /* Clear prefix structure. */
4481 memset(&p
, 0, sizeof(struct prefix
));
4483 if (addpath_encoded
) {
4485 /* When packet overflow occurs return immediately. */
4486 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4487 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4489 addpath_id
= ntohl(*((uint32_t *)pnt
));
4490 pnt
+= BGP_ADDPATH_ID_LEN
;
4493 /* Fetch prefix length. */
4494 p
.prefixlen
= *pnt
++;
4495 /* afi/safi validity already verified by caller,
4496 * bgp_update_receive */
4497 p
.family
= afi2family(afi
);
4499 /* Prefix length check. */
4500 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4503 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4504 peer
->host
, p
.prefixlen
, packet
->afi
);
4505 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4508 /* Packet size overflow check. */
4509 psize
= PSIZE(p
.prefixlen
);
4511 /* When packet overflow occur return immediately. */
4512 if (pnt
+ psize
> lim
) {
4515 "%s [Error] Update packet error (prefix length %d overflows packet)",
4516 peer
->host
, p
.prefixlen
);
4517 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4520 /* Defensive coding, double-check the psize fits in a struct
4522 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4525 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4526 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4527 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4530 /* Fetch prefix from NLRI packet. */
4531 memcpy(p
.u
.val
, pnt
, psize
);
4533 /* Check address. */
4534 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4535 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4536 /* From RFC4271 Section 6.3:
4538 * If a prefix in the NLRI field is semantically
4540 * (e.g., an unexpected multicast IP address),
4542 * be logged locally, and the prefix SHOULD be
4547 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4548 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4553 /* Check address. */
4554 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4555 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4560 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4562 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4567 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4572 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4574 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4581 /* Normal process. */
4583 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4584 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4585 NULL
, NULL
, 0, 0, NULL
);
4587 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4588 safi
, ZEBRA_ROUTE_BGP
,
4589 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4592 /* Do not send BGP notification twice when maximum-prefix count
4594 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4595 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4597 /* Address family configuration mismatch. */
4599 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4602 /* Packet length consistency check. */
4606 "%s [Error] Update packet error (prefix length mismatch with total length)",
4608 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4611 return BGP_NLRI_PARSE_OK
;
4614 static struct bgp_static
*bgp_static_new(void)
4616 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4619 static void bgp_static_free(struct bgp_static
*bgp_static
)
4621 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4622 route_map_counter_decrement(bgp_static
->rmap
.map
);
4624 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4625 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4628 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4629 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4631 struct bgp_node
*rn
;
4632 struct bgp_path_info
*pi
;
4633 struct bgp_path_info
*new;
4634 struct bgp_path_info rmap_path
;
4636 struct attr
*attr_new
;
4637 route_map_result_t ret
;
4639 int vnc_implicit_withdraw
= 0;
4646 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4648 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4650 attr
.nexthop
= bgp_static
->igpnexthop
;
4651 attr
.med
= bgp_static
->igpmetric
;
4652 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4654 if (bgp_static
->atomic
)
4655 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4657 /* Store label index, if required. */
4658 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4659 attr
.label_index
= bgp_static
->label_index
;
4660 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4663 /* Apply route-map. */
4664 if (bgp_static
->rmap
.name
) {
4665 struct attr attr_tmp
= attr
;
4667 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4668 rmap_path
.peer
= bgp
->peer_self
;
4669 rmap_path
.attr
= &attr_tmp
;
4671 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4673 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4676 bgp
->peer_self
->rmap_type
= 0;
4678 if (ret
== RMAP_DENYMATCH
) {
4679 /* Free uninterned attribute. */
4680 bgp_attr_flush(&attr_tmp
);
4682 /* Unintern original. */
4683 aspath_unintern(&attr
.aspath
);
4684 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4688 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4689 bgp_attr_add_gshut_community(&attr_tmp
);
4691 attr_new
= bgp_attr_intern(&attr_tmp
);
4694 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4695 bgp_attr_add_gshut_community(&attr
);
4697 attr_new
= bgp_attr_intern(&attr
);
4700 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4701 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4702 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4706 if (attrhash_cmp(pi
->attr
, attr_new
)
4707 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4708 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4709 bgp_unlock_node(rn
);
4710 bgp_attr_unintern(&attr_new
);
4711 aspath_unintern(&attr
.aspath
);
4714 /* The attribute is changed. */
4715 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4717 /* Rewrite BGP route information. */
4718 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4719 bgp_path_info_restore(rn
, pi
);
4721 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4723 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4724 && (safi
== SAFI_UNICAST
)) {
4725 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4727 * Implicit withdraw case.
4728 * We have to do this before pi is
4731 ++vnc_implicit_withdraw
;
4732 vnc_import_bgp_del_route(bgp
, p
, pi
);
4733 vnc_import_bgp_exterior_del_route(
4738 bgp_attr_unintern(&pi
->attr
);
4739 pi
->attr
= attr_new
;
4740 pi
->uptime
= bgp_clock();
4742 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4743 && (safi
== SAFI_UNICAST
)) {
4744 if (vnc_implicit_withdraw
) {
4745 vnc_import_bgp_add_route(bgp
, p
, pi
);
4746 vnc_import_bgp_exterior_add_route(
4752 /* Nexthop reachability check. */
4753 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4754 && (safi
== SAFI_UNICAST
4755 || safi
== SAFI_LABELED_UNICAST
)) {
4757 struct bgp
*bgp_nexthop
= bgp
;
4759 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4760 bgp_nexthop
= pi
->extra
->bgp_orig
;
4762 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4764 bgp_path_info_set_flag(rn
, pi
,
4767 if (BGP_DEBUG(nht
, NHT
)) {
4768 char buf1
[INET6_ADDRSTRLEN
];
4769 inet_ntop(p
->family
,
4773 "%s(%s): Route not in table, not advertising",
4774 __FUNCTION__
, buf1
);
4776 bgp_path_info_unset_flag(
4777 rn
, pi
, BGP_PATH_VALID
);
4780 /* Delete the NHT structure if any, if we're
4782 * enabling/disabling import check. We
4783 * deregister the route
4784 * from NHT to avoid overloading NHT and the
4785 * process interaction
4787 bgp_unlink_nexthop(pi
);
4788 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4790 /* Process change. */
4791 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4792 bgp_process(bgp
, rn
, afi
, safi
);
4794 if (SAFI_UNICAST
== safi
4795 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4797 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4798 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4802 bgp_unlock_node(rn
);
4803 aspath_unintern(&attr
.aspath
);
4808 /* Make new BGP info. */
4809 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4811 /* Nexthop reachability check. */
4812 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4813 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4814 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4815 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4817 if (BGP_DEBUG(nht
, NHT
)) {
4818 char buf1
[INET6_ADDRSTRLEN
];
4819 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4822 "%s(%s): Route not in table, not advertising",
4823 __FUNCTION__
, buf1
);
4825 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4828 /* Delete the NHT structure if any, if we're toggling between
4829 * enabling/disabling import check. We deregister the route
4830 * from NHT to avoid overloading NHT and the process interaction
4832 bgp_unlink_nexthop(new);
4834 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4837 /* Aggregate address increment. */
4838 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4840 /* Register new BGP information. */
4841 bgp_path_info_add(rn
, new);
4843 /* route_node_get lock */
4844 bgp_unlock_node(rn
);
4846 /* Process change. */
4847 bgp_process(bgp
, rn
, afi
, safi
);
4849 if (SAFI_UNICAST
== safi
4850 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4851 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4852 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4855 /* Unintern original. */
4856 aspath_unintern(&attr
.aspath
);
4859 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4862 struct bgp_node
*rn
;
4863 struct bgp_path_info
*pi
;
4865 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4867 /* Check selected route and self inserted route. */
4868 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4869 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4870 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4873 /* Withdraw static BGP route from routing table. */
4875 if (SAFI_UNICAST
== safi
4876 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4877 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4878 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4880 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4881 bgp_unlink_nexthop(pi
);
4882 bgp_path_info_delete(rn
, pi
);
4883 bgp_process(bgp
, rn
, afi
, safi
);
4886 /* Unlock bgp_node_lookup. */
4887 bgp_unlock_node(rn
);
4891 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4893 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4894 afi_t afi
, safi_t safi
,
4895 struct prefix_rd
*prd
)
4897 struct bgp_node
*rn
;
4898 struct bgp_path_info
*pi
;
4900 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4902 /* Check selected route and self inserted route. */
4903 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4904 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4905 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4908 /* Withdraw static BGP route from routing table. */
4911 rfapiProcessWithdraw(
4912 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4913 1); /* Kill, since it is an administrative change */
4915 if (SAFI_MPLS_VPN
== safi
4916 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4917 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4919 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4920 bgp_path_info_delete(rn
, pi
);
4921 bgp_process(bgp
, rn
, afi
, safi
);
4924 /* Unlock bgp_node_lookup. */
4925 bgp_unlock_node(rn
);
4928 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4929 struct bgp_static
*bgp_static
, afi_t afi
,
4932 struct bgp_node
*rn
;
4933 struct bgp_path_info
*new;
4934 struct attr
*attr_new
;
4935 struct attr attr
= {0};
4936 struct bgp_path_info
*pi
;
4938 mpls_label_t label
= 0;
4940 uint32_t num_labels
= 0;
4945 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4947 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4950 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4952 attr
.nexthop
= bgp_static
->igpnexthop
;
4953 attr
.med
= bgp_static
->igpmetric
;
4954 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4956 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4957 || (safi
== SAFI_ENCAP
)) {
4958 if (afi
== AFI_IP
) {
4959 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4960 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4963 if (afi
== AFI_L2VPN
) {
4964 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4966 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4967 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4968 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4969 sizeof(struct in6_addr
));
4970 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4971 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4972 struct bgp_encap_type_vxlan bet
;
4973 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4974 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4975 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4977 if (bgp_static
->router_mac
) {
4978 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4981 /* Apply route-map. */
4982 if (bgp_static
->rmap
.name
) {
4983 struct attr attr_tmp
= attr
;
4984 struct bgp_path_info rmap_path
;
4985 route_map_result_t ret
;
4987 rmap_path
.peer
= bgp
->peer_self
;
4988 rmap_path
.attr
= &attr_tmp
;
4990 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4992 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4995 bgp
->peer_self
->rmap_type
= 0;
4997 if (ret
== RMAP_DENYMATCH
) {
4998 /* Free uninterned attribute. */
4999 bgp_attr_flush(&attr_tmp
);
5001 /* Unintern original. */
5002 aspath_unintern(&attr
.aspath
);
5003 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5008 attr_new
= bgp_attr_intern(&attr_tmp
);
5010 attr_new
= bgp_attr_intern(&attr
);
5013 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5014 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5015 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5019 memset(&add
, 0, sizeof(union gw_addr
));
5020 if (attrhash_cmp(pi
->attr
, attr_new
)
5021 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
5022 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5023 bgp_unlock_node(rn
);
5024 bgp_attr_unintern(&attr_new
);
5025 aspath_unintern(&attr
.aspath
);
5028 /* The attribute is changed. */
5029 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5031 /* Rewrite BGP route information. */
5032 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5033 bgp_path_info_restore(rn
, pi
);
5035 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5036 bgp_attr_unintern(&pi
->attr
);
5037 pi
->attr
= attr_new
;
5038 pi
->uptime
= bgp_clock();
5041 label
= decode_label(&pi
->extra
->label
[0]);
5044 /* Process change. */
5045 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5046 bgp_process(bgp
, rn
, afi
, safi
);
5048 if (SAFI_MPLS_VPN
== safi
5049 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5050 vpn_leak_to_vrf_update(bgp
, pi
);
5053 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5054 pi
->attr
, afi
, safi
, pi
->type
,
5055 pi
->sub_type
, &label
);
5057 bgp_unlock_node(rn
);
5058 aspath_unintern(&attr
.aspath
);
5064 /* Make new BGP info. */
5065 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5067 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5068 new->extra
= bgp_path_info_extra_new();
5070 new->extra
->label
[0] = bgp_static
->label
;
5071 new->extra
->num_labels
= num_labels
;
5074 label
= decode_label(&bgp_static
->label
);
5077 /* Aggregate address increment. */
5078 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5080 /* Register new BGP information. */
5081 bgp_path_info_add(rn
, new);
5082 /* route_node_get lock */
5083 bgp_unlock_node(rn
);
5085 /* Process change. */
5086 bgp_process(bgp
, rn
, afi
, safi
);
5088 if (SAFI_MPLS_VPN
== safi
5089 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5090 vpn_leak_to_vrf_update(bgp
, new);
5093 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5094 safi
, new->type
, new->sub_type
, &label
);
5097 /* Unintern original. */
5098 aspath_unintern(&attr
.aspath
);
5101 /* Configure static BGP network. When user don't run zebra, static
5102 route should be installed as valid. */
5103 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5104 const char *ip_str
, afi_t afi
, safi_t safi
,
5105 const char *rmap
, int backdoor
, uint32_t label_index
)
5107 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5110 struct bgp_static
*bgp_static
;
5111 struct bgp_node
*rn
;
5112 uint8_t need_update
= 0;
5114 /* Convert IP prefix string to struct prefix. */
5115 ret
= str2prefix(ip_str
, &p
);
5117 vty_out(vty
, "%% Malformed prefix\n");
5118 return CMD_WARNING_CONFIG_FAILED
;
5120 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5121 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5122 return CMD_WARNING_CONFIG_FAILED
;
5129 /* Set BGP static route configuration. */
5130 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5133 vty_out(vty
, "%% Can't find static route specified\n");
5134 return CMD_WARNING_CONFIG_FAILED
;
5137 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5139 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5140 && (label_index
!= bgp_static
->label_index
)) {
5142 "%% label-index doesn't match static route\n");
5143 return CMD_WARNING_CONFIG_FAILED
;
5146 if ((rmap
&& bgp_static
->rmap
.name
)
5147 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5149 "%% route-map name doesn't match static route\n");
5150 return CMD_WARNING_CONFIG_FAILED
;
5153 /* Update BGP RIB. */
5154 if (!bgp_static
->backdoor
)
5155 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5157 /* Clear configuration. */
5158 bgp_static_free(bgp_static
);
5159 bgp_node_set_bgp_static_info(rn
, NULL
);
5160 bgp_unlock_node(rn
);
5161 bgp_unlock_node(rn
);
5164 /* Set BGP static route configuration. */
5165 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5167 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5169 /* Configuration change. */
5170 /* Label index cannot be changed. */
5171 if (bgp_static
->label_index
!= label_index
) {
5172 vty_out(vty
, "%% cannot change label-index\n");
5173 return CMD_WARNING_CONFIG_FAILED
;
5176 /* Check previous routes are installed into BGP. */
5177 if (bgp_static
->valid
5178 && bgp_static
->backdoor
!= backdoor
)
5181 bgp_static
->backdoor
= backdoor
;
5184 XFREE(MTYPE_ROUTE_MAP_NAME
,
5185 bgp_static
->rmap
.name
);
5186 route_map_counter_decrement(
5187 bgp_static
->rmap
.map
);
5188 bgp_static
->rmap
.name
=
5189 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5190 bgp_static
->rmap
.map
=
5191 route_map_lookup_by_name(rmap
);
5192 route_map_counter_increment(
5193 bgp_static
->rmap
.map
);
5195 XFREE(MTYPE_ROUTE_MAP_NAME
,
5196 bgp_static
->rmap
.name
);
5197 route_map_counter_decrement(
5198 bgp_static
->rmap
.map
);
5199 bgp_static
->rmap
.name
= NULL
;
5200 bgp_static
->rmap
.map
= NULL
;
5201 bgp_static
->valid
= 0;
5203 bgp_unlock_node(rn
);
5205 /* New configuration. */
5206 bgp_static
= bgp_static_new();
5207 bgp_static
->backdoor
= backdoor
;
5208 bgp_static
->valid
= 0;
5209 bgp_static
->igpmetric
= 0;
5210 bgp_static
->igpnexthop
.s_addr
= 0;
5211 bgp_static
->label_index
= label_index
;
5214 XFREE(MTYPE_ROUTE_MAP_NAME
,
5215 bgp_static
->rmap
.name
);
5216 route_map_counter_decrement(
5217 bgp_static
->rmap
.map
);
5218 bgp_static
->rmap
.name
=
5219 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5220 bgp_static
->rmap
.map
=
5221 route_map_lookup_by_name(rmap
);
5222 route_map_counter_increment(
5223 bgp_static
->rmap
.map
);
5225 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5228 bgp_static
->valid
= 1;
5230 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5232 if (!bgp_static
->backdoor
)
5233 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5239 void bgp_static_add(struct bgp
*bgp
)
5243 struct bgp_node
*rn
;
5244 struct bgp_node
*rm
;
5245 struct bgp_table
*table
;
5246 struct bgp_static
*bgp_static
;
5248 FOREACH_AFI_SAFI (afi
, safi
)
5249 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5250 rn
= bgp_route_next(rn
)) {
5251 if (!bgp_node_has_bgp_path_info_data(rn
))
5254 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5255 || (safi
== SAFI_EVPN
)) {
5256 table
= bgp_node_get_bgp_table_info(rn
);
5258 for (rm
= bgp_table_top(table
); rm
;
5259 rm
= bgp_route_next(rm
)) {
5261 bgp_node_get_bgp_static_info(
5263 bgp_static_update_safi(bgp
, &rm
->p
,
5270 bgp_node_get_bgp_static_info(rn
), afi
,
5276 /* Called from bgp_delete(). Delete all static routes from the BGP
5278 void bgp_static_delete(struct bgp
*bgp
)
5282 struct bgp_node
*rn
;
5283 struct bgp_node
*rm
;
5284 struct bgp_table
*table
;
5285 struct bgp_static
*bgp_static
;
5287 FOREACH_AFI_SAFI (afi
, safi
)
5288 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5289 rn
= bgp_route_next(rn
)) {
5290 if (!bgp_node_has_bgp_path_info_data(rn
))
5293 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5294 || (safi
== SAFI_EVPN
)) {
5295 table
= bgp_node_get_bgp_table_info(rn
);
5297 for (rm
= bgp_table_top(table
); rm
;
5298 rm
= bgp_route_next(rm
)) {
5300 bgp_node_get_bgp_static_info(
5305 bgp_static_withdraw_safi(
5306 bgp
, &rm
->p
, AFI_IP
, safi
,
5307 (struct prefix_rd
*)&rn
->p
);
5308 bgp_static_free(bgp_static
);
5309 bgp_node_set_bgp_static_info(rn
, NULL
);
5310 bgp_unlock_node(rn
);
5313 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5314 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5315 bgp_static_free(bgp_static
);
5316 bgp_node_set_bgp_static_info(rn
, NULL
);
5317 bgp_unlock_node(rn
);
5322 void bgp_static_redo_import_check(struct bgp
*bgp
)
5326 struct bgp_node
*rn
;
5327 struct bgp_node
*rm
;
5328 struct bgp_table
*table
;
5329 struct bgp_static
*bgp_static
;
5331 /* Use this flag to force reprocessing of the route */
5332 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5333 FOREACH_AFI_SAFI (afi
, safi
) {
5334 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5335 rn
= bgp_route_next(rn
)) {
5336 if (!bgp_node_has_bgp_path_info_data(rn
))
5339 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5340 || (safi
== SAFI_EVPN
)) {
5341 table
= bgp_node_get_bgp_table_info(rn
);
5343 for (rm
= bgp_table_top(table
); rm
;
5344 rm
= bgp_route_next(rm
)) {
5346 bgp_node_get_bgp_static_info(
5348 bgp_static_update_safi(bgp
, &rm
->p
,
5353 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5354 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5359 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5362 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5365 struct bgp_table
*table
;
5366 struct bgp_node
*rn
;
5367 struct bgp_path_info
*pi
;
5369 /* Do not install the aggregate route if BGP is in the
5370 * process of termination.
5372 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5373 (bgp
->peer_self
== NULL
))
5376 table
= bgp
->rib
[afi
][safi
];
5377 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5378 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5379 if (pi
->peer
== bgp
->peer_self
5380 && ((pi
->type
== ZEBRA_ROUTE_BGP
5381 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5382 || (pi
->type
!= ZEBRA_ROUTE_BGP
5384 == BGP_ROUTE_REDISTRIBUTE
))) {
5385 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5387 bgp_unlink_nexthop(pi
);
5388 bgp_path_info_delete(rn
, pi
);
5389 bgp_process(bgp
, rn
, afi
, safi
);
5396 * Purge all networks and redistributed routes from routing table.
5397 * Invoked upon the instance going down.
5399 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5404 FOREACH_AFI_SAFI (afi
, safi
)
5405 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5410 * Currently this is used to set static routes for VPN and ENCAP.
5411 * I think it can probably be factored with bgp_static_set.
5413 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5414 const char *ip_str
, const char *rd_str
,
5415 const char *label_str
, const char *rmap_str
,
5416 int evpn_type
, const char *esi
, const char *gwip
,
5417 const char *ethtag
, const char *routermac
)
5419 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5422 struct prefix_rd prd
;
5423 struct bgp_node
*prn
;
5424 struct bgp_node
*rn
;
5425 struct bgp_table
*table
;
5426 struct bgp_static
*bgp_static
;
5427 mpls_label_t label
= MPLS_INVALID_LABEL
;
5428 struct prefix gw_ip
;
5430 /* validate ip prefix */
5431 ret
= str2prefix(ip_str
, &p
);
5433 vty_out(vty
, "%% Malformed prefix\n");
5434 return CMD_WARNING_CONFIG_FAILED
;
5437 if ((afi
== AFI_L2VPN
)
5438 && (bgp_build_evpn_prefix(evpn_type
,
5439 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5440 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5441 return CMD_WARNING_CONFIG_FAILED
;
5444 ret
= str2prefix_rd(rd_str
, &prd
);
5446 vty_out(vty
, "%% Malformed rd\n");
5447 return CMD_WARNING_CONFIG_FAILED
;
5451 unsigned long label_val
;
5452 label_val
= strtoul(label_str
, NULL
, 10);
5453 encode_label(label_val
, &label
);
5456 if (safi
== SAFI_EVPN
) {
5457 if (esi
&& str2esi(esi
, NULL
) == 0) {
5458 vty_out(vty
, "%% Malformed ESI\n");
5459 return CMD_WARNING_CONFIG_FAILED
;
5461 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5462 vty_out(vty
, "%% Malformed Router MAC\n");
5463 return CMD_WARNING_CONFIG_FAILED
;
5466 memset(&gw_ip
, 0, sizeof(struct prefix
));
5467 ret
= str2prefix(gwip
, &gw_ip
);
5469 vty_out(vty
, "%% Malformed GatewayIp\n");
5470 return CMD_WARNING_CONFIG_FAILED
;
5472 if ((gw_ip
.family
== AF_INET
5473 && is_evpn_prefix_ipaddr_v6(
5474 (struct prefix_evpn
*)&p
))
5475 || (gw_ip
.family
== AF_INET6
5476 && is_evpn_prefix_ipaddr_v4(
5477 (struct prefix_evpn
*)&p
))) {
5479 "%% GatewayIp family differs with IP prefix\n");
5480 return CMD_WARNING_CONFIG_FAILED
;
5484 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5485 if (!bgp_node_has_bgp_path_info_data(prn
))
5486 bgp_node_set_bgp_table_info(prn
,
5487 bgp_table_init(bgp
, afi
, safi
));
5488 table
= bgp_node_get_bgp_table_info(prn
);
5490 rn
= bgp_node_get(table
, &p
);
5492 if (bgp_node_has_bgp_path_info_data(rn
)) {
5493 vty_out(vty
, "%% Same network configuration exists\n");
5494 bgp_unlock_node(rn
);
5496 /* New configuration. */
5497 bgp_static
= bgp_static_new();
5498 bgp_static
->backdoor
= 0;
5499 bgp_static
->valid
= 0;
5500 bgp_static
->igpmetric
= 0;
5501 bgp_static
->igpnexthop
.s_addr
= 0;
5502 bgp_static
->label
= label
;
5503 bgp_static
->prd
= prd
;
5506 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5507 route_map_counter_decrement(bgp_static
->rmap
.map
);
5508 bgp_static
->rmap
.name
=
5509 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5510 bgp_static
->rmap
.map
=
5511 route_map_lookup_by_name(rmap_str
);
5512 route_map_counter_increment(bgp_static
->rmap
.map
);
5515 if (safi
== SAFI_EVPN
) {
5517 bgp_static
->eth_s_id
=
5519 sizeof(struct eth_segment_id
));
5520 str2esi(esi
, bgp_static
->eth_s_id
);
5523 bgp_static
->router_mac
=
5524 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5525 (void)prefix_str2mac(routermac
,
5526 bgp_static
->router_mac
);
5529 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5531 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5533 bgp_static
->valid
= 1;
5534 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5540 /* Configure static BGP network. */
5541 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5542 const char *ip_str
, const char *rd_str
,
5543 const char *label_str
, int evpn_type
, const char *esi
,
5544 const char *gwip
, const char *ethtag
)
5546 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5549 struct prefix_rd prd
;
5550 struct bgp_node
*prn
;
5551 struct bgp_node
*rn
;
5552 struct bgp_table
*table
;
5553 struct bgp_static
*bgp_static
;
5554 mpls_label_t label
= MPLS_INVALID_LABEL
;
5556 /* Convert IP prefix string to struct prefix. */
5557 ret
= str2prefix(ip_str
, &p
);
5559 vty_out(vty
, "%% Malformed prefix\n");
5560 return CMD_WARNING_CONFIG_FAILED
;
5563 if ((afi
== AFI_L2VPN
)
5564 && (bgp_build_evpn_prefix(evpn_type
,
5565 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5566 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5567 return CMD_WARNING_CONFIG_FAILED
;
5569 ret
= str2prefix_rd(rd_str
, &prd
);
5571 vty_out(vty
, "%% Malformed rd\n");
5572 return CMD_WARNING_CONFIG_FAILED
;
5576 unsigned long label_val
;
5577 label_val
= strtoul(label_str
, NULL
, 10);
5578 encode_label(label_val
, &label
);
5581 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5582 if (!bgp_node_has_bgp_path_info_data(prn
))
5583 bgp_node_set_bgp_table_info(prn
,
5584 bgp_table_init(bgp
, afi
, safi
));
5586 bgp_unlock_node(prn
);
5587 table
= bgp_node_get_bgp_table_info(prn
);
5589 rn
= bgp_node_lookup(table
, &p
);
5592 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5594 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5595 bgp_static_free(bgp_static
);
5596 bgp_node_set_bgp_static_info(rn
, NULL
);
5597 bgp_unlock_node(rn
);
5598 bgp_unlock_node(rn
);
5600 vty_out(vty
, "%% Can't find the route\n");
5605 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5606 const char *rmap_name
)
5608 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5609 struct bgp_rmap
*rmap
;
5611 rmap
= &bgp
->table_map
[afi
][safi
];
5613 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5614 route_map_counter_decrement(rmap
->map
);
5615 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5616 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5617 route_map_counter_increment(rmap
->map
);
5619 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5620 route_map_counter_decrement(rmap
->map
);
5625 if (bgp_fibupd_safi(safi
))
5626 bgp_zebra_announce_table(bgp
, afi
, safi
);
5631 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5632 const char *rmap_name
)
5634 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5635 struct bgp_rmap
*rmap
;
5637 rmap
= &bgp
->table_map
[afi
][safi
];
5638 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5639 route_map_counter_decrement(rmap
->map
);
5643 if (bgp_fibupd_safi(safi
))
5644 bgp_zebra_announce_table(bgp
, afi
, safi
);
5649 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5652 if (bgp
->table_map
[afi
][safi
].name
) {
5653 vty_out(vty
, " table-map %s\n",
5654 bgp
->table_map
[afi
][safi
].name
);
5658 DEFUN (bgp_table_map
,
5661 "BGP table to RIB route download filter\n"
5662 "Name of the route map\n")
5665 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5666 argv
[idx_word
]->arg
);
5668 DEFUN (no_bgp_table_map
,
5669 no_bgp_table_map_cmd
,
5670 "no table-map WORD",
5672 "BGP table to RIB route download filter\n"
5673 "Name of the route map\n")
5676 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5677 argv
[idx_word
]->arg
);
5683 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5684 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5685 backdoor$backdoor}]",
5687 "Specify a network to announce via BGP\n"
5692 "Route-map to modify the attributes\n"
5693 "Name of the route map\n"
5694 "Label index to associate with the prefix\n"
5695 "Label index value\n"
5696 "Specify a BGP backdoor route\n")
5698 char addr_prefix_str
[BUFSIZ
];
5703 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5706 vty_out(vty
, "%% Inconsistent address and mask\n");
5707 return CMD_WARNING_CONFIG_FAILED
;
5711 return bgp_static_set(
5712 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5713 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5714 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5717 DEFPY(ipv6_bgp_network
,
5718 ipv6_bgp_network_cmd
,
5719 "[no] network X:X::X:X/M$prefix \
5720 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5722 "Specify a network to announce via BGP\n"
5724 "Route-map to modify the attributes\n"
5725 "Name of the route map\n"
5726 "Label index to associate with the prefix\n"
5727 "Label index value\n")
5729 return bgp_static_set(
5730 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5731 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5734 static struct bgp_aggregate
*bgp_aggregate_new(void)
5736 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5739 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5741 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
5742 route_map_counter_decrement(aggregate
->rmap
.map
);
5743 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5746 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5747 struct aspath
*aspath
,
5748 struct community
*comm
,
5749 struct ecommunity
*ecomm
,
5750 struct lcommunity
*lcomm
)
5752 static struct aspath
*ae
= NULL
;
5755 ae
= aspath_empty();
5760 if (origin
!= pi
->attr
->origin
)
5763 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5766 if (!community_cmp(pi
->attr
->community
, comm
))
5769 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5772 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5775 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5781 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5782 struct prefix
*p
, uint8_t origin
,
5783 struct aspath
*aspath
,
5784 struct community
*community
,
5785 struct ecommunity
*ecommunity
,
5786 struct lcommunity
*lcommunity
,
5787 uint8_t atomic_aggregate
,
5788 struct bgp_aggregate
*aggregate
)
5790 struct bgp_node
*rn
;
5791 struct bgp_table
*table
;
5792 struct bgp_path_info
*pi
, *orig
, *new;
5795 table
= bgp
->rib
[afi
][safi
];
5797 rn
= bgp_node_get(table
, p
);
5799 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5800 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5801 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5804 if (aggregate
->count
> 0) {
5806 * If the aggregate information has not changed
5807 * no need to re-install it again.
5809 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5810 ecommunity
, lcommunity
)) {
5811 bgp_unlock_node(rn
);
5814 aspath_free(aspath
);
5816 community_free(&community
);
5818 ecommunity_free(&ecommunity
);
5820 lcommunity_free(&lcommunity
);
5826 * Mark the old as unusable
5829 bgp_path_info_delete(rn
, pi
);
5831 attr
= bgp_attr_aggregate_intern(
5832 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
5833 aggregate
, atomic_aggregate
, p
);
5836 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
5840 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5841 bgp
->peer_self
, attr
, rn
);
5843 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5845 bgp_path_info_add(rn
, new);
5846 bgp_process(bgp
, rn
, afi
, safi
);
5848 for (pi
= orig
; pi
; pi
= pi
->next
)
5849 if (pi
->peer
== bgp
->peer_self
5850 && pi
->type
== ZEBRA_ROUTE_BGP
5851 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5854 /* Withdraw static BGP route from routing table. */
5856 bgp_path_info_delete(rn
, pi
);
5857 bgp_process(bgp
, rn
, afi
, safi
);
5861 bgp_unlock_node(rn
);
5864 /* Update an aggregate as routes are added/removed from the BGP table */
5865 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5866 afi_t afi
, safi_t safi
,
5867 struct bgp_aggregate
*aggregate
)
5869 struct bgp_table
*table
;
5870 struct bgp_node
*top
;
5871 struct bgp_node
*rn
;
5873 struct aspath
*aspath
= NULL
;
5874 struct community
*community
= NULL
;
5875 struct ecommunity
*ecommunity
= NULL
;
5876 struct lcommunity
*lcommunity
= NULL
;
5877 struct bgp_path_info
*pi
;
5878 unsigned long match
= 0;
5879 uint8_t atomic_aggregate
= 0;
5881 /* If the bgp instance is being deleted or self peer is deleted
5882 * then do not create aggregate route
5884 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5885 (bgp
->peer_self
== NULL
))
5888 /* ORIGIN attribute: If at least one route among routes that are
5889 aggregated has ORIGIN with the value INCOMPLETE, then the
5890 aggregated route must have the ORIGIN attribute with the value
5891 INCOMPLETE. Otherwise, if at least one route among routes that
5892 are aggregated has ORIGIN with the value EGP, then the aggregated
5893 route must have the origin attribute with the value EGP. In all
5894 other case the value of the ORIGIN attribute of the aggregated
5895 route is INTERNAL. */
5896 origin
= BGP_ORIGIN_IGP
;
5898 table
= bgp
->rib
[afi
][safi
];
5900 top
= bgp_node_get(table
, p
);
5901 for (rn
= bgp_node_get(table
, p
); rn
;
5902 rn
= bgp_route_next_until(rn
, top
)) {
5903 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5908 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5909 if (BGP_PATH_HOLDDOWN(pi
))
5913 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5914 atomic_aggregate
= 1;
5916 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5920 * summary-only aggregate route suppress
5921 * aggregated route announcements.
5923 if (aggregate
->summary_only
) {
5924 (bgp_path_info_extra_get(pi
))->suppress
++;
5925 bgp_path_info_set_flag(rn
, pi
,
5926 BGP_PATH_ATTR_CHANGED
);
5933 * If at least one route among routes that are
5934 * aggregated has ORIGIN with the value INCOMPLETE,
5935 * then the aggregated route MUST have the ORIGIN
5936 * attribute with the value INCOMPLETE. Otherwise, if
5937 * at least one route among routes that are aggregated
5938 * has ORIGIN with the value EGP, then the aggregated
5939 * route MUST have the ORIGIN attribute with the value
5942 switch (pi
->attr
->origin
) {
5943 case BGP_ORIGIN_INCOMPLETE
:
5944 aggregate
->incomplete_origin_count
++;
5946 case BGP_ORIGIN_EGP
:
5947 aggregate
->egp_origin_count
++;
5955 if (!aggregate
->as_set
)
5959 * as-set aggregate route generate origin, as path,
5960 * and community aggregation.
5962 /* Compute aggregate route's as-path.
5964 bgp_compute_aggregate_aspath_hash(aggregate
,
5967 /* Compute aggregate route's community.
5969 if (pi
->attr
->community
)
5970 bgp_compute_aggregate_community_hash(
5972 pi
->attr
->community
);
5974 /* Compute aggregate route's extended community.
5976 if (pi
->attr
->ecommunity
)
5977 bgp_compute_aggregate_ecommunity_hash(
5979 pi
->attr
->ecommunity
);
5981 /* Compute aggregate route's large community.
5983 if (pi
->attr
->lcommunity
)
5984 bgp_compute_aggregate_lcommunity_hash(
5986 pi
->attr
->lcommunity
);
5989 bgp_process(bgp
, rn
, afi
, safi
);
5991 if (aggregate
->as_set
) {
5992 bgp_compute_aggregate_aspath_val(aggregate
);
5993 bgp_compute_aggregate_community_val(aggregate
);
5994 bgp_compute_aggregate_ecommunity_val(aggregate
);
5995 bgp_compute_aggregate_lcommunity_val(aggregate
);
5999 bgp_unlock_node(top
);
6002 if (aggregate
->incomplete_origin_count
> 0)
6003 origin
= BGP_ORIGIN_INCOMPLETE
;
6004 else if (aggregate
->egp_origin_count
> 0)
6005 origin
= BGP_ORIGIN_EGP
;
6007 if (aggregate
->as_set
) {
6008 if (aggregate
->aspath
)
6009 /* Retrieve aggregate route's as-path.
6011 aspath
= aspath_dup(aggregate
->aspath
);
6013 if (aggregate
->community
)
6014 /* Retrieve aggregate route's community.
6016 community
= community_dup(aggregate
->community
);
6018 if (aggregate
->ecommunity
)
6019 /* Retrieve aggregate route's ecommunity.
6021 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6023 if (aggregate
->lcommunity
)
6024 /* Retrieve aggregate route's lcommunity.
6026 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6029 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6030 ecommunity
, lcommunity
, atomic_aggregate
,
6034 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6035 safi_t safi
, struct bgp_aggregate
*aggregate
)
6037 struct bgp_table
*table
;
6038 struct bgp_node
*top
;
6039 struct bgp_node
*rn
;
6040 struct bgp_path_info
*pi
;
6041 unsigned long match
;
6043 table
= bgp
->rib
[afi
][safi
];
6045 /* If routes exists below this node, generate aggregate routes. */
6046 top
= bgp_node_get(table
, p
);
6047 for (rn
= bgp_node_get(table
, p
); rn
;
6048 rn
= bgp_route_next_until(rn
, top
)) {
6049 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6053 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6054 if (BGP_PATH_HOLDDOWN(pi
))
6057 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6060 if (aggregate
->summary_only
&& pi
->extra
) {
6061 pi
->extra
->suppress
--;
6063 if (pi
->extra
->suppress
== 0) {
6064 bgp_path_info_set_flag(
6065 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6071 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6072 aggregate
->incomplete_origin_count
--;
6073 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6074 aggregate
->egp_origin_count
--;
6076 if (aggregate
->as_set
) {
6077 /* Remove as-path from aggregate.
6079 bgp_remove_aspath_from_aggregate_hash(
6083 if (pi
->attr
->community
)
6084 /* Remove community from aggregate.
6086 bgp_remove_comm_from_aggregate_hash(
6088 pi
->attr
->community
);
6090 if (pi
->attr
->ecommunity
)
6091 /* Remove ecommunity from aggregate.
6093 bgp_remove_ecomm_from_aggregate_hash(
6095 pi
->attr
->ecommunity
);
6097 if (pi
->attr
->lcommunity
)
6098 /* Remove lcommunity from aggregate.
6100 bgp_remove_lcomm_from_aggregate_hash(
6102 pi
->attr
->lcommunity
);
6107 /* If this node was suppressed, process the change. */
6109 bgp_process(bgp
, rn
, afi
, safi
);
6111 if (aggregate
->as_set
) {
6112 aspath_free(aggregate
->aspath
);
6113 aggregate
->aspath
= NULL
;
6114 if (aggregate
->community
)
6115 community_free(&aggregate
->community
);
6116 if (aggregate
->ecommunity
)
6117 ecommunity_free(&aggregate
->ecommunity
);
6118 if (aggregate
->lcommunity
)
6119 lcommunity_free(&aggregate
->lcommunity
);
6122 bgp_unlock_node(top
);
6125 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6126 struct bgp_path_info
*pinew
, afi_t afi
,
6128 struct bgp_aggregate
*aggregate
)
6131 struct aspath
*aspath
= NULL
;
6132 uint8_t atomic_aggregate
= 0;
6133 struct community
*community
= NULL
;
6134 struct ecommunity
*ecommunity
= NULL
;
6135 struct lcommunity
*lcommunity
= NULL
;
6137 /* ORIGIN attribute: If at least one route among routes that are
6138 * aggregated has ORIGIN with the value INCOMPLETE, then the
6139 * aggregated route must have the ORIGIN attribute with the value
6140 * INCOMPLETE. Otherwise, if at least one route among routes that
6141 * are aggregated has ORIGIN with the value EGP, then the aggregated
6142 * route must have the origin attribute with the value EGP. In all
6143 * other case the value of the ORIGIN attribute of the aggregated
6144 * route is INTERNAL.
6146 origin
= BGP_ORIGIN_IGP
;
6150 if (aggregate
->summary_only
)
6151 (bgp_path_info_extra_get(pinew
))->suppress
++;
6153 switch (pinew
->attr
->origin
) {
6154 case BGP_ORIGIN_INCOMPLETE
:
6155 aggregate
->incomplete_origin_count
++;
6157 case BGP_ORIGIN_EGP
:
6158 aggregate
->egp_origin_count
++;
6166 if (aggregate
->incomplete_origin_count
> 0)
6167 origin
= BGP_ORIGIN_INCOMPLETE
;
6168 else if (aggregate
->egp_origin_count
> 0)
6169 origin
= BGP_ORIGIN_EGP
;
6171 if (aggregate
->as_set
) {
6172 /* Compute aggregate route's as-path.
6174 bgp_compute_aggregate_aspath(aggregate
,
6175 pinew
->attr
->aspath
);
6177 /* Compute aggregate route's community.
6179 if (pinew
->attr
->community
)
6180 bgp_compute_aggregate_community(
6182 pinew
->attr
->community
);
6184 /* Compute aggregate route's extended community.
6186 if (pinew
->attr
->ecommunity
)
6187 bgp_compute_aggregate_ecommunity(
6189 pinew
->attr
->ecommunity
);
6191 /* Compute aggregate route's large community.
6193 if (pinew
->attr
->lcommunity
)
6194 bgp_compute_aggregate_lcommunity(
6196 pinew
->attr
->lcommunity
);
6198 /* Retrieve aggregate route's as-path.
6200 if (aggregate
->aspath
)
6201 aspath
= aspath_dup(aggregate
->aspath
);
6203 /* Retrieve aggregate route's community.
6205 if (aggregate
->community
)
6206 community
= community_dup(aggregate
->community
);
6208 /* Retrieve aggregate route's ecommunity.
6210 if (aggregate
->ecommunity
)
6211 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6213 /* Retrieve aggregate route's lcommunity.
6215 if (aggregate
->lcommunity
)
6216 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6219 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6220 aspath
, community
, ecommunity
,
6221 lcommunity
, atomic_aggregate
, aggregate
);
6224 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6226 struct bgp_path_info
*pi
,
6227 struct bgp_aggregate
*aggregate
,
6228 struct prefix
*aggr_p
)
6231 struct aspath
*aspath
= NULL
;
6232 uint8_t atomic_aggregate
= 0;
6233 struct community
*community
= NULL
;
6234 struct ecommunity
*ecommunity
= NULL
;
6235 struct lcommunity
*lcommunity
= NULL
;
6236 unsigned long match
= 0;
6238 if (BGP_PATH_HOLDDOWN(pi
))
6241 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6244 if (aggregate
->summary_only
6246 && pi
->extra
->suppress
> 0) {
6247 pi
->extra
->suppress
--;
6249 if (pi
->extra
->suppress
== 0) {
6250 bgp_path_info_set_flag(pi
->net
, pi
,
6251 BGP_PATH_ATTR_CHANGED
);
6256 if (aggregate
->count
> 0)
6259 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6260 aggregate
->incomplete_origin_count
--;
6261 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6262 aggregate
->egp_origin_count
--;
6264 if (aggregate
->as_set
) {
6265 /* Remove as-path from aggregate.
6267 bgp_remove_aspath_from_aggregate(aggregate
,
6270 if (pi
->attr
->community
)
6271 /* Remove community from aggregate.
6273 bgp_remove_community_from_aggregate(
6275 pi
->attr
->community
);
6277 if (pi
->attr
->ecommunity
)
6278 /* Remove ecommunity from aggregate.
6280 bgp_remove_ecommunity_from_aggregate(
6282 pi
->attr
->ecommunity
);
6284 if (pi
->attr
->lcommunity
)
6285 /* Remove lcommunity from aggregate.
6287 bgp_remove_lcommunity_from_aggregate(
6289 pi
->attr
->lcommunity
);
6292 /* If this node was suppressed, process the change. */
6294 bgp_process(bgp
, pi
->net
, afi
, safi
);
6296 origin
= BGP_ORIGIN_IGP
;
6297 if (aggregate
->incomplete_origin_count
> 0)
6298 origin
= BGP_ORIGIN_INCOMPLETE
;
6299 else if (aggregate
->egp_origin_count
> 0)
6300 origin
= BGP_ORIGIN_EGP
;
6302 if (aggregate
->as_set
) {
6303 /* Retrieve aggregate route's as-path.
6305 if (aggregate
->aspath
)
6306 aspath
= aspath_dup(aggregate
->aspath
);
6308 /* Retrieve aggregate route's community.
6310 if (aggregate
->community
)
6311 community
= community_dup(aggregate
->community
);
6313 /* Retrieve aggregate route's ecommunity.
6315 if (aggregate
->ecommunity
)
6316 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6318 /* Retrieve aggregate route's lcommunity.
6320 if (aggregate
->lcommunity
)
6321 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6324 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6325 aspath
, community
, ecommunity
,
6326 lcommunity
, atomic_aggregate
, aggregate
);
6329 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6330 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6332 struct bgp_node
*child
;
6333 struct bgp_node
*rn
;
6334 struct bgp_aggregate
*aggregate
;
6335 struct bgp_table
*table
;
6337 table
= bgp
->aggregate
[afi
][safi
];
6339 /* No aggregates configured. */
6340 if (bgp_table_top_nolock(table
) == NULL
)
6343 if (p
->prefixlen
== 0)
6346 if (BGP_PATH_HOLDDOWN(pi
))
6349 child
= bgp_node_get(table
, p
);
6351 /* Aggregate address configuration check. */
6352 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6353 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6354 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6355 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6359 bgp_unlock_node(child
);
6362 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6363 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6365 struct bgp_node
*child
;
6366 struct bgp_node
*rn
;
6367 struct bgp_aggregate
*aggregate
;
6368 struct bgp_table
*table
;
6370 table
= bgp
->aggregate
[afi
][safi
];
6372 /* No aggregates configured. */
6373 if (bgp_table_top_nolock(table
) == NULL
)
6376 if (p
->prefixlen
== 0)
6379 child
= bgp_node_get(table
, p
);
6381 /* Aggregate address configuration check. */
6382 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6383 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6384 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6385 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6386 del
, aggregate
, &rn
->p
);
6389 bgp_unlock_node(child
);
6392 /* Aggregate route attribute. */
6393 #define AGGREGATE_SUMMARY_ONLY 1
6394 #define AGGREGATE_AS_SET 1
6396 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6397 afi_t afi
, safi_t safi
)
6399 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6402 struct bgp_node
*rn
;
6403 struct bgp_aggregate
*aggregate
;
6405 /* Convert string to prefix structure. */
6406 ret
= str2prefix(prefix_str
, &p
);
6408 vty_out(vty
, "Malformed prefix\n");
6409 return CMD_WARNING_CONFIG_FAILED
;
6413 /* Old configuration check. */
6414 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6417 "%% There is no aggregate-address configuration.\n");
6418 return CMD_WARNING_CONFIG_FAILED
;
6421 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6422 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6423 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6424 NULL
, NULL
, 0, aggregate
);
6426 /* Unlock aggregate address configuration. */
6427 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6429 if (aggregate
->community
)
6430 community_free(&aggregate
->community
);
6432 if (aggregate
->community_hash
) {
6433 /* Delete all communities in the hash.
6435 hash_clean(aggregate
->community_hash
,
6436 bgp_aggr_community_remove
);
6437 /* Free up the community_hash.
6439 hash_free(aggregate
->community_hash
);
6442 if (aggregate
->ecommunity
)
6443 ecommunity_free(&aggregate
->ecommunity
);
6445 if (aggregate
->ecommunity_hash
) {
6446 /* Delete all ecommunities in the hash.
6448 hash_clean(aggregate
->ecommunity_hash
,
6449 bgp_aggr_ecommunity_remove
);
6450 /* Free up the ecommunity_hash.
6452 hash_free(aggregate
->ecommunity_hash
);
6455 if (aggregate
->lcommunity
)
6456 lcommunity_free(&aggregate
->lcommunity
);
6458 if (aggregate
->lcommunity_hash
) {
6459 /* Delete all lcommunities in the hash.
6461 hash_clean(aggregate
->lcommunity_hash
,
6462 bgp_aggr_lcommunity_remove
);
6463 /* Free up the lcommunity_hash.
6465 hash_free(aggregate
->lcommunity_hash
);
6468 if (aggregate
->aspath
)
6469 aspath_free(aggregate
->aspath
);
6471 if (aggregate
->aspath_hash
) {
6472 /* Delete all as-paths in the hash.
6474 hash_clean(aggregate
->aspath_hash
,
6475 bgp_aggr_aspath_remove
);
6476 /* Free up the aspath_hash.
6478 hash_free(aggregate
->aspath_hash
);
6481 bgp_aggregate_free(aggregate
);
6482 bgp_unlock_node(rn
);
6483 bgp_unlock_node(rn
);
6488 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6489 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6492 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6495 struct bgp_node
*rn
;
6496 struct bgp_aggregate
*aggregate
;
6498 /* Convert string to prefix structure. */
6499 ret
= str2prefix(prefix_str
, &p
);
6501 vty_out(vty
, "Malformed prefix\n");
6502 return CMD_WARNING_CONFIG_FAILED
;
6506 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6507 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6508 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6510 return CMD_WARNING_CONFIG_FAILED
;
6513 /* Old configuration check. */
6514 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6515 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6518 vty_out(vty
, "There is already same aggregate network.\n");
6519 /* try to remove the old entry */
6520 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6522 vty_out(vty
, "Error deleting aggregate.\n");
6523 bgp_unlock_node(rn
);
6524 return CMD_WARNING_CONFIG_FAILED
;
6528 /* Make aggregate address structure. */
6529 aggregate
= bgp_aggregate_new();
6530 aggregate
->summary_only
= summary_only
;
6531 aggregate
->as_set
= as_set
;
6532 aggregate
->safi
= safi
;
6535 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6536 route_map_counter_decrement(aggregate
->rmap
.map
);
6537 aggregate
->rmap
.name
=
6538 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6539 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6540 route_map_counter_increment(aggregate
->rmap
.map
);
6542 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6544 /* Aggregate address insert into BGP routing table. */
6545 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6550 DEFUN (aggregate_address
,
6551 aggregate_address_cmd
,
6552 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6553 "Configure BGP aggregate entries\n"
6554 "Aggregate prefix\n"
6555 "Generate AS set path information\n"
6556 "Filter more specific routes from updates\n"
6557 "Filter more specific routes from updates\n"
6558 "Generate AS set path information\n"
6559 "Apply route map to aggregate network\n"
6560 "Name of route map\n")
6563 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6564 char *prefix
= argv
[idx
]->arg
;
6567 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6569 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6570 ? AGGREGATE_SUMMARY_ONLY
6574 argv_find(argv
, argc
, "WORD", &idx
);
6576 rmap
= argv
[idx
]->arg
;
6578 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6579 rmap
, summary_only
, as_set
);
6582 DEFUN (aggregate_address_mask
,
6583 aggregate_address_mask_cmd
,
6584 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6585 "Configure BGP aggregate entries\n"
6586 "Aggregate address\n"
6588 "Generate AS set path information\n"
6589 "Filter more specific routes from updates\n"
6590 "Filter more specific routes from updates\n"
6591 "Generate AS set path information\n"
6592 "Apply route map to aggregate network\n"
6593 "Name of route map\n")
6596 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6597 char *prefix
= argv
[idx
]->arg
;
6598 char *mask
= argv
[idx
+ 1]->arg
;
6602 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6604 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6605 ? AGGREGATE_SUMMARY_ONLY
6608 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6610 rmap
= argv
[idx
]->arg
;
6612 char prefix_str
[BUFSIZ
];
6613 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6616 vty_out(vty
, "%% Inconsistent address and mask\n");
6617 return CMD_WARNING_CONFIG_FAILED
;
6620 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6621 rmap
, summary_only
, as_set
);
6624 DEFUN (no_aggregate_address
,
6625 no_aggregate_address_cmd
,
6626 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6628 "Configure BGP aggregate entries\n"
6629 "Aggregate prefix\n"
6630 "Generate AS set path information\n"
6631 "Filter more specific routes from updates\n"
6632 "Filter more specific routes from updates\n"
6633 "Generate AS set path information\n"
6634 "Apply route map to aggregate network\n"
6635 "Name of route map\n")
6638 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6639 char *prefix
= argv
[idx
]->arg
;
6640 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6643 DEFUN (no_aggregate_address_mask
,
6644 no_aggregate_address_mask_cmd
,
6645 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6647 "Configure BGP aggregate entries\n"
6648 "Aggregate address\n"
6650 "Generate AS set path information\n"
6651 "Filter more specific routes from updates\n"
6652 "Filter more specific routes from updates\n"
6653 "Generate AS set path information\n"
6654 "Apply route map to aggregate network\n"
6655 "Name of route map\n")
6658 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6659 char *prefix
= argv
[idx
]->arg
;
6660 char *mask
= argv
[idx
+ 1]->arg
;
6662 char prefix_str
[BUFSIZ
];
6663 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6666 vty_out(vty
, "%% Inconsistent address and mask\n");
6667 return CMD_WARNING_CONFIG_FAILED
;
6670 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6673 DEFUN (ipv6_aggregate_address
,
6674 ipv6_aggregate_address_cmd
,
6675 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6676 "Configure BGP aggregate entries\n"
6677 "Aggregate prefix\n"
6678 "Generate AS set path information\n"
6679 "Filter more specific routes from updates\n"
6680 "Filter more specific routes from updates\n"
6681 "Generate AS set path information\n"
6682 "Apply route map to aggregate network\n"
6683 "Name of route map\n")
6686 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6687 char *prefix
= argv
[idx
]->arg
;
6691 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6694 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6695 ? AGGREGATE_SUMMARY_ONLY
6698 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6700 rmap
= argv
[idx
]->arg
;
6702 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6706 DEFUN (no_ipv6_aggregate_address
,
6707 no_ipv6_aggregate_address_cmd
,
6708 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6710 "Configure BGP aggregate entries\n"
6711 "Aggregate prefix\n"
6712 "Generate AS set path information\n"
6713 "Filter more specific routes from updates\n"
6714 "Filter more specific routes from updates\n"
6715 "Generate AS set path information\n"
6716 "Apply route map to aggregate network\n"
6717 "Name of route map\n")
6720 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6721 char *prefix
= argv
[idx
]->arg
;
6722 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6725 /* Redistribute route treatment. */
6726 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6727 const union g_addr
*nexthop
, ifindex_t ifindex
,
6728 enum nexthop_types_t nhtype
, uint32_t metric
,
6729 uint8_t type
, unsigned short instance
,
6732 struct bgp_path_info
*new;
6733 struct bgp_path_info
*bpi
;
6734 struct bgp_path_info rmap_path
;
6735 struct bgp_node
*bn
;
6737 struct attr
*new_attr
;
6739 route_map_result_t ret
;
6740 struct bgp_redist
*red
;
6742 /* Make default attribute. */
6743 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6745 * This must not be NULL to satisfy Coverity SA
6747 assert(attr
.aspath
);
6750 case NEXTHOP_TYPE_IFINDEX
:
6752 case NEXTHOP_TYPE_IPV4
:
6753 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6754 attr
.nexthop
= nexthop
->ipv4
;
6756 case NEXTHOP_TYPE_IPV6
:
6757 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6758 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6759 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6761 case NEXTHOP_TYPE_BLACKHOLE
:
6762 switch (p
->family
) {
6764 attr
.nexthop
.s_addr
= INADDR_ANY
;
6767 memset(&attr
.mp_nexthop_global
, 0,
6768 sizeof(attr
.mp_nexthop_global
));
6769 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6774 attr
.nh_ifindex
= ifindex
;
6777 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6780 afi
= family2afi(p
->family
);
6782 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6784 struct attr attr_new
;
6786 /* Copy attribute for modification. */
6787 bgp_attr_dup(&attr_new
, &attr
);
6789 if (red
->redist_metric_flag
)
6790 attr_new
.med
= red
->redist_metric
;
6792 /* Apply route-map. */
6793 if (red
->rmap
.name
) {
6794 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6795 rmap_path
.peer
= bgp
->peer_self
;
6796 rmap_path
.attr
= &attr_new
;
6798 SET_FLAG(bgp
->peer_self
->rmap_type
,
6799 PEER_RMAP_TYPE_REDISTRIBUTE
);
6801 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6804 bgp
->peer_self
->rmap_type
= 0;
6806 if (ret
== RMAP_DENYMATCH
) {
6807 /* Free uninterned attribute. */
6808 bgp_attr_flush(&attr_new
);
6810 /* Unintern original. */
6811 aspath_unintern(&attr
.aspath
);
6812 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6817 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6818 bgp_attr_add_gshut_community(&attr_new
);
6820 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6821 SAFI_UNICAST
, p
, NULL
);
6823 new_attr
= bgp_attr_intern(&attr_new
);
6825 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6827 if (bpi
->peer
== bgp
->peer_self
6828 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6832 /* Ensure the (source route) type is updated. */
6834 if (attrhash_cmp(bpi
->attr
, new_attr
)
6835 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6836 bgp_attr_unintern(&new_attr
);
6837 aspath_unintern(&attr
.aspath
);
6838 bgp_unlock_node(bn
);
6841 /* The attribute is changed. */
6842 bgp_path_info_set_flag(bn
, bpi
,
6843 BGP_PATH_ATTR_CHANGED
);
6845 /* Rewrite BGP route information. */
6846 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6847 bgp_path_info_restore(bn
, bpi
);
6849 bgp_aggregate_decrement(
6850 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6851 bgp_attr_unintern(&bpi
->attr
);
6852 bpi
->attr
= new_attr
;
6853 bpi
->uptime
= bgp_clock();
6855 /* Process change. */
6856 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6858 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6859 bgp_unlock_node(bn
);
6860 aspath_unintern(&attr
.aspath
);
6862 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6864 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6866 vpn_leak_from_vrf_update(
6867 bgp_get_default(), bgp
, bpi
);
6873 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6874 bgp
->peer_self
, new_attr
, bn
);
6875 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6877 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6878 bgp_path_info_add(bn
, new);
6879 bgp_unlock_node(bn
);
6880 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6882 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6883 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6885 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6889 /* Unintern original. */
6890 aspath_unintern(&attr
.aspath
);
6893 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6894 unsigned short instance
)
6897 struct bgp_node
*rn
;
6898 struct bgp_path_info
*pi
;
6899 struct bgp_redist
*red
;
6901 afi
= family2afi(p
->family
);
6903 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6905 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6906 SAFI_UNICAST
, p
, NULL
);
6908 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6909 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6913 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6914 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6916 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6919 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6920 bgp_path_info_delete(rn
, pi
);
6921 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6923 bgp_unlock_node(rn
);
6927 /* Withdraw specified route type's route. */
6928 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6929 unsigned short instance
)
6931 struct bgp_node
*rn
;
6932 struct bgp_path_info
*pi
;
6933 struct bgp_table
*table
;
6935 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6937 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6938 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6939 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6940 && pi
->instance
== instance
)
6944 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6945 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6947 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6950 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6952 bgp_path_info_delete(rn
, pi
);
6953 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6958 /* Static function to display route. */
6959 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6966 if (p
->family
== AF_INET
) {
6970 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6973 json_object_string_add(json
, "prefix",
6974 inet_ntop(p
->family
,
6977 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6978 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6979 json_object_string_add(json
, "network", buf2
);
6981 } else if (p
->family
== AF_ETHERNET
) {
6982 prefix2str(p
, buf
, PREFIX_STRLEN
);
6983 len
= vty_out(vty
, "%s", buf
);
6984 } else if (p
->family
== AF_EVPN
) {
6988 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6991 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6992 } else if (p
->family
== AF_FLOWSPEC
) {
6993 route_vty_out_flowspec(vty
, p
, NULL
,
6995 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6996 NLRI_STRING_FORMAT_MIN
, json
);
7001 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7004 json_object_string_add(json
, "prefix",
7005 inet_ntop(p
->family
,
7008 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7009 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7010 json_object_string_add(json
, "network", buf2
);
7017 vty_out(vty
, "\n%*s", 20, " ");
7019 vty_out(vty
, "%*s", len
, " ");
7023 enum bgp_display_type
{
7027 /* Print the short form route status for a bgp_path_info */
7028 static void route_vty_short_status_out(struct vty
*vty
,
7029 struct bgp_path_info
*path
,
7030 json_object
*json_path
)
7034 /* Route status display. */
7035 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7036 json_object_boolean_true_add(json_path
, "removed");
7038 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7039 json_object_boolean_true_add(json_path
, "stale");
7041 if (path
->extra
&& path
->extra
->suppress
)
7042 json_object_boolean_true_add(json_path
, "suppressed");
7044 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7045 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7046 json_object_boolean_true_add(json_path
, "valid");
7049 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7050 json_object_boolean_true_add(json_path
, "history");
7052 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7053 json_object_boolean_true_add(json_path
, "damped");
7055 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7056 json_object_boolean_true_add(json_path
, "bestpath");
7058 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7059 json_object_boolean_true_add(json_path
, "multipath");
7061 /* Internal route. */
7062 if ((path
->peer
->as
)
7063 && (path
->peer
->as
== path
->peer
->local_as
))
7064 json_object_string_add(json_path
, "pathFrom",
7067 json_object_string_add(json_path
, "pathFrom",
7073 /* Route status display. */
7074 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7076 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7078 else if (path
->extra
&& path
->extra
->suppress
)
7080 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7081 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7087 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7089 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7091 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7093 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7098 /* Internal route. */
7099 if (path
->peer
&& (path
->peer
->as
)
7100 && (path
->peer
->as
== path
->peer
->local_as
))
7106 static char *bgp_nexthop_fqdn(struct peer
*peer
)
7108 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
))
7109 return peer
->hostname
;
7113 /* called from terminal list command */
7114 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7115 struct bgp_path_info
*path
, int display
, safi_t safi
,
7116 json_object
*json_paths
)
7119 json_object
*json_path
= NULL
;
7120 json_object
*json_nexthops
= NULL
;
7121 json_object
*json_nexthop_global
= NULL
;
7122 json_object
*json_nexthop_ll
= NULL
;
7123 json_object
*json_ext_community
= NULL
;
7124 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7126 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7127 bool nexthop_othervrf
= false;
7128 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7129 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7130 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
7133 json_path
= json_object_new_object();
7135 /* short status lead text */
7136 route_vty_short_status_out(vty
, path
, json_path
);
7139 /* print prefix and mask */
7141 route_vty_out_route(p
, vty
, json_path
);
7143 vty_out(vty
, "%*s", 17, " ");
7145 route_vty_out_route(p
, vty
, json_path
);
7148 /* Print attribute */
7152 * If vrf id of nexthop is different from that of prefix,
7153 * set up printable string to append
7155 if (path
->extra
&& path
->extra
->bgp_orig
) {
7156 const char *self
= "";
7161 nexthop_othervrf
= true;
7162 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7164 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7165 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7166 "@%s%s", VRFID_NONE_STR
, self
);
7168 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7169 path
->extra
->bgp_orig
->vrf_id
, self
);
7171 if (path
->extra
->bgp_orig
->inst_type
7172 != BGP_INSTANCE_TYPE_DEFAULT
)
7174 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7176 const char *self
= "";
7181 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7185 * For ENCAP and EVPN routes, nexthop address family is not
7186 * neccessarily the same as the prefix address family.
7187 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7188 * EVPN routes are also exchanged with a MP nexthop. Currently,
7190 * is only IPv4, the value will be present in either
7192 * attr->mp_nexthop_global_in
7194 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7197 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7201 sprintf(nexthop
, "%s",
7202 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7206 sprintf(nexthop
, "%s",
7207 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7211 sprintf(nexthop
, "?");
7216 json_nexthop_global
= json_object_new_object();
7218 json_object_string_add(
7219 json_nexthop_global
, "afi",
7220 nexthop_fqdn
? "fqdn"
7221 : (af
== AF_INET
) ? "ip" : "ipv6");
7222 json_object_string_add(
7223 json_nexthop_global
,
7224 nexthop_fqdn
? "fqdn"
7225 : (af
== AF_INET
) ? "ip" : "ipv6",
7226 nexthop_fqdn
? nexthop_fqdn
: nexthop
);
7227 json_object_boolean_true_add(json_nexthop_global
,
7230 vty_out(vty
, "%s%s",
7231 nexthop_fqdn
? nexthop_fqdn
: nexthop
,
7233 } else if (safi
== SAFI_EVPN
) {
7235 json_nexthop_global
= json_object_new_object();
7237 json_object_string_add(
7238 json_nexthop_global
,
7239 nexthop_fqdn
? "fqdn" : "ip",
7240 nexthop_fqdn
? nexthop_fqdn
7241 : inet_ntoa(attr
->nexthop
));
7242 json_object_string_add(json_nexthop_global
, "afi",
7244 json_object_boolean_true_add(json_nexthop_global
,
7247 vty_out(vty
, "%-16s%s",
7248 nexthop_fqdn
?: inet_ntoa(attr
->nexthop
),
7250 } else if (safi
== SAFI_FLOWSPEC
) {
7251 if (attr
->nexthop
.s_addr
!= 0) {
7253 json_nexthop_global
= json_object_new_object();
7254 json_object_string_add(
7255 json_nexthop_global
,
7256 nexthop_fqdn
? "fqdn" : "ip",
7259 : inet_ntoa(attr
->nexthop
));
7260 json_object_string_add(json_nexthop_global
,
7262 json_object_boolean_true_add(
7263 json_nexthop_global
,
7266 vty_out(vty
, "%-16s",
7269 : inet_ntoa(attr
->nexthop
));
7272 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7274 json_nexthop_global
= json_object_new_object();
7276 json_object_string_add(json_nexthop_global
,
7277 nexthop_fqdn
? "fqdn" : "ip",
7280 : inet_ntoa(attr
->nexthop
));
7282 json_object_string_add(json_nexthop_global
, "afi",
7284 json_object_boolean_true_add(json_nexthop_global
,
7289 snprintf(buf
, sizeof(buf
), "%s%s",
7290 nexthop_fqdn
? nexthop_fqdn
7291 : inet_ntoa(attr
->nexthop
),
7293 vty_out(vty
, "%-16s", buf
);
7298 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7303 json_nexthop_global
= json_object_new_object();
7304 json_object_string_add(
7305 json_nexthop_global
,
7306 nexthop_fqdn
? "fqdn" : "ip",
7309 : inet_ntop(AF_INET6
,
7310 &attr
->mp_nexthop_global
,
7312 json_object_string_add(json_nexthop_global
, "afi",
7314 json_object_string_add(json_nexthop_global
, "scope",
7317 /* We display both LL & GL if both have been
7319 if ((attr
->mp_nexthop_len
7320 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7321 || (path
->peer
->conf_if
)) {
7322 json_nexthop_ll
= json_object_new_object();
7323 json_object_string_add(
7325 nexthop_fqdn
? "fqdn" : "ip",
7330 &attr
->mp_nexthop_local
,
7332 json_object_string_add(json_nexthop_ll
, "afi",
7334 json_object_string_add(json_nexthop_ll
, "scope",
7337 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7338 &attr
->mp_nexthop_local
)
7340 && !attr
->mp_nexthop_prefer_global
)
7341 json_object_boolean_true_add(
7342 json_nexthop_ll
, "used");
7344 json_object_boolean_true_add(
7345 json_nexthop_global
, "used");
7347 json_object_boolean_true_add(
7348 json_nexthop_global
, "used");
7350 /* Display LL if LL/Global both in table unless
7351 * prefer-global is set */
7352 if (((attr
->mp_nexthop_len
7353 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7354 && !attr
->mp_nexthop_prefer_global
)
7355 || (path
->peer
->conf_if
)) {
7356 if (path
->peer
->conf_if
) {
7357 len
= vty_out(vty
, "%s",
7358 path
->peer
->conf_if
);
7359 len
= 16 - len
; /* len of IPv6
7365 vty_out(vty
, "\n%*s", 36, " ");
7367 vty_out(vty
, "%*s", len
, " ");
7375 &attr
->mp_nexthop_local
,
7381 vty_out(vty
, "\n%*s", 36, " ");
7383 vty_out(vty
, "%*s", len
, " ");
7392 &attr
->mp_nexthop_global
,
7398 vty_out(vty
, "\n%*s", 36, " ");
7400 vty_out(vty
, "%*s", len
, " ");
7406 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7410 * Adding "metric" field to match with corresponding
7411 * CLI. "med" will be deprecated in future.
7413 json_object_int_add(json_path
, "med", attr
->med
);
7414 json_object_int_add(json_path
, "metric", attr
->med
);
7416 vty_out(vty
, "%10u", attr
->med
);
7417 else if (!json_paths
)
7421 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7425 * Adding "locPrf" field to match with corresponding
7426 * CLI. "localPref" will be deprecated in future.
7428 json_object_int_add(json_path
, "localpref",
7430 json_object_int_add(json_path
, "locPrf",
7433 vty_out(vty
, "%7u", attr
->local_pref
);
7434 else if (!json_paths
)
7438 json_object_int_add(json_path
, "weight", attr
->weight
);
7440 vty_out(vty
, "%7u ", attr
->weight
);
7444 json_object_string_add(
7445 json_path
, "peerId",
7446 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7454 * Adding "path" field to match with corresponding
7455 * CLI. "aspath" will be deprecated in future.
7457 json_object_string_add(json_path
, "aspath",
7459 json_object_string_add(json_path
, "path",
7462 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7467 json_object_string_add(json_path
, "origin",
7468 bgp_origin_long_str
[attr
->origin
]);
7470 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7473 if (safi
== SAFI_EVPN
&&
7474 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7475 json_ext_community
= json_object_new_object();
7476 json_object_string_add(json_ext_community
,
7478 attr
->ecommunity
->str
);
7479 json_object_object_add(json_path
,
7480 "extendedCommunity",
7481 json_ext_community
);
7485 json_object_boolean_true_add(json_path
,
7486 "announceNexthopSelf");
7487 if (nexthop_othervrf
) {
7488 json_object_string_add(json_path
, "nhVrfName",
7491 json_object_int_add(json_path
, "nhVrfId",
7492 ((nexthop_vrfid
== VRF_UNKNOWN
)
7494 : (int)nexthop_vrfid
));
7499 if (json_nexthop_global
|| json_nexthop_ll
) {
7500 json_nexthops
= json_object_new_array();
7502 if (json_nexthop_global
)
7503 json_object_array_add(json_nexthops
,
7504 json_nexthop_global
);
7506 if (json_nexthop_ll
)
7507 json_object_array_add(json_nexthops
,
7510 json_object_object_add(json_path
, "nexthops",
7514 json_object_array_add(json_paths
, json_path
);
7518 if (safi
== SAFI_EVPN
&&
7519 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7520 vty_out(vty
, "%*s", 20, " ");
7521 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7525 /* prints an additional line, indented, with VNC info, if
7527 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7528 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7533 /* called from terminal list command */
7534 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7535 safi_t safi
, bool use_json
, json_object
*json_ar
)
7537 json_object
*json_status
= NULL
;
7538 json_object
*json_net
= NULL
;
7541 /* Route status display. */
7543 json_status
= json_object_new_object();
7544 json_net
= json_object_new_object();
7551 /* print prefix and mask */
7553 if (safi
== SAFI_EVPN
)
7554 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7555 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7556 json_object_string_add(
7557 json_net
, "addrPrefix",
7558 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7560 json_object_int_add(json_net
, "prefixLen",
7562 prefix2str(p
, buff
, PREFIX_STRLEN
);
7563 json_object_string_add(json_net
, "network", buff
);
7566 route_vty_out_route(p
, vty
, NULL
);
7568 /* Print attribute */
7571 if (p
->family
== AF_INET
7572 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7573 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7574 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7575 json_object_string_add(
7576 json_net
, "nextHop",
7578 attr
->mp_nexthop_global_in
));
7580 json_object_string_add(
7581 json_net
, "nextHop",
7582 inet_ntoa(attr
->nexthop
));
7583 } else if (p
->family
== AF_INET6
7584 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7587 json_object_string_add(
7588 json_net
, "nextHopGlobal",
7590 &attr
->mp_nexthop_global
, buf
,
7592 } else if (p
->family
== AF_EVPN
&&
7593 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7594 json_object_string_add(json_net
,
7595 "nextHop", inet_ntoa(
7596 attr
->mp_nexthop_global_in
));
7599 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7600 json_object_int_add(json_net
, "metric",
7603 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7606 * Adding "locPrf" field to match with
7607 * corresponding CLI. "localPref" will be
7608 * deprecated in future.
7610 json_object_int_add(json_net
, "localPref",
7612 json_object_int_add(json_net
, "locPrf",
7616 json_object_int_add(json_net
, "weight", attr
->weight
);
7622 * Adding "path" field to match with
7623 * corresponding CLI. "localPref" will be
7624 * deprecated in future.
7626 json_object_string_add(json_net
, "asPath",
7628 json_object_string_add(json_net
, "path",
7633 json_object_string_add(json_net
, "bgpOriginCode",
7634 bgp_origin_str
[attr
->origin
]);
7636 if (p
->family
== AF_INET
7637 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7638 || safi
== SAFI_EVPN
7639 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7640 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7641 || safi
== SAFI_EVPN
)
7642 vty_out(vty
, "%-16s",
7644 attr
->mp_nexthop_global_in
));
7646 vty_out(vty
, "%-16s",
7647 inet_ntoa(attr
->nexthop
));
7648 } else if (p
->family
== AF_INET6
7649 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7656 &attr
->mp_nexthop_global
, buf
,
7660 vty_out(vty
, "\n%*s", 36, " ");
7662 vty_out(vty
, "%*s", len
, " ");
7665 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7666 vty_out(vty
, "%10u", attr
->med
);
7670 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7671 vty_out(vty
, "%7u", attr
->local_pref
);
7675 vty_out(vty
, "%7u ", attr
->weight
);
7679 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7682 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7686 json_object_boolean_true_add(json_status
, "*");
7687 json_object_boolean_true_add(json_status
, ">");
7688 json_object_object_add(json_net
, "appliedStatusSymbols",
7691 prefix2str(p
, buff
, PREFIX_STRLEN
);
7692 json_object_object_add(json_ar
, buff
, json_net
);
7697 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7698 struct bgp_path_info
*path
, int display
, safi_t safi
,
7701 json_object
*json_out
= NULL
;
7703 mpls_label_t label
= MPLS_INVALID_LABEL
;
7709 json_out
= json_object_new_object();
7711 /* short status lead text */
7712 route_vty_short_status_out(vty
, path
, json_out
);
7714 /* print prefix and mask */
7717 route_vty_out_route(p
, vty
, NULL
);
7719 vty_out(vty
, "%*s", 17, " ");
7722 /* Print attribute */
7724 if (((p
->family
== AF_INET
)
7725 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7726 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7727 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7728 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7729 || safi
== SAFI_EVPN
) {
7731 json_object_string_add(
7732 json_out
, "mpNexthopGlobalIn",
7733 inet_ntoa(attr
->mp_nexthop_global_in
));
7735 vty_out(vty
, "%-16s",
7736 inet_ntoa(attr
->mp_nexthop_global_in
));
7739 json_object_string_add(
7740 json_out
, "nexthop",
7741 inet_ntoa(attr
->nexthop
));
7743 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
7745 } else if (((p
->family
== AF_INET6
)
7746 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7747 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7748 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7751 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7753 json_object_string_add(
7754 json_out
, "mpNexthopGlobalIn",
7756 &attr
->mp_nexthop_global
,
7757 buf_a
, sizeof(buf_a
)));
7761 &attr
->mp_nexthop_global
,
7762 buf_a
, sizeof(buf_a
)));
7763 } else if (attr
->mp_nexthop_len
7764 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7765 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
7766 &attr
->mp_nexthop_global
,
7767 &attr
->mp_nexthop_local
);
7769 json_object_string_add(json_out
,
7770 "mpNexthopGlobalLocal",
7773 vty_out(vty
, "%s", buf_a
);
7777 label
= decode_label(&path
->extra
->label
[0]);
7779 if (bgp_is_valid_label(&label
)) {
7781 json_object_int_add(json_out
, "notag", label
);
7782 json_object_array_add(json
, json_out
);
7784 vty_out(vty
, "notag/%d", label
);
7790 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7791 struct bgp_path_info
*path
, int display
,
7792 json_object
*json_paths
)
7795 char buf
[BUFSIZ
] = {0};
7796 json_object
*json_path
= NULL
;
7797 json_object
*json_nexthop
= NULL
;
7798 json_object
*json_overlay
= NULL
;
7804 json_path
= json_object_new_object();
7805 json_overlay
= json_object_new_object();
7806 json_nexthop
= json_object_new_object();
7809 /* short status lead text */
7810 route_vty_short_status_out(vty
, path
, json_path
);
7812 /* print prefix and mask */
7814 route_vty_out_route(p
, vty
, json_path
);
7816 vty_out(vty
, "%*s", 17, " ");
7818 /* Print attribute */
7821 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7825 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
7827 vty_out(vty
, "%-16s", buf
);
7829 json_object_string_add(json_nexthop
, "ip", buf
);
7831 json_object_string_add(json_nexthop
, "afi", "ipv4");
7833 json_object_object_add(json_path
, "nexthop",
7838 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
7839 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
7841 vty_out(vty
, "%s(%s)", buf
, buf1
);
7843 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
7845 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
7848 json_object_string_add(json_nexthop
, "afi", "ipv6");
7850 json_object_object_add(json_path
, "nexthop",
7858 json_object_string_add(json_nexthop
, "Error",
7859 "Unsupported address-family");
7863 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7866 vty_out(vty
, "%s", str
);
7868 json_object_string_add(json_overlay
, "esi", str
);
7870 XFREE(MTYPE_TMP
, str
);
7872 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7873 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
7875 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7876 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7881 vty_out(vty
, "/%s", buf
);
7883 json_object_string_add(json_overlay
, "gw", buf
);
7885 if (attr
->ecommunity
) {
7887 struct ecommunity_val
*routermac
= ecommunity_lookup(
7888 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7889 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7892 mac
= ecom_mac2str((char *)routermac
->val
);
7895 vty_out(vty
, "/%s", (char *)mac
);
7897 json_object_string_add(json_overlay
, "rmac",
7900 XFREE(MTYPE_TMP
, mac
);
7907 json_object_object_add(json_path
, "overlay", json_overlay
);
7909 json_object_array_add(json_paths
, json_path
);
7913 /* dampening route */
7914 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7915 struct bgp_path_info
*path
, int display
, afi_t afi
,
7916 safi_t safi
, bool use_json
, json_object
*json
)
7920 char timebuf
[BGP_UPTIME_LEN
];
7922 /* short status lead text */
7923 route_vty_short_status_out(vty
, path
, json
);
7925 /* print prefix and mask */
7928 route_vty_out_route(p
, vty
, NULL
);
7930 vty_out(vty
, "%*s", 17, " ");
7933 len
= vty_out(vty
, "%s", path
->peer
->host
);
7937 vty_out(vty
, "\n%*s", 34, " ");
7940 json_object_int_add(json
, "peerHost", len
);
7942 vty_out(vty
, "%*s", len
, " ");
7946 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
7947 safi
, use_json
, json
);
7950 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7951 BGP_UPTIME_LEN
, afi
, safi
,
7954 /* Print attribute */
7960 json_object_string_add(json
, "asPath",
7963 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7968 json_object_string_add(json
, "origin",
7969 bgp_origin_str
[attr
->origin
]);
7971 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7978 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7979 struct bgp_path_info
*path
, int display
, afi_t afi
,
7980 safi_t safi
, bool use_json
, json_object
*json
)
7983 struct bgp_damp_info
*bdi
;
7984 char timebuf
[BGP_UPTIME_LEN
];
7990 bdi
= path
->extra
->damp_info
;
7992 /* short status lead text */
7993 route_vty_short_status_out(vty
, path
, json
);
7995 /* print prefix and mask */
7998 route_vty_out_route(p
, vty
, NULL
);
8000 vty_out(vty
, "%*s", 17, " ");
8003 len
= vty_out(vty
, "%s", path
->peer
->host
);
8007 vty_out(vty
, "\n%*s", 33, " ");
8010 json_object_int_add(json
, "peerHost", len
);
8012 vty_out(vty
, "%*s", len
, " ");
8015 len
= vty_out(vty
, "%d", bdi
->flap
);
8022 json_object_int_add(json
, "bdiFlap", len
);
8024 vty_out(vty
, "%*s", len
, " ");
8028 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8031 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8032 BGP_UPTIME_LEN
, 0, NULL
));
8034 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8035 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8037 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8038 BGP_UPTIME_LEN
, afi
, safi
,
8042 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8043 BGP_UPTIME_LEN
, afi
,
8044 safi
, use_json
, json
));
8047 vty_out(vty
, "%*s ", 8, " ");
8050 /* Print attribute */
8056 json_object_string_add(json
, "asPath",
8059 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8064 json_object_string_add(json
, "origin",
8065 bgp_origin_str
[attr
->origin
]);
8067 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8073 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8074 int *first
, const char *header
,
8075 json_object
*json_adv_to
)
8077 char buf1
[INET6_ADDRSTRLEN
];
8078 json_object
*json_peer
= NULL
;
8081 /* 'advertised-to' is a dictionary of peers we have advertised
8083 * prefix too. The key is the peer's IP or swpX, the value is
8085 * hostname if we know it and "" if not.
8087 json_peer
= json_object_new_object();
8090 json_object_string_add(json_peer
, "hostname",
8094 json_object_object_add(json_adv_to
, peer
->conf_if
,
8097 json_object_object_add(
8099 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8103 vty_out(vty
, "%s", header
);
8108 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8110 vty_out(vty
, " %s(%s)", peer
->hostname
,
8113 vty_out(vty
, " %s(%s)", peer
->hostname
,
8114 sockunion2str(&peer
->su
, buf1
,
8118 vty_out(vty
, " %s", peer
->conf_if
);
8121 sockunion2str(&peer
->su
, buf1
,
8127 static void route_vty_out_tx_ids(struct vty
*vty
,
8128 struct bgp_addpath_info_data
*d
)
8132 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8133 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8134 d
->addpath_tx_id
[i
],
8135 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8139 static const char *bgp_path_selection_reason2str(
8140 enum bgp_path_selection_reason reason
)
8143 case bgp_path_selection_none
:
8144 return "Nothing to Select";
8146 case bgp_path_selection_first
:
8147 return "First path received";
8149 case bgp_path_selection_evpn_sticky_mac
:
8150 return "EVPN Sticky Mac";
8152 case bgp_path_selection_evpn_seq
:
8153 return "EVPN sequence number";
8155 case bgp_path_selection_evpn_lower_ip
:
8156 return "EVPN lower IP";
8158 case bgp_path_selection_weight
:
8161 case bgp_path_selection_local_pref
:
8162 return "Local Pref";
8164 case bgp_path_selection_local_route
:
8165 return "Local Route";
8167 case bgp_path_selection_confed_as_path
:
8168 return "Confederation based AS Path";
8170 case bgp_path_selection_as_path
:
8173 case bgp_path_selection_origin
:
8176 case bgp_path_selection_med
:
8179 case bgp_path_selection_peer
:
8182 case bgp_path_selection_confed
:
8183 return "Confed Peer Type";
8185 case bgp_path_selection_igp_metric
:
8186 return "IGP Metric";
8188 case bgp_path_selection_older
:
8189 return "Older Path";
8191 case bgp_path_selection_router_id
:
8194 case bgp_path_selection_cluster_length
:
8195 return "Cluser length";
8197 case bgp_path_selection_stale
:
8198 return "Path Staleness";
8200 case bgp_path_selection_local_configured
:
8201 return "Locally configured route";
8203 case bgp_path_selection_neighbor_ip
:
8204 return "Neighbor IP";
8206 case bgp_path_selection_default
:
8207 return "Nothing left to compare";
8210 return "Invalid (internal error)";
8213 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8214 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8215 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8217 char buf
[INET6_ADDRSTRLEN
];
8219 char buf2
[EVPN_ROUTE_STRLEN
];
8221 int sockunion_vty_out(struct vty
*, union sockunion
*);
8223 json_object
*json_bestpath
= NULL
;
8224 json_object
*json_cluster_list
= NULL
;
8225 json_object
*json_cluster_list_list
= NULL
;
8226 json_object
*json_ext_community
= NULL
;
8227 json_object
*json_last_update
= NULL
;
8228 json_object
*json_pmsi
= NULL
;
8229 json_object
*json_nexthop_global
= NULL
;
8230 json_object
*json_nexthop_ll
= NULL
;
8231 json_object
*json_nexthops
= NULL
;
8232 json_object
*json_path
= NULL
;
8233 json_object
*json_peer
= NULL
;
8234 json_object
*json_string
= NULL
;
8235 json_object
*json_adv_to
= NULL
;
8237 struct listnode
*node
, *nnode
;
8239 int addpath_capable
;
8241 unsigned int first_as
;
8243 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8245 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
8248 json_path
= json_object_new_object();
8249 json_peer
= json_object_new_object();
8250 json_nexthop_global
= json_object_new_object();
8258 if (path
->extra
&& path
->extra
->num_labels
) {
8259 bgp_evpn_label2str(path
->extra
->label
,
8260 path
->extra
->num_labels
, tag_buf
,
8263 if (safi
== SAFI_EVPN
) {
8265 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8266 buf2
, sizeof(buf2
));
8267 vty_out(vty
, " Route %s", buf2
);
8268 if (tag_buf
[0] != '\0')
8269 vty_out(vty
, " VNI %s", tag_buf
);
8273 json_object_string_add(json_path
, "VNI",
8278 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8279 struct bgp_path_info
*parent_ri
;
8280 struct bgp_node
*rn
, *prn
;
8282 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8283 rn
= parent_ri
->net
;
8284 if (rn
&& rn
->prn
) {
8286 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8287 buf1
, sizeof(buf1
));
8288 if (is_pi_family_evpn(parent_ri
)) {
8289 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8290 buf2
, sizeof(buf2
));
8291 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8293 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8300 /* Line1 display AS-path, Aggregator */
8303 if (!attr
->aspath
->json
)
8304 aspath_str_update(attr
->aspath
, true);
8305 json_object_lock(attr
->aspath
->json
);
8306 json_object_object_add(json_path
, "aspath",
8307 attr
->aspath
->json
);
8309 if (attr
->aspath
->segments
)
8310 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8312 vty_out(vty
, " Local");
8316 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8318 json_object_boolean_true_add(json_path
, "removed");
8320 vty_out(vty
, ", (removed)");
8323 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8325 json_object_boolean_true_add(json_path
, "stale");
8327 vty_out(vty
, ", (stale)");
8330 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8332 json_object_int_add(json_path
, "aggregatorAs",
8333 attr
->aggregator_as
);
8334 json_object_string_add(
8335 json_path
, "aggregatorId",
8336 inet_ntoa(attr
->aggregator_addr
));
8338 vty_out(vty
, ", (aggregated by %u %s)",
8339 attr
->aggregator_as
,
8340 inet_ntoa(attr
->aggregator_addr
));
8344 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8345 PEER_FLAG_REFLECTOR_CLIENT
)) {
8347 json_object_boolean_true_add(json_path
,
8348 "rxedFromRrClient");
8350 vty_out(vty
, ", (Received from a RR-client)");
8353 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8354 PEER_FLAG_RSERVER_CLIENT
)) {
8356 json_object_boolean_true_add(json_path
,
8357 "rxedFromRsClient");
8359 vty_out(vty
, ", (Received from a RS-client)");
8362 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8364 json_object_boolean_true_add(json_path
,
8365 "dampeningHistoryEntry");
8367 vty_out(vty
, ", (history entry)");
8368 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8370 json_object_boolean_true_add(json_path
,
8371 "dampeningSuppressed");
8373 vty_out(vty
, ", (suppressed due to dampening)");
8379 /* Line2 display Next-hop, Neighbor, Router-id */
8380 /* Display the nexthop */
8381 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8382 || bn
->p
.family
== AF_EVPN
)
8383 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8384 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8385 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8386 || safi
== SAFI_EVPN
) {
8388 json_object_string_add(
8389 json_nexthop_global
,
8390 nexthop_fqdn
? "fqdn" : "ip",
8394 attr
->mp_nexthop_global_in
));
8400 attr
->mp_nexthop_global_in
));
8403 json_object_string_add(
8404 json_nexthop_global
,
8405 nexthop_fqdn
? "fqdn" : "ip",
8408 : inet_ntoa(attr
->nexthop
));
8413 : inet_ntoa(attr
->nexthop
));
8417 json_object_string_add(json_nexthop_global
, "afi",
8421 json_object_string_add(
8422 json_nexthop_global
,
8423 nexthop_fqdn
? "fqdn" : "ip",
8426 : inet_ntop(AF_INET6
,
8427 &attr
->mp_nexthop_global
,
8428 buf
, INET6_ADDRSTRLEN
));
8429 json_object_string_add(json_nexthop_global
, "afi",
8431 json_object_string_add(json_nexthop_global
, "scope",
8437 : inet_ntop(AF_INET6
,
8438 &attr
->mp_nexthop_global
,
8439 buf
, INET6_ADDRSTRLEN
));
8443 /* Display the IGP cost or 'inaccessible' */
8444 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8446 json_object_boolean_false_add(json_nexthop_global
,
8449 vty_out(vty
, " (inaccessible)");
8451 if (path
->extra
&& path
->extra
->igpmetric
) {
8453 json_object_int_add(json_nexthop_global
,
8455 path
->extra
->igpmetric
);
8457 vty_out(vty
, " (metric %u)",
8458 path
->extra
->igpmetric
);
8461 /* IGP cost is 0, display this only for json */
8464 json_object_int_add(json_nexthop_global
,
8469 json_object_boolean_true_add(json_nexthop_global
,
8473 /* Display peer "from" output */
8474 /* This path was originated locally */
8475 if (path
->peer
== bgp
->peer_self
) {
8477 if (safi
== SAFI_EVPN
8478 || (bn
->p
.family
== AF_INET
8479 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8481 json_object_string_add(json_peer
, "peerId",
8484 vty_out(vty
, " from 0.0.0.0 ");
8487 json_object_string_add(json_peer
, "peerId",
8490 vty_out(vty
, " from :: ");
8494 json_object_string_add(json_peer
, "routerId",
8495 inet_ntoa(bgp
->router_id
));
8497 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8500 /* We RXed this path from one of our peers */
8504 json_object_string_add(json_peer
, "peerId",
8505 sockunion2str(&path
->peer
->su
,
8508 json_object_string_add(json_peer
, "routerId",
8510 &path
->peer
->remote_id
,
8511 buf1
, sizeof(buf1
)));
8513 if (path
->peer
->hostname
)
8514 json_object_string_add(json_peer
, "hostname",
8515 path
->peer
->hostname
);
8517 if (path
->peer
->domainname
)
8518 json_object_string_add(json_peer
, "domainname",
8519 path
->peer
->domainname
);
8521 if (path
->peer
->conf_if
)
8522 json_object_string_add(json_peer
, "interface",
8523 path
->peer
->conf_if
);
8525 if (path
->peer
->conf_if
) {
8526 if (path
->peer
->hostname
8527 && bgp_flag_check(path
->peer
->bgp
,
8528 BGP_FLAG_SHOW_HOSTNAME
))
8529 vty_out(vty
, " from %s(%s)",
8530 path
->peer
->hostname
,
8531 path
->peer
->conf_if
);
8533 vty_out(vty
, " from %s",
8534 path
->peer
->conf_if
);
8536 if (path
->peer
->hostname
8537 && bgp_flag_check(path
->peer
->bgp
,
8538 BGP_FLAG_SHOW_HOSTNAME
))
8539 vty_out(vty
, " from %s(%s)",
8540 path
->peer
->hostname
,
8543 vty_out(vty
, " from %s",
8544 sockunion2str(&path
->peer
->su
,
8549 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8550 vty_out(vty
, " (%s)",
8551 inet_ntoa(attr
->originator_id
));
8553 vty_out(vty
, " (%s)",
8555 &path
->peer
->remote_id
, buf1
,
8561 * Note when vrfid of nexthop is different from that of prefix
8563 if (path
->extra
&& path
->extra
->bgp_orig
) {
8564 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8569 if (path
->extra
->bgp_orig
->inst_type
8570 == BGP_INSTANCE_TYPE_DEFAULT
)
8571 vn
= VRF_DEFAULT_NAME
;
8573 vn
= path
->extra
->bgp_orig
->name
;
8575 json_object_string_add(json_path
, "nhVrfName", vn
);
8577 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8578 json_object_int_add(json_path
, "nhVrfId", -1);
8580 json_object_int_add(json_path
, "nhVrfId",
8581 (int)nexthop_vrfid
);
8584 if (nexthop_vrfid
== VRF_UNKNOWN
)
8585 vty_out(vty
, " vrf ?");
8587 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8593 json_object_boolean_true_add(json_path
,
8594 "announceNexthopSelf");
8596 vty_out(vty
, " announce-nh-self");
8603 /* display the link-local nexthop */
8604 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8606 json_nexthop_ll
= json_object_new_object();
8607 json_object_string_add(
8608 json_nexthop_ll
, nexthop_fqdn
? "fqdn" : "ip",
8611 : inet_ntop(AF_INET6
,
8612 &attr
->mp_nexthop_local
,
8613 buf
, INET6_ADDRSTRLEN
));
8614 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8615 json_object_string_add(json_nexthop_ll
, "scope",
8618 json_object_boolean_true_add(json_nexthop_ll
,
8621 if (!attr
->mp_nexthop_prefer_global
)
8622 json_object_boolean_true_add(json_nexthop_ll
,
8625 json_object_boolean_true_add(
8626 json_nexthop_global
, "used");
8628 vty_out(vty
, " (%s) %s\n",
8629 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8630 buf
, INET6_ADDRSTRLEN
),
8631 attr
->mp_nexthop_prefer_global
8636 /* If we do not have a link-local nexthop then we must flag the
8640 json_object_boolean_true_add(json_nexthop_global
,
8644 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8645 * Int/Ext/Local, Atomic, best */
8647 json_object_string_add(json_path
, "origin",
8648 bgp_origin_long_str
[attr
->origin
]);
8650 vty_out(vty
, " Origin %s",
8651 bgp_origin_long_str
[attr
->origin
]);
8653 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8656 * Adding "metric" field to match with
8657 * corresponding CLI. "med" will be
8658 * deprecated in future.
8660 json_object_int_add(json_path
, "med", attr
->med
);
8661 json_object_int_add(json_path
, "metric", attr
->med
);
8663 vty_out(vty
, ", metric %u", attr
->med
);
8666 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8668 json_object_int_add(json_path
, "localpref",
8671 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8674 if (attr
->weight
!= 0) {
8676 json_object_int_add(json_path
, "weight", attr
->weight
);
8678 vty_out(vty
, ", weight %u", attr
->weight
);
8681 if (attr
->tag
!= 0) {
8683 json_object_int_add(json_path
, "tag", attr
->tag
);
8685 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
8688 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8690 json_object_boolean_false_add(json_path
, "valid");
8692 vty_out(vty
, ", invalid");
8693 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8695 json_object_boolean_true_add(json_path
, "valid");
8697 vty_out(vty
, ", valid");
8700 if (path
->peer
!= bgp
->peer_self
) {
8701 if (path
->peer
->as
== path
->peer
->local_as
) {
8702 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
8704 json_object_string_add(
8708 vty_out(vty
, ", confed-internal");
8711 json_object_string_add(
8712 json_peer
, "type", "internal");
8714 vty_out(vty
, ", internal");
8717 if (bgp_confederation_peers_check(bgp
,
8720 json_object_string_add(
8724 vty_out(vty
, ", confed-external");
8727 json_object_string_add(
8728 json_peer
, "type", "external");
8730 vty_out(vty
, ", external");
8733 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8735 json_object_boolean_true_add(json_path
, "aggregated");
8736 json_object_boolean_true_add(json_path
, "local");
8738 vty_out(vty
, ", aggregated, local");
8740 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8742 json_object_boolean_true_add(json_path
, "sourced");
8744 vty_out(vty
, ", sourced");
8747 json_object_boolean_true_add(json_path
, "sourced");
8748 json_object_boolean_true_add(json_path
, "local");
8750 vty_out(vty
, ", sourced, local");
8754 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8756 json_object_boolean_true_add(json_path
,
8759 vty_out(vty
, ", atomic-aggregate");
8762 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8763 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8764 && bgp_path_info_mpath_count(path
))) {
8766 json_object_boolean_true_add(json_path
, "multipath");
8768 vty_out(vty
, ", multipath");
8771 // Mark the bestpath(s)
8772 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8773 first_as
= aspath_get_first_as(attr
->aspath
);
8777 json_bestpath
= json_object_new_object();
8778 json_object_int_add(json_bestpath
, "bestpathFromAs",
8782 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
8784 vty_out(vty
, ", bestpath-from-AS Local");
8788 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8791 json_bestpath
= json_object_new_object();
8792 json_object_boolean_true_add(json_bestpath
, "overall");
8793 json_object_string_add(
8794 json_bestpath
, "selectionReason",
8795 bgp_path_selection_reason2str(bn
->reason
));
8797 vty_out(vty
, ", best");
8798 vty_out(vty
, " (%s)",
8799 bgp_path_selection_reason2str(bn
->reason
));
8804 json_object_object_add(json_path
, "bestpath", json_bestpath
);
8809 /* Line 4 display Community */
8810 if (attr
->community
) {
8812 if (!attr
->community
->json
)
8813 community_str(attr
->community
, true);
8814 json_object_lock(attr
->community
->json
);
8815 json_object_object_add(json_path
, "community",
8816 attr
->community
->json
);
8818 vty_out(vty
, " Community: %s\n",
8819 attr
->community
->str
);
8823 /* Line 5 display Extended-community */
8824 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8826 json_ext_community
= json_object_new_object();
8827 json_object_string_add(json_ext_community
, "string",
8828 attr
->ecommunity
->str
);
8829 json_object_object_add(json_path
, "extendedCommunity",
8830 json_ext_community
);
8832 vty_out(vty
, " Extended Community: %s\n",
8833 attr
->ecommunity
->str
);
8837 /* Line 6 display Large community */
8838 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8840 if (!attr
->lcommunity
->json
)
8841 lcommunity_str(attr
->lcommunity
, true);
8842 json_object_lock(attr
->lcommunity
->json
);
8843 json_object_object_add(json_path
, "largeCommunity",
8844 attr
->lcommunity
->json
);
8846 vty_out(vty
, " Large Community: %s\n",
8847 attr
->lcommunity
->str
);
8851 /* Line 7 display Originator, Cluster-id */
8852 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8853 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8854 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8856 json_object_string_add(
8857 json_path
, "originatorId",
8858 inet_ntoa(attr
->originator_id
));
8860 vty_out(vty
, " Originator: %s",
8861 inet_ntoa(attr
->originator_id
));
8864 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8868 json_cluster_list
= json_object_new_object();
8869 json_cluster_list_list
=
8870 json_object_new_array();
8872 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8874 json_string
= json_object_new_string(
8875 inet_ntoa(attr
->cluster
8877 json_object_array_add(
8878 json_cluster_list_list
,
8883 * struct cluster_list does not have
8884 * "str" variable like aspath and community
8885 * do. Add this someday if someone asks
8887 * json_object_string_add(json_cluster_list,
8888 * "string", attr->cluster->str);
8890 json_object_object_add(json_cluster_list
,
8892 json_cluster_list_list
);
8893 json_object_object_add(json_path
, "clusterList",
8896 vty_out(vty
, ", Cluster list: ");
8898 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8901 inet_ntoa(attr
->cluster
8911 if (path
->extra
&& path
->extra
->damp_info
)
8912 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
8915 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8916 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
8917 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8920 json_object_int_add(json_path
, "remoteLabel", label
);
8922 vty_out(vty
, " Remote label: %d\n", label
);
8926 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8928 json_object_int_add(json_path
, "labelIndex",
8931 vty_out(vty
, " Label Index: %d\n",
8935 /* Line 8 display Addpath IDs */
8936 if (path
->addpath_rx_id
8937 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8939 json_object_int_add(json_path
, "addpathRxId",
8940 path
->addpath_rx_id
);
8942 /* Keep backwards compatibility with the old API
8943 * by putting TX All's ID in the old field
8945 json_object_int_add(
8946 json_path
, "addpathTxId",
8948 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
8950 /* ... but create a specific field for each
8953 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8954 json_object_int_add(
8956 bgp_addpath_names(i
)->id_json_name
,
8957 path
->tx_addpath
.addpath_tx_id
[i
]);
8960 vty_out(vty
, " AddPath ID: RX %u, ",
8961 path
->addpath_rx_id
);
8963 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8967 /* If we used addpath to TX a non-bestpath we need to display
8968 * "Advertised to" on a path-by-path basis
8970 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8973 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8975 bgp_addpath_encode_tx(peer
, afi
, safi
);
8976 has_adj
= bgp_adj_out_lookup(
8978 bgp_addpath_id_for_peer(peer
, afi
, safi
,
8979 &path
->tx_addpath
));
8981 if ((addpath_capable
&& has_adj
)
8982 || (!addpath_capable
&& has_adj
8983 && CHECK_FLAG(path
->flags
,
8984 BGP_PATH_SELECTED
))) {
8985 if (json_path
&& !json_adv_to
)
8986 json_adv_to
= json_object_new_object();
8988 route_vty_out_advertised_to(
8990 " Advertised to:", json_adv_to
);
8996 json_object_object_add(
8997 json_path
, "advertisedTo", json_adv_to
);
9006 /* Line 9 display Uptime */
9007 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9009 json_last_update
= json_object_new_object();
9010 json_object_int_add(json_last_update
, "epoch", tbuf
);
9011 json_object_string_add(json_last_update
, "string",
9013 json_object_object_add(json_path
, "lastUpdate",
9016 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9018 /* Line 10 display PMSI tunnel attribute, if present */
9019 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9021 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9022 PMSI_TNLTYPE_STR_DEFAULT
);
9025 json_pmsi
= json_object_new_object();
9026 json_object_string_add(json_pmsi
, "tunnelType", str
);
9027 json_object_int_add(json_pmsi
, "label",
9028 label2vni(&attr
->label
));
9029 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9031 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9032 str
, label2vni(&attr
->label
));
9035 /* We've constructed the json object for this path, add it to the json
9039 if (json_nexthop_global
|| json_nexthop_ll
) {
9040 json_nexthops
= json_object_new_array();
9042 if (json_nexthop_global
)
9043 json_object_array_add(json_nexthops
,
9044 json_nexthop_global
);
9046 if (json_nexthop_ll
)
9047 json_object_array_add(json_nexthops
,
9050 json_object_object_add(json_path
, "nexthops",
9054 json_object_object_add(json_path
, "peer", json_peer
);
9055 json_object_array_add(json_paths
, json_path
);
9059 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9060 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9061 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9063 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9064 const char *prefix_list_str
, afi_t afi
,
9065 safi_t safi
, enum bgp_show_type type
);
9066 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9067 const char *filter
, afi_t afi
, safi_t safi
,
9068 enum bgp_show_type type
);
9069 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9070 const char *rmap_str
, afi_t afi
, safi_t safi
,
9071 enum bgp_show_type type
);
9072 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9073 const char *com
, int exact
, afi_t afi
,
9075 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9076 const char *prefix
, afi_t afi
, safi_t safi
,
9077 enum bgp_show_type type
);
9078 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9079 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
9080 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9081 const char *comstr
, int exact
, afi_t afi
,
9082 safi_t safi
, bool use_json
);
9085 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9086 struct bgp_table
*table
, enum bgp_show_type type
,
9087 void *output_arg
, bool use_json
, char *rd
,
9088 int is_last
, unsigned long *output_cum
,
9089 unsigned long *total_cum
,
9090 unsigned long *json_header_depth
)
9092 struct bgp_path_info
*pi
;
9093 struct bgp_node
*rn
;
9096 unsigned long output_count
= 0;
9097 unsigned long total_count
= 0;
9100 json_object
*json_paths
= NULL
;
9103 if (output_cum
&& *output_cum
!= 0)
9106 if (use_json
&& !*json_header_depth
) {
9108 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9109 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9110 " \"localAS\": %u,\n \"routes\": { ",
9111 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9112 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9115 table
->version
, inet_ntoa(bgp
->router_id
),
9116 bgp
->default_local_pref
, bgp
->as
);
9117 *json_header_depth
= 2;
9119 vty_out(vty
, " \"routeDistinguishers\" : {");
9120 ++*json_header_depth
;
9124 if (use_json
&& rd
) {
9125 vty_out(vty
, " \"%s\" : { ", rd
);
9128 /* Start processing of routes. */
9129 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9130 pi
= bgp_node_get_bgp_path_info(rn
);
9136 json_paths
= json_object_new_array();
9140 for (; pi
; pi
= pi
->next
) {
9142 if (type
== bgp_show_type_flap_statistics
9143 || type
== bgp_show_type_flap_neighbor
9144 || type
== bgp_show_type_dampend_paths
9145 || type
== bgp_show_type_damp_neighbor
) {
9146 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9149 if (type
== bgp_show_type_regexp
) {
9150 regex_t
*regex
= output_arg
;
9152 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9156 if (type
== bgp_show_type_prefix_list
) {
9157 struct prefix_list
*plist
= output_arg
;
9159 if (prefix_list_apply(plist
, &rn
->p
)
9163 if (type
== bgp_show_type_filter_list
) {
9164 struct as_list
*as_list
= output_arg
;
9166 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9167 != AS_FILTER_PERMIT
)
9170 if (type
== bgp_show_type_route_map
) {
9171 struct route_map
*rmap
= output_arg
;
9172 struct bgp_path_info path
;
9173 struct attr dummy_attr
;
9174 route_map_result_t ret
;
9176 bgp_attr_dup(&dummy_attr
, pi
->attr
);
9178 path
.peer
= pi
->peer
;
9179 path
.attr
= &dummy_attr
;
9181 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9183 if (ret
== RMAP_DENYMATCH
)
9186 if (type
== bgp_show_type_neighbor
9187 || type
== bgp_show_type_flap_neighbor
9188 || type
== bgp_show_type_damp_neighbor
) {
9189 union sockunion
*su
= output_arg
;
9191 if (pi
->peer
== NULL
9192 || pi
->peer
->su_remote
== NULL
9193 || !sockunion_same(pi
->peer
->su_remote
, su
))
9196 if (type
== bgp_show_type_cidr_only
) {
9197 uint32_t destination
;
9199 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9200 if (IN_CLASSC(destination
)
9201 && rn
->p
.prefixlen
== 24)
9203 if (IN_CLASSB(destination
)
9204 && rn
->p
.prefixlen
== 16)
9206 if (IN_CLASSA(destination
)
9207 && rn
->p
.prefixlen
== 8)
9210 if (type
== bgp_show_type_prefix_longer
) {
9212 if (!prefix_match(p
, &rn
->p
))
9215 if (type
== bgp_show_type_community_all
) {
9216 if (!pi
->attr
->community
)
9219 if (type
== bgp_show_type_community
) {
9220 struct community
*com
= output_arg
;
9222 if (!pi
->attr
->community
9223 || !community_match(pi
->attr
->community
,
9227 if (type
== bgp_show_type_community_exact
) {
9228 struct community
*com
= output_arg
;
9230 if (!pi
->attr
->community
9231 || !community_cmp(pi
->attr
->community
, com
))
9234 if (type
== bgp_show_type_community_list
) {
9235 struct community_list
*list
= output_arg
;
9237 if (!community_list_match(pi
->attr
->community
,
9241 if (type
== bgp_show_type_community_list_exact
) {
9242 struct community_list
*list
= output_arg
;
9244 if (!community_list_exact_match(
9245 pi
->attr
->community
, list
))
9248 if (type
== bgp_show_type_lcommunity
) {
9249 struct lcommunity
*lcom
= output_arg
;
9251 if (!pi
->attr
->lcommunity
9252 || !lcommunity_match(pi
->attr
->lcommunity
,
9257 if (type
== bgp_show_type_lcommunity_exact
) {
9258 struct lcommunity
*lcom
= output_arg
;
9260 if (!pi
->attr
->lcommunity
9261 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9265 if (type
== bgp_show_type_lcommunity_list
) {
9266 struct community_list
*list
= output_arg
;
9268 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9273 == bgp_show_type_lcommunity_list_exact
) {
9274 struct community_list
*list
= output_arg
;
9276 if (!lcommunity_list_exact_match(
9277 pi
->attr
->lcommunity
, list
))
9280 if (type
== bgp_show_type_lcommunity_all
) {
9281 if (!pi
->attr
->lcommunity
)
9284 if (type
== bgp_show_type_dampend_paths
9285 || type
== bgp_show_type_damp_neighbor
) {
9286 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9287 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9291 if (!use_json
&& header
) {
9292 vty_out(vty
, "BGP table version is %" PRIu64
9293 ", local router ID is %s, vrf id ",
9295 inet_ntoa(bgp
->router_id
));
9296 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9297 vty_out(vty
, "%s", VRFID_NONE_STR
);
9299 vty_out(vty
, "%u", bgp
->vrf_id
);
9301 vty_out(vty
, "Default local pref %u, ",
9302 bgp
->default_local_pref
);
9303 vty_out(vty
, "local AS %u\n", bgp
->as
);
9304 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9305 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9306 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9307 if (type
== bgp_show_type_dampend_paths
9308 || type
== bgp_show_type_damp_neighbor
)
9309 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9310 else if (type
== bgp_show_type_flap_statistics
9311 || type
== bgp_show_type_flap_neighbor
)
9312 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9314 vty_out(vty
, BGP_SHOW_HEADER
);
9317 if (rd
!= NULL
&& !display
&& !output_count
) {
9320 "Route Distinguisher: %s\n",
9323 if (type
== bgp_show_type_dampend_paths
9324 || type
== bgp_show_type_damp_neighbor
)
9325 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9326 safi
, use_json
, json_paths
);
9327 else if (type
== bgp_show_type_flap_statistics
9328 || type
== bgp_show_type_flap_neighbor
)
9329 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9330 safi
, use_json
, json_paths
);
9332 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9344 if (p
->family
== AF_FLOWSPEC
) {
9345 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9347 bgp_fs_nlri_get_string((unsigned char *)
9348 p
->u
.prefix_flowspec
.ptr
,
9349 p
->u
.prefix_flowspec
9352 NLRI_STRING_FORMAT_MIN
,
9355 vty_out(vty
, "\"%s/%d\": ",
9357 p
->u
.prefix_flowspec
.prefixlen
);
9359 vty_out(vty
, ",\"%s/%d\": ",
9361 p
->u
.prefix_flowspec
.prefixlen
);
9363 prefix2str(p
, buf2
, sizeof(buf2
));
9365 vty_out(vty
, "\"%s\": ", buf2
);
9367 vty_out(vty
, ",\"%s\": ", buf2
);
9370 json_object_to_json_string(json_paths
));
9371 json_object_free(json_paths
);
9375 json_object_free(json_paths
);
9379 output_count
+= *output_cum
;
9380 *output_cum
= output_count
;
9383 total_count
+= *total_cum
;
9384 *total_cum
= total_count
;
9388 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9392 for (i
= 0; i
< *json_header_depth
; ++i
)
9393 vty_out(vty
, " } ");
9398 /* No route is displayed */
9399 if (output_count
== 0) {
9400 if (type
== bgp_show_type_normal
)
9402 "No BGP prefixes displayed, %ld exist\n",
9406 "\nDisplayed %ld routes and %ld total paths\n",
9407 output_count
, total_count
);
9414 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9415 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9416 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9418 struct bgp_node
*rn
, *next
;
9419 unsigned long output_cum
= 0;
9420 unsigned long total_cum
= 0;
9421 unsigned long json_header_depth
= 0;
9422 struct bgp_table
*itable
;
9425 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9427 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9428 next
= bgp_route_next(rn
);
9429 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9432 itable
= bgp_node_get_bgp_table_info(rn
);
9433 if (itable
!= NULL
) {
9434 struct prefix_rd prd
;
9435 char rd
[RD_ADDRSTRLEN
];
9437 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9438 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9439 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9440 use_json
, rd
, next
== NULL
, &output_cum
,
9441 &total_cum
, &json_header_depth
);
9447 if (output_cum
== 0)
9448 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9452 "\nDisplayed %ld routes and %ld total paths\n",
9453 output_cum
, total_cum
);
9457 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9458 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9460 struct bgp_table
*table
;
9461 unsigned long json_header_depth
= 0;
9464 bgp
= bgp_get_default();
9469 vty_out(vty
, "No BGP process is configured\n");
9471 vty_out(vty
, "{}\n");
9475 table
= bgp
->rib
[afi
][safi
];
9476 /* use MPLS and ENCAP specific shows until they are merged */
9477 if (safi
== SAFI_MPLS_VPN
) {
9478 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9479 output_arg
, use_json
);
9482 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9483 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9484 output_arg
, use_json
,
9487 /* labeled-unicast routes live in the unicast table */
9488 else if (safi
== SAFI_LABELED_UNICAST
)
9489 safi
= SAFI_UNICAST
;
9491 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9492 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9495 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9496 safi_t safi
, bool use_json
)
9498 struct listnode
*node
, *nnode
;
9501 bool route_output
= false;
9504 vty_out(vty
, "{\n");
9506 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9507 route_output
= true;
9510 vty_out(vty
, ",\n");
9514 vty_out(vty
, "\"%s\":",
9515 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9519 vty_out(vty
, "\nInstance %s:\n",
9520 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9524 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9529 vty_out(vty
, "}\n");
9530 else if (!route_output
)
9531 vty_out(vty
, "%% BGP instance not found\n");
9534 /* Header of detailed BGP route information */
9535 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9536 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9537 afi_t afi
, safi_t safi
, json_object
*json
)
9539 struct bgp_path_info
*pi
;
9542 struct listnode
*node
, *nnode
;
9543 char buf1
[RD_ADDRSTRLEN
];
9544 char buf2
[INET6_ADDRSTRLEN
];
9545 char buf3
[EVPN_ROUTE_STRLEN
];
9546 char prefix_str
[BUFSIZ
];
9551 int route_filter_translated_v4
= 0;
9552 int route_filter_v4
= 0;
9553 int route_filter_translated_v6
= 0;
9554 int route_filter_v6
= 0;
9557 int accept_own_nexthop
= 0;
9560 int no_advertise
= 0;
9564 int has_valid_label
= 0;
9565 mpls_label_t label
= 0;
9566 json_object
*json_adv_to
= NULL
;
9569 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9571 if (has_valid_label
)
9572 label
= label_pton(&rn
->local_label
);
9574 if (safi
== SAFI_EVPN
) {
9577 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9578 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9579 : "", prd
? ":" : "",
9580 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9581 buf3
, sizeof(buf3
)));
9583 json_object_string_add(json
, "rd",
9584 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9586 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9590 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9591 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9592 ? prefix_rd2str(prd
, buf1
,
9595 safi
== SAFI_MPLS_VPN
? ":" : "",
9596 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9601 json_object_string_add(json
, "prefix",
9602 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9605 if (has_valid_label
) {
9607 json_object_int_add(json
, "localLabel", label
);
9609 vty_out(vty
, "Local label: %d\n", label
);
9613 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9614 vty_out(vty
, "not allocated\n");
9616 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9618 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9620 if (pi
->extra
&& pi
->extra
->suppress
)
9623 if (pi
->attr
->community
== NULL
)
9626 no_advertise
+= community_include(
9627 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9628 no_export
+= community_include(pi
->attr
->community
,
9629 COMMUNITY_NO_EXPORT
);
9630 local_as
+= community_include(pi
->attr
->community
,
9631 COMMUNITY_LOCAL_AS
);
9632 accept_own
+= community_include(pi
->attr
->community
,
9633 COMMUNITY_ACCEPT_OWN
);
9634 route_filter_translated_v4
+= community_include(
9635 pi
->attr
->community
,
9636 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9637 route_filter_translated_v6
+= community_include(
9638 pi
->attr
->community
,
9639 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9640 route_filter_v4
+= community_include(
9641 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9642 route_filter_v6
+= community_include(
9643 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9644 llgr_stale
+= community_include(pi
->attr
->community
,
9645 COMMUNITY_LLGR_STALE
);
9646 no_llgr
+= community_include(pi
->attr
->community
,
9648 accept_own_nexthop
+=
9649 community_include(pi
->attr
->community
,
9650 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9651 blackhole
+= community_include(pi
->attr
->community
,
9652 COMMUNITY_BLACKHOLE
);
9653 no_peer
+= community_include(pi
->attr
->community
,
9659 vty_out(vty
, "Paths: (%d available", count
);
9661 vty_out(vty
, ", best #%d", best
);
9662 if (safi
== SAFI_UNICAST
) {
9663 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9664 vty_out(vty
, ", table %s",
9667 vty_out(vty
, ", vrf %s",
9671 vty_out(vty
, ", no best path");
9675 ", accept own local route exported and imported in different VRF");
9676 else if (route_filter_translated_v4
)
9678 ", mark translated RTs for VPNv4 route filtering");
9679 else if (route_filter_v4
)
9681 ", attach RT as-is for VPNv4 route filtering");
9682 else if (route_filter_translated_v6
)
9684 ", mark translated RTs for VPNv6 route filtering");
9685 else if (route_filter_v6
)
9687 ", attach RT as-is for VPNv6 route filtering");
9688 else if (llgr_stale
)
9690 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9693 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9694 else if (accept_own_nexthop
)
9696 ", accept local nexthop");
9698 vty_out(vty
, ", inform peer to blackhole prefix");
9700 vty_out(vty
, ", not advertised to EBGP peer");
9701 else if (no_advertise
)
9702 vty_out(vty
, ", not advertised to any peer");
9704 vty_out(vty
, ", not advertised outside local AS");
9707 ", inform EBGP peer not to advertise to their EBGP peers");
9711 ", Advertisements suppressed by an aggregate.");
9712 vty_out(vty
, ")\n");
9715 /* If we are not using addpath then we can display Advertised to and
9717 * show what peers we advertised the bestpath to. If we are using
9719 * though then we must display Advertised to on a path-by-path basis. */
9720 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9721 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9722 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9723 if (json
&& !json_adv_to
)
9724 json_adv_to
= json_object_new_object();
9726 route_vty_out_advertised_to(
9728 " Advertised to non peer-group peers:\n ",
9735 json_object_object_add(json
, "advertisedTo",
9740 vty_out(vty
, " Not advertised to any peer");
9746 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
9747 struct bgp_node
*bgp_node
, struct vty
*vty
,
9748 struct bgp
*bgp
, afi_t afi
,
9749 safi_t safi
, json_object
*json
,
9750 enum bgp_path_type pathtype
, int *display
)
9752 struct bgp_path_info
*pi
;
9754 char rdbuf
[RD_ADDRSTRLEN
];
9755 json_object
*json_header
= NULL
;
9756 json_object
*json_paths
= NULL
;
9758 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
9761 if (json
&& !json_paths
) {
9762 /* Instantiate json_paths only if path is valid */
9763 json_paths
= json_object_new_array();
9765 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
9766 json_header
= json_object_new_object();
9772 route_vty_out_detail_header(
9773 vty
, bgp
, bgp_node
, pfx_rd
,
9774 AFI_IP
, safi
, json_header
);
9779 if (pathtype
== BGP_PATH_SHOW_ALL
9780 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9781 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
9782 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9783 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
9784 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
9785 route_vty_out_detail(vty
, bgp
, bgp_node
,
9790 if (json
&& json_paths
) {
9791 json_object_object_add(json_header
, "paths", json_paths
);
9794 json_object_object_add(json
, rdbuf
, json_header
);
9798 /* Display specified route of BGP table. */
9799 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9800 struct bgp_table
*rib
, const char *ip_str
,
9801 afi_t afi
, safi_t safi
,
9802 struct prefix_rd
*prd
, int prefix_check
,
9803 enum bgp_path_type pathtype
, bool use_json
)
9807 struct prefix match
;
9808 struct bgp_node
*rn
;
9809 struct bgp_node
*rm
;
9810 struct bgp_table
*table
;
9811 json_object
*json
= NULL
;
9812 json_object
*json_paths
= NULL
;
9814 /* Check IP address argument. */
9815 ret
= str2prefix(ip_str
, &match
);
9817 vty_out(vty
, "address is malformed\n");
9821 match
.family
= afi2family(afi
);
9824 json
= json_object_new_object();
9826 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
9827 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9828 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9830 table
= bgp_node_get_bgp_table_info(rn
);
9834 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9838 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9839 bgp_unlock_node(rm
);
9843 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9844 vty
, bgp
, afi
, safi
, json
,
9845 pathtype
, &display
);
9847 bgp_unlock_node(rm
);
9849 } else if (safi
== SAFI_EVPN
) {
9850 struct bgp_node
*longest_pfx
;
9851 bool is_exact_pfxlen_match
= FALSE
;
9853 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9854 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9856 table
= bgp_node_get_bgp_table_info(rn
);
9861 is_exact_pfxlen_match
= FALSE
;
9863 * Search through all the prefixes for a match. The
9864 * pfx's are enumerated in ascending order of pfxlens.
9865 * So, the last pfx match is the longest match. Set
9866 * is_exact_pfxlen_match when we get exact pfxlen match
9868 for (rm
= bgp_table_top(table
); rm
;
9869 rm
= bgp_route_next(rm
)) {
9871 * Get prefixlen of the ip-prefix within type5
9874 if (evpn_type5_prefix_match(&rm
->p
,
9875 &match
) && rm
->info
) {
9878 bgp_evpn_get_type5_prefixlen(&rm
->p
);
9879 if (type5_pfxlen
== match
.prefixlen
) {
9880 is_exact_pfxlen_match
= TRUE
;
9881 bgp_unlock_node(rm
);
9890 if (prefix_check
&& !is_exact_pfxlen_match
)
9896 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9897 vty
, bgp
, afi
, safi
, json
,
9898 pathtype
, &display
);
9900 bgp_unlock_node(rm
);
9902 } else if (safi
== SAFI_FLOWSPEC
) {
9904 json_paths
= json_object_new_array();
9906 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9907 &match
, prefix_check
,
9911 if (use_json
&& display
)
9912 json_object_object_add(json
, "paths", json_paths
);
9914 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9916 || rn
->p
.prefixlen
== match
.prefixlen
) {
9917 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
9919 pathtype
, &display
);
9922 bgp_unlock_node(rn
);
9927 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9928 json
, JSON_C_TO_STRING_PRETTY
|
9929 JSON_C_TO_STRING_NOSLASHESCAPE
));
9930 json_object_free(json
);
9933 vty_out(vty
, "%% Network not in table\n");
9941 /* Display specified route of Main RIB */
9942 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9943 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9944 int prefix_check
, enum bgp_path_type pathtype
,
9948 bgp
= bgp_get_default();
9951 vty_out(vty
, "No BGP process is configured\n");
9953 vty_out(vty
, "{}\n");
9958 /* labeled-unicast routes live in the unicast table */
9959 if (safi
== SAFI_LABELED_UNICAST
)
9960 safi
= SAFI_UNICAST
;
9962 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9963 afi
, safi
, prd
, prefix_check
, pathtype
,
9967 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9968 struct cmd_token
**argv
, bool exact
, afi_t afi
,
9969 safi_t safi
, bool uj
)
9971 struct lcommunity
*lcom
;
9977 b
= buffer_new(1024);
9978 for (i
= 0; i
< argc
; i
++) {
9980 buffer_putc(b
, ' ');
9982 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9984 buffer_putstr(b
, argv
[i
]->arg
);
9988 buffer_putc(b
, '\0');
9990 str
= buffer_getstr(b
);
9993 lcom
= lcommunity_str2com(str
);
9994 XFREE(MTYPE_TMP
, str
);
9996 vty_out(vty
, "%% Large-community malformed\n");
10000 return bgp_show(vty
, bgp
, afi
, safi
,
10001 (exact
? bgp_show_type_lcommunity_exact
10002 : bgp_show_type_lcommunity
),
10006 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10007 const char *lcom
, bool exact
, afi_t afi
,
10008 safi_t safi
, bool uj
)
10010 struct community_list
*list
;
10012 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10013 LARGE_COMMUNITY_LIST_MASTER
);
10014 if (list
== NULL
) {
10015 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10017 return CMD_WARNING
;
10020 return bgp_show(vty
, bgp
, afi
, safi
,
10021 (exact
? bgp_show_type_lcommunity_list_exact
10022 : bgp_show_type_lcommunity_list
),
10026 DEFUN (show_ip_bgp_large_community_list
,
10027 show_ip_bgp_large_community_list_cmd
,
10028 "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]",
10032 BGP_INSTANCE_HELP_STR
10034 BGP_SAFI_WITH_LABEL_HELP_STR
10035 "Display routes matching the large-community-list\n"
10036 "large-community-list number\n"
10037 "large-community-list name\n"
10038 "Exact match of the large-communities\n"
10042 afi_t afi
= AFI_IP6
;
10043 safi_t safi
= SAFI_UNICAST
;
10045 bool exact_match
= 0;
10047 if (argv_find(argv
, argc
, "ip", &idx
))
10049 if (argv_find(argv
, argc
, "view", &idx
)
10050 || argv_find(argv
, argc
, "vrf", &idx
))
10051 vrf
= argv
[++idx
]->arg
;
10052 if (argv_find(argv
, argc
, "ipv4", &idx
)
10053 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10054 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10055 if (argv_find(argv
, argc
, "unicast", &idx
)
10056 || argv_find(argv
, argc
, "multicast", &idx
))
10057 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10060 bool uj
= use_json(argc
, argv
);
10062 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10064 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10065 return CMD_WARNING
;
10068 argv_find(argv
, argc
, "large-community-list", &idx
);
10070 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10072 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10075 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10076 exact_match
, afi
, safi
, uj
);
10078 DEFUN (show_ip_bgp_large_community
,
10079 show_ip_bgp_large_community_cmd
,
10080 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10084 BGP_INSTANCE_HELP_STR
10086 BGP_SAFI_WITH_LABEL_HELP_STR
10087 "Display routes matching the large-communities\n"
10088 "List of large-community numbers\n"
10089 "Exact match of the large-communities\n"
10093 afi_t afi
= AFI_IP6
;
10094 safi_t safi
= SAFI_UNICAST
;
10096 bool exact_match
= 0;
10098 if (argv_find(argv
, argc
, "ip", &idx
))
10100 if (argv_find(argv
, argc
, "view", &idx
)
10101 || argv_find(argv
, argc
, "vrf", &idx
))
10102 vrf
= argv
[++idx
]->arg
;
10103 if (argv_find(argv
, argc
, "ipv4", &idx
)
10104 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10105 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10106 if (argv_find(argv
, argc
, "unicast", &idx
)
10107 || argv_find(argv
, argc
, "multicast", &idx
))
10108 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10111 bool uj
= use_json(argc
, argv
);
10113 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10115 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10116 return CMD_WARNING
;
10119 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10120 if (argv_find(argv
, argc
, "exact-match", &idx
))
10122 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10123 exact_match
, afi
, safi
, uj
);
10125 return bgp_show(vty
, bgp
, afi
, safi
,
10126 bgp_show_type_lcommunity_all
, NULL
, uj
);
10129 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10133 /* BGP route print out function without JSON */
10134 DEFUN (show_ip_bgp
,
10136 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10137 <dampening <parameters>\
10142 |community-list <(1-500)|WORD> [exact-match]\
10143 |A.B.C.D/M longer-prefixes\
10144 |X:X::X:X/M longer-prefixes\
10149 BGP_INSTANCE_HELP_STR
10151 BGP_SAFI_WITH_LABEL_HELP_STR
10152 "Display detailed information about dampening\n"
10153 "Display detail of configured dampening parameters\n"
10154 "Display routes matching the route-map\n"
10155 "A route-map to match on\n"
10156 "Display routes conforming to the prefix-list\n"
10157 "Prefix-list name\n"
10158 "Display routes conforming to the filter-list\n"
10159 "Regular expression access list name\n"
10160 "BGP RIB advertisement statistics\n"
10161 "Display routes matching the community-list\n"
10162 "community-list number\n"
10163 "community-list name\n"
10164 "Exact match of the communities\n"
10166 "Display route and more specific routes\n"
10168 "Display route and more specific routes\n")
10170 afi_t afi
= AFI_IP6
;
10171 safi_t safi
= SAFI_UNICAST
;
10172 int exact_match
= 0;
10173 struct bgp
*bgp
= NULL
;
10176 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10179 return CMD_WARNING
;
10181 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10182 if (argv_find(argv
, argc
, "parameters", &idx
))
10183 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10186 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10187 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10188 safi
, bgp_show_type_prefix_list
);
10190 if (argv_find(argv
, argc
, "filter-list", &idx
))
10191 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10192 safi
, bgp_show_type_filter_list
);
10194 if (argv_find(argv
, argc
, "statistics", &idx
))
10195 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10197 if (argv_find(argv
, argc
, "route-map", &idx
))
10198 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10199 safi
, bgp_show_type_route_map
);
10201 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10202 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10203 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10205 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10206 exact_match
, afi
, safi
);
10208 /* prefix-longer */
10209 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10210 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10211 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10213 bgp_show_type_prefix_longer
);
10215 return CMD_WARNING
;
10218 /* BGP route print out function with JSON */
10219 DEFUN (show_ip_bgp_json
,
10220 show_ip_bgp_json_cmd
,
10221 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10223 |dampening <flap-statistics|dampened-paths>\
10224 |community [AA:NN|local-AS|no-advertise|no-export\
10225 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10226 |accept-own|accept-own-nexthop|route-filter-v6\
10227 |route-filter-v4|route-filter-translated-v6\
10228 |route-filter-translated-v4] [exact-match]\
10233 BGP_INSTANCE_HELP_STR
10235 BGP_SAFI_WITH_LABEL_HELP_STR
10236 "Display only routes with non-natural netmasks\n"
10237 "Display detailed information about dampening\n"
10238 "Display flap statistics of routes\n"
10239 "Display paths suppressed due to dampening\n"
10240 "Display routes matching the communities\n"
10242 "Do not send outside local AS (well-known community)\n"
10243 "Do not advertise to any peer (well-known community)\n"
10244 "Do not export to next AS (well-known community)\n"
10245 "Graceful shutdown (well-known community)\n"
10246 "Do not export to any peer (well-known community)\n"
10247 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10248 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10249 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10250 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10251 "Should accept VPN route with local nexthop (well-known community)\n"
10252 "RT VPNv6 route filtering (well-known community)\n"
10253 "RT VPNv4 route filtering (well-known community)\n"
10254 "RT translated VPNv6 route filtering (well-known community)\n"
10255 "RT translated VPNv4 route filtering (well-known community)\n"
10256 "Exact match of the communities\n"
10259 afi_t afi
= AFI_IP6
;
10260 safi_t safi
= SAFI_UNICAST
;
10261 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10262 struct bgp
*bgp
= NULL
;
10264 int exact_match
= 0;
10265 bool uj
= use_json(argc
, argv
);
10270 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10273 return CMD_WARNING
;
10275 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10276 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10279 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10280 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10281 return bgp_show(vty
, bgp
, afi
, safi
,
10282 bgp_show_type_dampend_paths
, NULL
, uj
);
10283 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10284 return bgp_show(vty
, bgp
, afi
, safi
,
10285 bgp_show_type_flap_statistics
, NULL
,
10289 if (argv_find(argv
, argc
, "community", &idx
)) {
10290 char *maybecomm
= NULL
;
10291 char *community
= NULL
;
10293 if (idx
+ 1 < argc
) {
10294 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10295 maybecomm
= argv
[idx
+ 1]->arg
;
10297 maybecomm
= argv
[idx
+ 1]->text
;
10300 if (maybecomm
&& !strmatch(maybecomm
, "json")
10301 && !strmatch(maybecomm
, "exact-match"))
10302 community
= maybecomm
;
10304 if (argv_find(argv
, argc
, "exact-match", &idx
))
10308 return bgp_show_community(vty
, bgp
, community
,
10309 exact_match
, afi
, safi
, uj
);
10311 return (bgp_show(vty
, bgp
, afi
, safi
,
10312 bgp_show_type_community_all
, NULL
,
10316 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10319 DEFUN (show_ip_bgp_route
,
10320 show_ip_bgp_route_cmd
,
10321 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10322 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10326 BGP_INSTANCE_HELP_STR
10328 BGP_SAFI_WITH_LABEL_HELP_STR
10329 "Network in the BGP routing table to display\n"
10331 "Network in the BGP routing table to display\n"
10333 "Display only the bestpath\n"
10334 "Display only multipaths\n"
10337 int prefix_check
= 0;
10339 afi_t afi
= AFI_IP6
;
10340 safi_t safi
= SAFI_UNICAST
;
10341 char *prefix
= NULL
;
10342 struct bgp
*bgp
= NULL
;
10343 enum bgp_path_type path_type
;
10344 bool uj
= use_json(argc
, argv
);
10348 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10351 return CMD_WARNING
;
10355 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10356 return CMD_WARNING
;
10359 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10360 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10361 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10363 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10364 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10367 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10368 && afi
!= AFI_IP6
) {
10370 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10371 return CMD_WARNING
;
10373 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10374 && afi
!= AFI_IP
) {
10376 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10377 return CMD_WARNING
;
10380 prefix
= argv
[idx
]->arg
;
10382 /* [<bestpath|multipath>] */
10383 if (argv_find(argv
, argc
, "bestpath", &idx
))
10384 path_type
= BGP_PATH_SHOW_BESTPATH
;
10385 else if (argv_find(argv
, argc
, "multipath", &idx
))
10386 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10388 path_type
= BGP_PATH_SHOW_ALL
;
10390 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10394 DEFUN (show_ip_bgp_regexp
,
10395 show_ip_bgp_regexp_cmd
,
10396 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10400 BGP_INSTANCE_HELP_STR
10402 BGP_SAFI_WITH_LABEL_HELP_STR
10403 "Display routes matching the AS path regular expression\n"
10404 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10406 afi_t afi
= AFI_IP6
;
10407 safi_t safi
= SAFI_UNICAST
;
10408 struct bgp
*bgp
= NULL
;
10411 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10414 return CMD_WARNING
;
10416 // get index of regex
10417 argv_find(argv
, argc
, "regexp", &idx
);
10420 char *regstr
= argv_concat(argv
, argc
, idx
);
10421 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10422 bgp_show_type_regexp
);
10423 XFREE(MTYPE_TMP
, regstr
);
10427 DEFUN (show_ip_bgp_instance_all
,
10428 show_ip_bgp_instance_all_cmd
,
10429 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10433 BGP_INSTANCE_ALL_HELP_STR
10435 BGP_SAFI_WITH_LABEL_HELP_STR
10438 afi_t afi
= AFI_IP
;
10439 safi_t safi
= SAFI_UNICAST
;
10440 struct bgp
*bgp
= NULL
;
10442 bool uj
= use_json(argc
, argv
);
10447 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10450 return CMD_WARNING
;
10452 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10453 return CMD_SUCCESS
;
10456 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10457 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10462 if (!config_bgp_aspath_validate(regstr
)) {
10463 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10465 return CMD_WARNING_CONFIG_FAILED
;
10468 regex
= bgp_regcomp(regstr
);
10470 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10471 return CMD_WARNING
;
10474 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10475 bgp_regex_free(regex
);
10479 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10480 const char *prefix_list_str
, afi_t afi
,
10481 safi_t safi
, enum bgp_show_type type
)
10483 struct prefix_list
*plist
;
10485 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10486 if (plist
== NULL
) {
10487 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10489 return CMD_WARNING
;
10492 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10495 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10496 const char *filter
, afi_t afi
, safi_t safi
,
10497 enum bgp_show_type type
)
10499 struct as_list
*as_list
;
10501 as_list
= as_list_lookup(filter
);
10502 if (as_list
== NULL
) {
10503 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10505 return CMD_WARNING
;
10508 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10511 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10512 const char *rmap_str
, afi_t afi
, safi_t safi
,
10513 enum bgp_show_type type
)
10515 struct route_map
*rmap
;
10517 rmap
= route_map_lookup_by_name(rmap_str
);
10519 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10520 return CMD_WARNING
;
10523 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10526 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10527 const char *comstr
, int exact
, afi_t afi
,
10528 safi_t safi
, bool use_json
)
10530 struct community
*com
;
10533 com
= community_str2com(comstr
);
10535 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10536 return CMD_WARNING
;
10539 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10540 (exact
? bgp_show_type_community_exact
10541 : bgp_show_type_community
),
10543 community_free(&com
);
10548 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10549 const char *com
, int exact
, afi_t afi
,
10552 struct community_list
*list
;
10554 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10555 if (list
== NULL
) {
10556 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10557 return CMD_WARNING
;
10560 return bgp_show(vty
, bgp
, afi
, safi
,
10561 (exact
? bgp_show_type_community_list_exact
10562 : bgp_show_type_community_list
),
10566 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10567 const char *prefix
, afi_t afi
, safi_t safi
,
10568 enum bgp_show_type type
)
10575 ret
= str2prefix(prefix
, p
);
10577 vty_out(vty
, "%% Malformed Prefix\n");
10578 return CMD_WARNING
;
10581 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10587 BGP_STATS_MAXBITLEN
= 0,
10589 BGP_STATS_PREFIXES
,
10591 BGP_STATS_UNAGGREGATEABLE
,
10592 BGP_STATS_MAX_AGGREGATEABLE
,
10593 BGP_STATS_AGGREGATES
,
10595 BGP_STATS_ASPATH_COUNT
,
10596 BGP_STATS_ASPATH_MAXHOPS
,
10597 BGP_STATS_ASPATH_TOTHOPS
,
10598 BGP_STATS_ASPATH_MAXSIZE
,
10599 BGP_STATS_ASPATH_TOTSIZE
,
10600 BGP_STATS_ASN_HIGHEST
,
10604 static const char *const table_stats_strs
[] = {
10605 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10606 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10607 [BGP_STATS_RIB
] = "Total Advertisements",
10608 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10609 [BGP_STATS_MAX_AGGREGATEABLE
] =
10610 "Maximum aggregateable prefixes",
10611 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10612 [BGP_STATS_SPACE
] = "Address space advertised",
10613 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10614 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10615 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10616 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10617 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10618 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10619 [BGP_STATS_MAX
] = NULL
,
10622 struct bgp_table_stats
{
10623 struct bgp_table
*table
;
10624 unsigned long long counts
[BGP_STATS_MAX
];
10625 double total_space
;
10629 #define TALLY_SIGFIG 100000
10630 static unsigned long
10631 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10633 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10634 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10635 unsigned long ret
= newtot
/ count
;
10637 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10644 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10645 struct bgp_table_stats
*ts
, unsigned int space
)
10647 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10648 struct bgp_path_info
*pi
;
10653 if (!bgp_node_has_bgp_path_info_data(rn
))
10656 ts
->counts
[BGP_STATS_PREFIXES
]++;
10657 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10660 ts
->counts
[BGP_STATS_AVGPLEN
]
10661 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10662 ts
->counts
[BGP_STATS_AVGPLEN
],
10666 /* check if the prefix is included by any other announcements */
10667 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10668 prn
= bgp_node_parent_nolock(prn
);
10670 if (prn
== NULL
|| prn
== top
) {
10671 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10672 /* announced address space */
10674 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10675 } else if (bgp_node_has_bgp_path_info_data(prn
))
10676 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10679 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10680 ts
->counts
[BGP_STATS_RIB
]++;
10682 if (CHECK_FLAG(pi
->attr
->flag
,
10683 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
10684 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10686 /* as-path stats */
10687 if (pi
->attr
->aspath
) {
10688 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10689 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10690 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10692 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10694 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10695 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10697 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10698 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10700 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10701 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10703 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10704 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10705 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10707 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10708 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10709 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10712 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10713 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10718 static int bgp_table_stats_walker(struct thread
*t
)
10720 struct bgp_node
*rn
, *nrn
;
10721 struct bgp_node
*top
;
10722 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10723 unsigned int space
= 0;
10725 if (!(top
= bgp_table_top(ts
->table
)))
10728 switch (ts
->table
->afi
) {
10730 space
= IPV4_MAX_BITLEN
;
10733 space
= IPV6_MAX_BITLEN
;
10739 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10741 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10742 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10743 struct bgp_table
*table
;
10745 table
= bgp_node_get_bgp_table_info(rn
);
10749 top
= bgp_table_top(table
);
10750 for (nrn
= bgp_table_top(table
); nrn
;
10751 nrn
= bgp_route_next(nrn
))
10752 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10754 bgp_table_stats_rn(rn
, top
, ts
, space
);
10761 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10764 struct bgp_table_stats ts
;
10767 if (!bgp
->rib
[afi
][safi
]) {
10768 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10770 return CMD_WARNING
;
10773 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
10775 /* labeled-unicast routes live in the unicast table */
10776 if (safi
== SAFI_LABELED_UNICAST
)
10777 safi
= SAFI_UNICAST
;
10779 memset(&ts
, 0, sizeof(ts
));
10780 ts
.table
= bgp
->rib
[afi
][safi
];
10781 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10783 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10784 if (!table_stats_strs
[i
])
10789 case BGP_STATS_ASPATH_AVGHOPS
:
10790 case BGP_STATS_ASPATH_AVGSIZE
:
10791 case BGP_STATS_AVGPLEN
:
10792 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10793 vty_out (vty
, "%12.2f",
10794 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10797 case BGP_STATS_ASPATH_TOTHOPS
:
10798 case BGP_STATS_ASPATH_TOTSIZE
:
10799 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10800 vty_out(vty
, "%12.2f",
10802 ? (float)ts
.counts
[i
]
10804 [BGP_STATS_ASPATH_COUNT
]
10807 case BGP_STATS_TOTPLEN
:
10808 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10809 vty_out(vty
, "%12.2f",
10811 ? (float)ts
.counts
[i
]
10813 [BGP_STATS_PREFIXES
]
10816 case BGP_STATS_SPACE
:
10817 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10818 vty_out(vty
, "%12g\n", ts
.total_space
);
10820 if (afi
== AFI_IP6
) {
10821 vty_out(vty
, "%30s: ", "/32 equivalent ");
10822 vty_out(vty
, "%12g\n",
10823 ts
.total_space
* pow(2.0, -128 + 32));
10824 vty_out(vty
, "%30s: ", "/48 equivalent ");
10825 vty_out(vty
, "%12g\n",
10826 ts
.total_space
* pow(2.0, -128 + 48));
10828 vty_out(vty
, "%30s: ", "% announced ");
10829 vty_out(vty
, "%12.2f\n",
10830 ts
.total_space
* 100. * pow(2.0, -32));
10831 vty_out(vty
, "%30s: ", "/8 equivalent ");
10832 vty_out(vty
, "%12.2f\n",
10833 ts
.total_space
* pow(2.0, -32 + 8));
10834 vty_out(vty
, "%30s: ", "/24 equivalent ");
10835 vty_out(vty
, "%12.2f\n",
10836 ts
.total_space
* pow(2.0, -32 + 24));
10840 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10841 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10844 vty_out(vty
, "\n");
10846 return CMD_SUCCESS
;
10858 PCOUNT_PFCNT
, /* the figure we display to users */
10862 static const char *const pcount_strs
[] = {
10863 [PCOUNT_ADJ_IN
] = "Adj-in",
10864 [PCOUNT_DAMPED
] = "Damped",
10865 [PCOUNT_REMOVED
] = "Removed",
10866 [PCOUNT_HISTORY
] = "History",
10867 [PCOUNT_STALE
] = "Stale",
10868 [PCOUNT_VALID
] = "Valid",
10869 [PCOUNT_ALL
] = "All RIB",
10870 [PCOUNT_COUNTED
] = "PfxCt counted",
10871 [PCOUNT_PFCNT
] = "Useable",
10872 [PCOUNT_MAX
] = NULL
,
10875 struct peer_pcounts
{
10876 unsigned int count
[PCOUNT_MAX
];
10877 const struct peer
*peer
;
10878 const struct bgp_table
*table
;
10881 static int bgp_peer_count_walker(struct thread
*t
)
10883 struct bgp_node
*rn
;
10884 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10885 const struct peer
*peer
= pc
->peer
;
10887 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10888 struct bgp_adj_in
*ain
;
10889 struct bgp_path_info
*pi
;
10891 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10892 if (ain
->peer
== peer
)
10893 pc
->count
[PCOUNT_ADJ_IN
]++;
10895 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10897 if (pi
->peer
!= peer
)
10900 pc
->count
[PCOUNT_ALL
]++;
10902 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10903 pc
->count
[PCOUNT_DAMPED
]++;
10904 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10905 pc
->count
[PCOUNT_HISTORY
]++;
10906 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10907 pc
->count
[PCOUNT_REMOVED
]++;
10908 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10909 pc
->count
[PCOUNT_STALE
]++;
10910 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10911 pc
->count
[PCOUNT_VALID
]++;
10912 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10913 pc
->count
[PCOUNT_PFCNT
]++;
10915 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10916 pc
->count
[PCOUNT_COUNTED
]++;
10917 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10919 EC_LIB_DEVELOPMENT
,
10920 "Attempting to count but flags say it is unusable");
10922 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10924 EC_LIB_DEVELOPMENT
,
10925 "Not counted but flags say we should");
10932 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10933 safi_t safi
, bool use_json
)
10935 struct peer_pcounts pcounts
= {.peer
= peer
};
10937 json_object
*json
= NULL
;
10938 json_object
*json_loop
= NULL
;
10941 json
= json_object_new_object();
10942 json_loop
= json_object_new_object();
10945 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10946 || !peer
->bgp
->rib
[afi
][safi
]) {
10948 json_object_string_add(
10950 "No such neighbor or address family");
10951 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10952 json_object_free(json
);
10954 vty_out(vty
, "%% No such neighbor or address family\n");
10956 return CMD_WARNING
;
10959 memset(&pcounts
, 0, sizeof(pcounts
));
10960 pcounts
.peer
= peer
;
10961 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10963 /* in-place call via thread subsystem so as to record execution time
10964 * stats for the thread-walk (i.e. ensure this can't be blamed on
10965 * on just vty_read()).
10967 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10970 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10971 json_object_string_add(json
, "multiProtocol",
10972 get_afi_safi_str(afi
, safi
, true));
10973 json_object_int_add(json
, "pfxCounter",
10974 peer
->pcount
[afi
][safi
]);
10976 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10977 json_object_int_add(json_loop
, pcount_strs
[i
],
10980 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10982 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10983 json_object_string_add(json
, "pfxctDriftFor",
10985 json_object_string_add(
10986 json
, "recommended",
10987 "Please report this bug, with the above command output");
10989 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10990 json
, JSON_C_TO_STRING_PRETTY
));
10991 json_object_free(json
);
10995 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10996 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10997 peer
->hostname
, peer
->host
,
10998 get_afi_safi_str(afi
, safi
, false));
11000 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11001 get_afi_safi_str(afi
, safi
, false));
11004 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
11005 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11007 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11008 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
11011 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11012 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
11014 "Please report this bug, with the above command output\n");
11018 return CMD_SUCCESS
;
11021 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11022 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11023 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11024 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11028 BGP_INSTANCE_HELP_STR
11031 "Detailed information on TCP and BGP neighbor connections\n"
11032 "Neighbor to display information about\n"
11033 "Neighbor to display information about\n"
11034 "Neighbor on BGP configured interface\n"
11035 "Display detailed prefix count information\n"
11038 afi_t afi
= AFI_IP6
;
11039 safi_t safi
= SAFI_UNICAST
;
11042 struct bgp
*bgp
= NULL
;
11043 bool uj
= use_json(argc
, argv
);
11048 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11051 return CMD_WARNING
;
11053 argv_find(argv
, argc
, "neighbors", &idx
);
11054 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11056 return CMD_WARNING
;
11058 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11061 #ifdef KEEP_OLD_VPN_COMMANDS
11062 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11063 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11064 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11069 "Display information about all VPNv4 NLRIs\n"
11070 "Detailed information on TCP and BGP neighbor connections\n"
11071 "Neighbor to display information about\n"
11072 "Neighbor to display information about\n"
11073 "Neighbor on BGP configured interface\n"
11074 "Display detailed prefix count information\n"
11079 bool uj
= use_json(argc
, argv
);
11081 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11083 return CMD_WARNING
;
11085 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11088 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11089 show_ip_bgp_vpn_all_route_prefix_cmd
,
11090 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11095 "Display information about all VPNv4 NLRIs\n"
11096 "Network in the BGP routing table to display\n"
11097 "Network in the BGP routing table to display\n"
11101 char *network
= NULL
;
11102 struct bgp
*bgp
= bgp_get_default();
11104 vty_out(vty
, "Can't find default instance\n");
11105 return CMD_WARNING
;
11108 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11109 network
= argv
[idx
]->arg
;
11110 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11111 network
= argv
[idx
]->arg
;
11113 vty_out(vty
, "Unable to figure out Network\n");
11114 return CMD_WARNING
;
11117 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11118 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11120 #endif /* KEEP_OLD_VPN_COMMANDS */
11122 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11123 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11124 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11129 "Network in the BGP routing table to display\n"
11130 "Network in the BGP routing table to display\n"
11131 "Network in the BGP routing table to display\n"
11132 "Network in the BGP routing table to display\n"
11136 char *network
= NULL
;
11137 int prefix_check
= 0;
11139 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11140 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11141 network
= argv
[idx
]->arg
;
11142 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11143 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11144 network
= argv
[idx
]->arg
;
11147 vty_out(vty
, "Unable to figure out Network\n");
11148 return CMD_WARNING
;
11150 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11151 prefix_check
, BGP_PATH_SHOW_ALL
,
11152 use_json(argc
, argv
));
11155 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11156 safi_t safi
, enum bgp_show_adj_route_type type
,
11157 const char *rmap_name
, bool use_json
,
11160 struct bgp_table
*table
;
11161 struct bgp_adj_in
*ain
;
11162 struct bgp_adj_out
*adj
;
11163 unsigned long output_count
;
11164 unsigned long filtered_count
;
11165 struct bgp_node
*rn
;
11171 struct update_subgroup
*subgrp
;
11172 json_object
*json_scode
= NULL
;
11173 json_object
*json_ocode
= NULL
;
11174 json_object
*json_ar
= NULL
;
11175 struct peer_af
*paf
;
11176 bool route_filtered
;
11179 json_scode
= json_object_new_object();
11180 json_ocode
= json_object_new_object();
11181 json_ar
= json_object_new_object();
11183 json_object_string_add(json_scode
, "suppressed", "s");
11184 json_object_string_add(json_scode
, "damped", "d");
11185 json_object_string_add(json_scode
, "history", "h");
11186 json_object_string_add(json_scode
, "valid", "*");
11187 json_object_string_add(json_scode
, "best", ">");
11188 json_object_string_add(json_scode
, "multipath", "=");
11189 json_object_string_add(json_scode
, "internal", "i");
11190 json_object_string_add(json_scode
, "ribFailure", "r");
11191 json_object_string_add(json_scode
, "stale", "S");
11192 json_object_string_add(json_scode
, "removed", "R");
11194 json_object_string_add(json_ocode
, "igp", "i");
11195 json_object_string_add(json_ocode
, "egp", "e");
11196 json_object_string_add(json_ocode
, "incomplete", "?");
11203 json_object_string_add(json
, "alert", "no BGP");
11204 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11205 json_object_free(json
);
11207 vty_out(vty
, "%% No bgp\n");
11211 /* labeled-unicast routes live in the unicast table */
11212 if (safi
== SAFI_LABELED_UNICAST
)
11213 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11215 table
= bgp
->rib
[afi
][safi
];
11217 output_count
= filtered_count
= 0;
11218 subgrp
= peer_subgroup(peer
, afi
, safi
);
11220 if (type
== bgp_show_adj_route_advertised
&& subgrp
11221 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11223 json_object_int_add(json
, "bgpTableVersion",
11225 json_object_string_add(json
, "bgpLocalRouterId",
11226 inet_ntoa(bgp
->router_id
));
11227 json_object_int_add(json
, "defaultLocPrf",
11228 bgp
->default_local_pref
);
11229 json_object_int_add(json
, "localAS", bgp
->as
);
11230 json_object_object_add(json
, "bgpStatusCodes",
11232 json_object_object_add(json
, "bgpOriginCodes",
11234 json_object_string_add(
11235 json
, "bgpOriginatingDefaultNetwork",
11236 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11238 vty_out(vty
, "BGP table version is %" PRIu64
11239 ", local router ID is %s, vrf id ",
11240 table
->version
, inet_ntoa(bgp
->router_id
));
11241 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11242 vty_out(vty
, "%s", VRFID_NONE_STR
);
11244 vty_out(vty
, "%u", bgp
->vrf_id
);
11245 vty_out(vty
, "\n");
11246 vty_out(vty
, "Default local pref %u, ",
11247 bgp
->default_local_pref
);
11248 vty_out(vty
, "local AS %u\n", bgp
->as
);
11249 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11250 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11251 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11253 vty_out(vty
, "Originating default network %s\n\n",
11254 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11259 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11260 if (type
== bgp_show_adj_route_received
11261 || type
== bgp_show_adj_route_filtered
) {
11262 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11263 if (ain
->peer
!= peer
)
11268 json_object_int_add(
11269 json
, "bgpTableVersion",
11271 json_object_string_add(
11273 "bgpLocalRouterId",
11276 json_object_int_add(json
,
11278 bgp
->default_local_pref
);
11279 json_object_int_add(json
,
11280 "localAS", bgp
->as
);
11281 json_object_object_add(
11282 json
, "bgpStatusCodes",
11284 json_object_object_add(
11285 json
, "bgpOriginCodes",
11289 "BGP table version is 0, local router ID is %s, vrf id ",
11292 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11298 vty_out(vty
, "\n");
11300 "Default local pref %u, ",
11301 bgp
->default_local_pref
);
11302 vty_out(vty
, "local AS %u\n",
11305 BGP_SHOW_SCODE_HEADER
);
11307 BGP_SHOW_NCODE_HEADER
);
11309 BGP_SHOW_OCODE_HEADER
);
11315 vty_out(vty
, BGP_SHOW_HEADER
);
11319 bgp_attr_dup(&attr
, ain
->attr
);
11320 route_filtered
= false;
11322 /* Filter prefix using distribute list,
11323 * filter list or prefix list
11325 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11326 safi
)) == FILTER_DENY
)
11327 route_filtered
= true;
11329 /* Filter prefix using route-map */
11330 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11331 afi
, safi
, rmap_name
, NULL
, 0,
11334 if (type
== bgp_show_adj_route_filtered
&&
11335 !route_filtered
&& ret
!= RMAP_DENY
) {
11336 bgp_attr_undup(&attr
, ain
->attr
);
11340 if (type
== bgp_show_adj_route_received
&&
11341 (route_filtered
|| ret
== RMAP_DENY
))
11344 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11345 use_json
, json_ar
);
11346 bgp_attr_undup(&attr
, ain
->attr
);
11349 } else if (type
== bgp_show_adj_route_advertised
) {
11350 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11351 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11352 if (paf
->peer
!= peer
|| !adj
->attr
)
11357 json_object_int_add(
11361 json_object_string_add(
11363 "bgpLocalRouterId",
11366 json_object_int_add(
11367 json
, "defaultLocPrf",
11368 bgp
->default_local_pref
11370 json_object_int_add(
11373 json_object_object_add(
11377 json_object_object_add(
11383 "BGP table version is %" PRIu64
11384 ", local router ID is %s, vrf id ",
11397 vty_out(vty
, "\n");
11399 "Default local pref %u, ",
11400 bgp
->default_local_pref
11406 BGP_SHOW_SCODE_HEADER
);
11408 BGP_SHOW_NCODE_HEADER
);
11410 BGP_SHOW_OCODE_HEADER
);
11421 bgp_attr_dup(&attr
, adj
->attr
);
11422 ret
= bgp_output_modifier(
11423 peer
, &rn
->p
, &attr
, afi
, safi
,
11426 if (ret
!= RMAP_DENY
) {
11427 route_vty_out_tmp(vty
, &rn
->p
,
11436 bgp_attr_undup(&attr
, adj
->attr
);
11442 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11443 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11444 json_object_int_add(json
, "filteredPrefixCounter",
11447 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11448 json
, JSON_C_TO_STRING_PRETTY
));
11449 json_object_free(json
);
11450 } else if (output_count
> 0) {
11451 if (filtered_count
> 0)
11453 "\nTotal number of prefixes %ld (%ld filtered)\n",
11454 output_count
, filtered_count
);
11456 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11461 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11462 safi_t safi
, enum bgp_show_adj_route_type type
,
11463 const char *rmap_name
, bool use_json
)
11465 json_object
*json
= NULL
;
11468 json
= json_object_new_object();
11470 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11472 json_object_string_add(
11474 "No such neighbor or address family");
11475 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11476 json_object_free(json
);
11478 vty_out(vty
, "%% No such neighbor or address family\n");
11480 return CMD_WARNING
;
11483 if ((type
== bgp_show_adj_route_received
11484 || type
== bgp_show_adj_route_filtered
)
11485 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11486 PEER_FLAG_SOFT_RECONFIG
)) {
11488 json_object_string_add(
11490 "Inbound soft reconfiguration not enabled");
11491 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11492 json_object_free(json
);
11495 "%% Inbound soft reconfiguration not enabled\n");
11497 return CMD_WARNING
;
11500 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11502 return CMD_SUCCESS
;
11505 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11506 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11507 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11508 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11512 BGP_INSTANCE_HELP_STR
11514 BGP_SAFI_WITH_LABEL_HELP_STR
11515 "Detailed information on TCP and BGP neighbor connections\n"
11516 "Neighbor to display information about\n"
11517 "Neighbor to display information about\n"
11518 "Neighbor on BGP configured interface\n"
11519 "Display the routes advertised to a BGP neighbor\n"
11520 "Display the received routes from neighbor\n"
11521 "Display the filtered routes received from neighbor\n"
11522 "Route-map to modify the attributes\n"
11523 "Name of the route map\n"
11526 afi_t afi
= AFI_IP6
;
11527 safi_t safi
= SAFI_UNICAST
;
11528 char *rmap_name
= NULL
;
11529 char *peerstr
= NULL
;
11530 struct bgp
*bgp
= NULL
;
11532 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11534 bool uj
= use_json(argc
, argv
);
11539 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11542 return CMD_WARNING
;
11544 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11545 argv_find(argv
, argc
, "neighbors", &idx
);
11546 peerstr
= argv
[++idx
]->arg
;
11548 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11550 return CMD_WARNING
;
11552 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11553 type
= bgp_show_adj_route_advertised
;
11554 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11555 type
= bgp_show_adj_route_received
;
11556 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11557 type
= bgp_show_adj_route_filtered
;
11559 if (argv_find(argv
, argc
, "route-map", &idx
))
11560 rmap_name
= argv
[++idx
]->arg
;
11562 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11565 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11566 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11567 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11573 "Address Family modifier\n"
11574 "Detailed information on TCP and BGP neighbor connections\n"
11575 "Neighbor to display information about\n"
11576 "Neighbor to display information about\n"
11577 "Neighbor on BGP configured interface\n"
11578 "Display information received from a BGP neighbor\n"
11579 "Display the prefixlist filter\n"
11582 afi_t afi
= AFI_IP6
;
11583 safi_t safi
= SAFI_UNICAST
;
11584 char *peerstr
= NULL
;
11587 union sockunion su
;
11593 /* show [ip] bgp */
11594 if (argv_find(argv
, argc
, "ip", &idx
))
11596 /* [<ipv4|ipv6> [unicast]] */
11597 if (argv_find(argv
, argc
, "ipv4", &idx
))
11599 if (argv_find(argv
, argc
, "ipv6", &idx
))
11601 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11602 argv_find(argv
, argc
, "neighbors", &idx
);
11603 peerstr
= argv
[++idx
]->arg
;
11605 bool uj
= use_json(argc
, argv
);
11607 ret
= str2sockunion(peerstr
, &su
);
11609 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11612 vty_out(vty
, "{}\n");
11615 "%% Malformed address or name: %s\n",
11617 return CMD_WARNING
;
11620 peer
= peer_lookup(NULL
, &su
);
11623 vty_out(vty
, "{}\n");
11625 vty_out(vty
, "No peer\n");
11626 return CMD_WARNING
;
11630 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11631 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11634 vty_out(vty
, "Address Family: %s\n",
11635 get_afi_safi_str(afi
, safi
, false));
11636 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11639 vty_out(vty
, "{}\n");
11641 vty_out(vty
, "No functional output\n");
11644 return CMD_SUCCESS
;
11647 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11648 afi_t afi
, safi_t safi
,
11649 enum bgp_show_type type
, bool use_json
)
11651 /* labeled-unicast routes live in the unicast table */
11652 if (safi
== SAFI_LABELED_UNICAST
)
11653 safi
= SAFI_UNICAST
;
11655 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11657 json_object
*json_no
= NULL
;
11658 json_no
= json_object_new_object();
11659 json_object_string_add(
11660 json_no
, "warning",
11661 "No such neighbor or address family");
11662 vty_out(vty
, "%s\n",
11663 json_object_to_json_string(json_no
));
11664 json_object_free(json_no
);
11666 vty_out(vty
, "%% No such neighbor or address family\n");
11667 return CMD_WARNING
;
11670 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11673 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11674 show_ip_bgp_flowspec_routes_detailed_cmd
,
11675 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11679 BGP_INSTANCE_HELP_STR
11682 "Detailed information on flowspec entries\n"
11685 afi_t afi
= AFI_IP
;
11686 safi_t safi
= SAFI_UNICAST
;
11687 struct bgp
*bgp
= NULL
;
11689 bool uj
= use_json(argc
, argv
);
11694 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11697 return CMD_WARNING
;
11699 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11702 DEFUN (show_ip_bgp_neighbor_routes
,
11703 show_ip_bgp_neighbor_routes_cmd
,
11704 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11705 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11709 BGP_INSTANCE_HELP_STR
11711 BGP_SAFI_WITH_LABEL_HELP_STR
11712 "Detailed information on TCP and BGP neighbor connections\n"
11713 "Neighbor to display information about\n"
11714 "Neighbor to display information about\n"
11715 "Neighbor on BGP configured interface\n"
11716 "Display flap statistics of the routes learned from neighbor\n"
11717 "Display the dampened routes received from neighbor\n"
11718 "Display routes learned from neighbor\n"
11721 char *peerstr
= NULL
;
11722 struct bgp
*bgp
= NULL
;
11723 afi_t afi
= AFI_IP6
;
11724 safi_t safi
= SAFI_UNICAST
;
11726 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11728 bool uj
= use_json(argc
, argv
);
11733 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11736 return CMD_WARNING
;
11738 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11739 argv_find(argv
, argc
, "neighbors", &idx
);
11740 peerstr
= argv
[++idx
]->arg
;
11742 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11744 return CMD_WARNING
;
11746 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11747 sh_type
= bgp_show_type_flap_neighbor
;
11748 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11749 sh_type
= bgp_show_type_damp_neighbor
;
11750 else if (argv_find(argv
, argc
, "routes", &idx
))
11751 sh_type
= bgp_show_type_neighbor
;
11753 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11756 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11758 struct bgp_distance
{
11759 /* Distance value for the IP source prefix. */
11762 /* Name of the access-list to be matched. */
11766 DEFUN (show_bgp_afi_vpn_rd_route
,
11767 show_bgp_afi_vpn_rd_route_cmd
,
11768 "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]",
11772 "Address Family modifier\n"
11773 "Display information for a route distinguisher\n"
11774 "Route Distinguisher\n"
11775 "Network in the BGP routing table to display\n"
11776 "Network in the BGP routing table to display\n"
11780 struct prefix_rd prd
;
11781 afi_t afi
= AFI_MAX
;
11784 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11785 vty_out(vty
, "%% Malformed Address Family\n");
11786 return CMD_WARNING
;
11789 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11791 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11792 return CMD_WARNING
;
11795 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11796 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11799 static struct bgp_distance
*bgp_distance_new(void)
11801 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11804 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11806 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11809 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11810 const char *ip_str
, const char *access_list_str
)
11817 struct bgp_node
*rn
;
11818 struct bgp_distance
*bdistance
;
11820 afi
= bgp_node_afi(vty
);
11821 safi
= bgp_node_safi(vty
);
11823 ret
= str2prefix(ip_str
, &p
);
11825 vty_out(vty
, "Malformed prefix\n");
11826 return CMD_WARNING_CONFIG_FAILED
;
11829 distance
= atoi(distance_str
);
11831 /* Get BGP distance node. */
11832 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11833 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11835 bgp_unlock_node(rn
);
11837 bdistance
= bgp_distance_new();
11838 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11841 /* Set distance value. */
11842 bdistance
->distance
= distance
;
11844 /* Reset access-list configuration. */
11845 if (bdistance
->access_list
) {
11846 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11847 bdistance
->access_list
= NULL
;
11849 if (access_list_str
)
11850 bdistance
->access_list
=
11851 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11853 return CMD_SUCCESS
;
11856 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11857 const char *ip_str
, const char *access_list_str
)
11864 struct bgp_node
*rn
;
11865 struct bgp_distance
*bdistance
;
11867 afi
= bgp_node_afi(vty
);
11868 safi
= bgp_node_safi(vty
);
11870 ret
= str2prefix(ip_str
, &p
);
11872 vty_out(vty
, "Malformed prefix\n");
11873 return CMD_WARNING_CONFIG_FAILED
;
11876 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11877 (struct prefix
*)&p
);
11879 vty_out(vty
, "Can't find specified prefix\n");
11880 return CMD_WARNING_CONFIG_FAILED
;
11883 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11884 distance
= atoi(distance_str
);
11886 if (bdistance
->distance
!= distance
) {
11887 vty_out(vty
, "Distance does not match configured\n");
11888 return CMD_WARNING_CONFIG_FAILED
;
11891 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11892 bgp_distance_free(bdistance
);
11894 bgp_node_set_bgp_path_info(rn
, NULL
);
11895 bgp_unlock_node(rn
);
11896 bgp_unlock_node(rn
);
11898 return CMD_SUCCESS
;
11901 /* Apply BGP information to distance method. */
11902 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11903 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11905 struct bgp_node
*rn
;
11908 struct bgp_distance
*bdistance
;
11909 struct access_list
*alist
;
11910 struct bgp_static
*bgp_static
;
11915 peer
= pinfo
->peer
;
11917 if (pinfo
->attr
->distance
)
11918 return pinfo
->attr
->distance
;
11920 /* Check source address. */
11921 sockunion2hostprefix(&peer
->su
, &q
);
11922 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11924 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11925 bgp_unlock_node(rn
);
11927 if (bdistance
->access_list
) {
11928 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11930 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11931 return bdistance
->distance
;
11933 return bdistance
->distance
;
11936 /* Backdoor check. */
11937 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11939 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11940 bgp_unlock_node(rn
);
11942 if (bgp_static
->backdoor
) {
11943 if (bgp
->distance_local
[afi
][safi
])
11944 return bgp
->distance_local
[afi
][safi
];
11946 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11950 if (peer
->sort
== BGP_PEER_EBGP
) {
11951 if (bgp
->distance_ebgp
[afi
][safi
])
11952 return bgp
->distance_ebgp
[afi
][safi
];
11953 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11955 if (bgp
->distance_ibgp
[afi
][safi
])
11956 return bgp
->distance_ibgp
[afi
][safi
];
11957 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11961 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
11962 * we should tell ZEBRA update the routes for a specific
11963 * AFI/SAFI to reflect changes in RIB.
11965 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
11967 safi_t update_safi
)
11972 FOREACH_AFI_SAFI (afi
, safi
) {
11973 if (!bgp_fibupd_safi(safi
))
11976 if (afi
!= update_afi
&& safi
!= update_safi
)
11979 if (BGP_DEBUG(zebra
, ZEBRA
))
11981 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
11982 __func__
, afi
, safi
);
11983 bgp_zebra_announce_table(bgp
, afi
, safi
);
11987 DEFUN (bgp_distance
,
11989 "distance bgp (1-255) (1-255) (1-255)",
11990 "Define an administrative distance\n"
11992 "Distance for routes external to the AS\n"
11993 "Distance for routes internal to the AS\n"
11994 "Distance for local routes\n")
11996 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11997 int idx_number
= 2;
11998 int idx_number_2
= 3;
11999 int idx_number_3
= 4;
12000 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
12001 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
12002 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
12006 afi
= bgp_node_afi(vty
);
12007 safi
= bgp_node_safi(vty
);
12009 if (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
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
12013 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
12014 bgp
->distance_local
[afi
][safi
] = distance_local
;
12015 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12017 return CMD_SUCCESS
;
12020 DEFUN (no_bgp_distance
,
12021 no_bgp_distance_cmd
,
12022 "no distance bgp [(1-255) (1-255) (1-255)]",
12024 "Define an administrative distance\n"
12026 "Distance for routes external to the AS\n"
12027 "Distance for routes internal to the AS\n"
12028 "Distance for local routes\n")
12030 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12034 afi
= bgp_node_afi(vty
);
12035 safi
= bgp_node_safi(vty
);
12037 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12038 || bgp
->distance_ibgp
[afi
][safi
] != 0
12039 || bgp
->distance_local
[afi
][safi
] != 0) {
12040 bgp
->distance_ebgp
[afi
][safi
] = 0;
12041 bgp
->distance_ibgp
[afi
][safi
] = 0;
12042 bgp
->distance_local
[afi
][safi
] = 0;
12043 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12045 return CMD_SUCCESS
;
12049 DEFUN (bgp_distance_source
,
12050 bgp_distance_source_cmd
,
12051 "distance (1-255) A.B.C.D/M",
12052 "Define an administrative distance\n"
12053 "Administrative distance\n"
12054 "IP source prefix\n")
12056 int idx_number
= 1;
12057 int idx_ipv4_prefixlen
= 2;
12058 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12059 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12060 return CMD_SUCCESS
;
12063 DEFUN (no_bgp_distance_source
,
12064 no_bgp_distance_source_cmd
,
12065 "no distance (1-255) A.B.C.D/M",
12067 "Define an administrative distance\n"
12068 "Administrative distance\n"
12069 "IP source prefix\n")
12071 int idx_number
= 2;
12072 int idx_ipv4_prefixlen
= 3;
12073 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12074 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12075 return CMD_SUCCESS
;
12078 DEFUN (bgp_distance_source_access_list
,
12079 bgp_distance_source_access_list_cmd
,
12080 "distance (1-255) A.B.C.D/M WORD",
12081 "Define an administrative distance\n"
12082 "Administrative distance\n"
12083 "IP source prefix\n"
12084 "Access list name\n")
12086 int idx_number
= 1;
12087 int idx_ipv4_prefixlen
= 2;
12089 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12090 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12091 return CMD_SUCCESS
;
12094 DEFUN (no_bgp_distance_source_access_list
,
12095 no_bgp_distance_source_access_list_cmd
,
12096 "no distance (1-255) A.B.C.D/M WORD",
12098 "Define an administrative distance\n"
12099 "Administrative distance\n"
12100 "IP source prefix\n"
12101 "Access list name\n")
12103 int idx_number
= 2;
12104 int idx_ipv4_prefixlen
= 3;
12106 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12107 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12108 return CMD_SUCCESS
;
12111 DEFUN (ipv6_bgp_distance_source
,
12112 ipv6_bgp_distance_source_cmd
,
12113 "distance (1-255) X:X::X:X/M",
12114 "Define an administrative distance\n"
12115 "Administrative distance\n"
12116 "IP source prefix\n")
12118 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12119 return CMD_SUCCESS
;
12122 DEFUN (no_ipv6_bgp_distance_source
,
12123 no_ipv6_bgp_distance_source_cmd
,
12124 "no distance (1-255) X:X::X:X/M",
12126 "Define an administrative distance\n"
12127 "Administrative distance\n"
12128 "IP source prefix\n")
12130 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12131 return CMD_SUCCESS
;
12134 DEFUN (ipv6_bgp_distance_source_access_list
,
12135 ipv6_bgp_distance_source_access_list_cmd
,
12136 "distance (1-255) X:X::X:X/M WORD",
12137 "Define an administrative distance\n"
12138 "Administrative distance\n"
12139 "IP source prefix\n"
12140 "Access list name\n")
12142 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12143 return CMD_SUCCESS
;
12146 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12147 no_ipv6_bgp_distance_source_access_list_cmd
,
12148 "no distance (1-255) X:X::X:X/M WORD",
12150 "Define an administrative distance\n"
12151 "Administrative distance\n"
12152 "IP source prefix\n"
12153 "Access list name\n")
12155 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12156 return CMD_SUCCESS
;
12159 DEFUN (bgp_damp_set
,
12161 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12162 "BGP Specific commands\n"
12163 "Enable route-flap dampening\n"
12164 "Half-life time for the penalty\n"
12165 "Value to start reusing a route\n"
12166 "Value to start suppressing a route\n"
12167 "Maximum duration to suppress a stable route\n")
12169 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12170 int idx_half_life
= 2;
12172 int idx_suppress
= 4;
12173 int idx_max_suppress
= 5;
12174 int half
= DEFAULT_HALF_LIFE
* 60;
12175 int reuse
= DEFAULT_REUSE
;
12176 int suppress
= DEFAULT_SUPPRESS
;
12177 int max
= 4 * half
;
12180 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12181 reuse
= atoi(argv
[idx_reuse
]->arg
);
12182 suppress
= atoi(argv
[idx_suppress
]->arg
);
12183 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12184 } else if (argc
== 3) {
12185 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12190 * These can't be 0 but our SA doesn't understand the
12191 * way our cli is constructed
12195 if (suppress
< reuse
) {
12197 "Suppress value cannot be less than reuse value \n");
12201 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12202 reuse
, suppress
, max
);
12205 DEFUN (bgp_damp_unset
,
12206 bgp_damp_unset_cmd
,
12207 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12209 "BGP Specific commands\n"
12210 "Enable route-flap dampening\n"
12211 "Half-life time for the penalty\n"
12212 "Value to start reusing a route\n"
12213 "Value to start suppressing a route\n"
12214 "Maximum duration to suppress a stable route\n")
12216 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12217 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12220 /* Display specified route of BGP table. */
12221 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12222 const char *ip_str
, afi_t afi
, safi_t safi
,
12223 struct prefix_rd
*prd
, int prefix_check
)
12226 struct prefix match
;
12227 struct bgp_node
*rn
;
12228 struct bgp_node
*rm
;
12229 struct bgp_path_info
*pi
;
12230 struct bgp_path_info
*pi_temp
;
12232 struct bgp_table
*table
;
12234 /* BGP structure lookup. */
12236 bgp
= bgp_lookup_by_name(view_name
);
12238 vty_out(vty
, "%% Can't find BGP instance %s\n",
12240 return CMD_WARNING
;
12243 bgp
= bgp_get_default();
12245 vty_out(vty
, "%% No BGP process is configured\n");
12246 return CMD_WARNING
;
12250 /* Check IP address argument. */
12251 ret
= str2prefix(ip_str
, &match
);
12253 vty_out(vty
, "%% address is malformed\n");
12254 return CMD_WARNING
;
12257 match
.family
= afi2family(afi
);
12259 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12260 || (safi
== SAFI_EVPN
)) {
12261 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12262 rn
= bgp_route_next(rn
)) {
12263 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12265 table
= bgp_node_get_bgp_table_info(rn
);
12268 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12272 || rm
->p
.prefixlen
== match
.prefixlen
) {
12273 pi
= bgp_node_get_bgp_path_info(rm
);
12275 if (pi
->extra
&& pi
->extra
->damp_info
) {
12276 pi_temp
= pi
->next
;
12277 bgp_damp_info_free(
12278 pi
->extra
->damp_info
,
12286 bgp_unlock_node(rm
);
12289 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12292 || rn
->p
.prefixlen
== match
.prefixlen
) {
12293 pi
= bgp_node_get_bgp_path_info(rn
);
12295 if (pi
->extra
&& pi
->extra
->damp_info
) {
12296 pi_temp
= pi
->next
;
12297 bgp_damp_info_free(
12298 pi
->extra
->damp_info
,
12306 bgp_unlock_node(rn
);
12310 return CMD_SUCCESS
;
12313 DEFUN (clear_ip_bgp_dampening
,
12314 clear_ip_bgp_dampening_cmd
,
12315 "clear ip bgp dampening",
12319 "Clear route flap dampening information\n")
12321 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
12322 return CMD_SUCCESS
;
12325 DEFUN (clear_ip_bgp_dampening_prefix
,
12326 clear_ip_bgp_dampening_prefix_cmd
,
12327 "clear ip bgp dampening A.B.C.D/M",
12331 "Clear route flap dampening information\n"
12334 int idx_ipv4_prefixlen
= 4;
12335 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12336 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12339 DEFUN (clear_ip_bgp_dampening_address
,
12340 clear_ip_bgp_dampening_address_cmd
,
12341 "clear ip bgp dampening A.B.C.D",
12345 "Clear route flap dampening information\n"
12346 "Network to clear damping information\n")
12349 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12350 SAFI_UNICAST
, NULL
, 0);
12353 DEFUN (clear_ip_bgp_dampening_address_mask
,
12354 clear_ip_bgp_dampening_address_mask_cmd
,
12355 "clear ip bgp dampening A.B.C.D A.B.C.D",
12359 "Clear route flap dampening information\n"
12360 "Network to clear damping information\n"
12364 int idx_ipv4_2
= 5;
12366 char prefix_str
[BUFSIZ
];
12368 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12371 vty_out(vty
, "%% Inconsistent address and mask\n");
12372 return CMD_WARNING
;
12375 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12379 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12381 struct vty
*vty
= arg
;
12382 struct peer
*peer
= bucket
->data
;
12383 char buf
[SU_ADDRSTRLEN
];
12385 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12386 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12389 DEFUN (show_bgp_peerhash
,
12390 show_bgp_peerhash_cmd
,
12391 "show bgp peerhash",
12394 "Display information about the BGP peerhash\n")
12396 struct list
*instances
= bm
->bgp
;
12397 struct listnode
*node
;
12400 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12401 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12402 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12406 return CMD_SUCCESS
;
12409 /* also used for encap safi */
12410 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12411 afi_t afi
, safi_t safi
)
12413 struct bgp_node
*prn
;
12414 struct bgp_node
*rn
;
12415 struct bgp_table
*table
;
12417 struct prefix_rd
*prd
;
12418 struct bgp_static
*bgp_static
;
12419 mpls_label_t label
;
12420 char buf
[SU_ADDRSTRLEN
];
12421 char rdbuf
[RD_ADDRSTRLEN
];
12423 /* Network configuration. */
12424 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12425 prn
= bgp_route_next(prn
)) {
12426 table
= bgp_node_get_bgp_table_info(prn
);
12430 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12431 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12432 if (bgp_static
== NULL
)
12436 prd
= (struct prefix_rd
*)&prn
->p
;
12438 /* "network" configuration display. */
12439 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12440 label
= decode_label(&bgp_static
->label
);
12442 vty_out(vty
, " network %s/%d rd %s",
12443 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12445 p
->prefixlen
, rdbuf
);
12446 if (safi
== SAFI_MPLS_VPN
)
12447 vty_out(vty
, " label %u", label
);
12449 if (bgp_static
->rmap
.name
)
12450 vty_out(vty
, " route-map %s",
12451 bgp_static
->rmap
.name
);
12453 if (bgp_static
->backdoor
)
12454 vty_out(vty
, " backdoor");
12456 vty_out(vty
, "\n");
12461 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12462 afi_t afi
, safi_t safi
)
12464 struct bgp_node
*prn
;
12465 struct bgp_node
*rn
;
12466 struct bgp_table
*table
;
12468 struct prefix_rd
*prd
;
12469 struct bgp_static
*bgp_static
;
12470 char buf
[PREFIX_STRLEN
* 2];
12471 char buf2
[SU_ADDRSTRLEN
];
12472 char rdbuf
[RD_ADDRSTRLEN
];
12474 /* Network configuration. */
12475 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12476 prn
= bgp_route_next(prn
)) {
12477 table
= bgp_node_get_bgp_table_info(prn
);
12481 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12482 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12483 if (bgp_static
== NULL
)
12486 char *macrouter
= NULL
;
12489 if (bgp_static
->router_mac
)
12490 macrouter
= prefix_mac2str(
12491 bgp_static
->router_mac
, NULL
, 0);
12492 if (bgp_static
->eth_s_id
)
12493 esi
= esi2str(bgp_static
->eth_s_id
);
12495 prd
= (struct prefix_rd
*)&prn
->p
;
12497 /* "network" configuration display. */
12498 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12499 if (p
->u
.prefix_evpn
.route_type
== 5) {
12500 char local_buf
[PREFIX_STRLEN
];
12501 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12502 struct prefix_evpn
*)p
)
12506 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12507 local_buf
, PREFIX_STRLEN
);
12508 sprintf(buf
, "%s/%u", local_buf
,
12509 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12511 prefix2str(p
, buf
, sizeof(buf
));
12514 if (bgp_static
->gatewayIp
.family
== AF_INET
12515 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12516 inet_ntop(bgp_static
->gatewayIp
.family
,
12517 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12520 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12522 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12523 decode_label(&bgp_static
->label
), esi
, buf2
,
12526 XFREE(MTYPE_TMP
, macrouter
);
12527 XFREE(MTYPE_TMP
, esi
);
12532 /* Configuration of static route announcement and aggregate
12534 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12537 struct bgp_node
*rn
;
12539 struct bgp_static
*bgp_static
;
12540 struct bgp_aggregate
*bgp_aggregate
;
12541 char buf
[SU_ADDRSTRLEN
];
12543 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12544 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12548 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12549 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12553 /* Network configuration. */
12554 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12555 rn
= bgp_route_next(rn
)) {
12556 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12557 if (bgp_static
== NULL
)
12562 vty_out(vty
, " network %s/%d",
12563 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12566 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12567 vty_out(vty
, " label-index %u",
12568 bgp_static
->label_index
);
12570 if (bgp_static
->rmap
.name
)
12571 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12573 if (bgp_static
->backdoor
)
12574 vty_out(vty
, " backdoor");
12576 vty_out(vty
, "\n");
12579 /* Aggregate-address configuration. */
12580 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12581 rn
= bgp_route_next(rn
)) {
12582 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12583 if (bgp_aggregate
== NULL
)
12588 vty_out(vty
, " aggregate-address %s/%d",
12589 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12592 if (bgp_aggregate
->as_set
)
12593 vty_out(vty
, " as-set");
12595 if (bgp_aggregate
->summary_only
)
12596 vty_out(vty
, " summary-only");
12598 if (bgp_aggregate
->rmap
.name
)
12599 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12601 vty_out(vty
, "\n");
12605 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12608 struct bgp_node
*rn
;
12609 struct bgp_distance
*bdistance
;
12611 /* Distance configuration. */
12612 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12613 && bgp
->distance_local
[afi
][safi
]
12614 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12615 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12616 || bgp
->distance_local
[afi
][safi
]
12617 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12618 vty_out(vty
, " distance bgp %d %d %d\n",
12619 bgp
->distance_ebgp
[afi
][safi
],
12620 bgp
->distance_ibgp
[afi
][safi
],
12621 bgp
->distance_local
[afi
][safi
]);
12624 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12625 rn
= bgp_route_next(rn
)) {
12626 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12627 if (bdistance
!= NULL
) {
12628 char buf
[PREFIX_STRLEN
];
12630 vty_out(vty
, " distance %d %s %s\n",
12631 bdistance
->distance
,
12632 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12633 bdistance
->access_list
? bdistance
->access_list
12639 /* Allocate routing table structure and install commands. */
12640 void bgp_route_init(void)
12645 /* Init BGP distance table. */
12646 FOREACH_AFI_SAFI (afi
, safi
)
12647 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12649 /* IPv4 BGP commands. */
12650 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12651 install_element(BGP_NODE
, &bgp_network_cmd
);
12652 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12654 install_element(BGP_NODE
, &aggregate_address_cmd
);
12655 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12656 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12657 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12659 /* IPv4 unicast configuration. */
12660 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12661 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12662 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12664 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12665 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12666 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12667 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12669 /* IPv4 multicast configuration. */
12670 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12671 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12672 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12673 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12674 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12675 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12676 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12678 /* IPv4 labeled-unicast configuration. */
12679 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12680 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12681 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12682 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12683 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12685 install_element(VIEW_NODE
,
12686 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12687 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12688 install_element(VIEW_NODE
,
12689 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12690 #ifdef KEEP_OLD_VPN_COMMANDS
12691 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12692 #endif /* KEEP_OLD_VPN_COMMANDS */
12693 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12694 install_element(VIEW_NODE
,
12695 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
12697 /* BGP dampening clear commands */
12698 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12699 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12701 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12702 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12705 install_element(ENABLE_NODE
,
12706 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12707 #ifdef KEEP_OLD_VPN_COMMANDS
12708 install_element(ENABLE_NODE
,
12709 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12710 #endif /* KEEP_OLD_VPN_COMMANDS */
12712 /* New config IPv6 BGP commands. */
12713 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12714 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12715 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12717 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12718 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12720 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12722 install_element(BGP_NODE
, &bgp_distance_cmd
);
12723 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12724 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12725 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12726 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12727 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12728 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12729 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12730 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12731 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12732 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12733 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12734 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12735 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12736 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12737 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12738 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12739 install_element(BGP_IPV4M_NODE
,
12740 &no_bgp_distance_source_access_list_cmd
);
12741 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12742 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12743 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12744 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12745 install_element(BGP_IPV6_NODE
,
12746 &ipv6_bgp_distance_source_access_list_cmd
);
12747 install_element(BGP_IPV6_NODE
,
12748 &no_ipv6_bgp_distance_source_access_list_cmd
);
12749 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12750 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12751 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12752 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12753 install_element(BGP_IPV6M_NODE
,
12754 &ipv6_bgp_distance_source_access_list_cmd
);
12755 install_element(BGP_IPV6M_NODE
,
12756 &no_ipv6_bgp_distance_source_access_list_cmd
);
12758 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12759 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12760 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12761 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12763 /* IPv4 Multicast Mode */
12764 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12765 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12767 /* Large Communities */
12768 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12769 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12771 /* show bgp ipv4 flowspec detailed */
12772 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12774 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12777 void bgp_route_finish(void)
12782 FOREACH_AFI_SAFI (afi
, safi
) {
12783 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12784 bgp_distance_table
[afi
][safi
] = NULL
;