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);
203 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
206 /* FIXME: since multiple e may have the same e->parent
207 * and e->parent->net is holding a refcount for each
208 * of them, we need to do some fudging here.
210 * WARNING: if bpi->net->lock drops to 0, bpi may be
211 * freed as well (because bpi->net was holding the
212 * last reference to bpi) => write after free!
216 bpi
= bgp_path_info_lock(bpi
);
217 refcount
= bpi
->net
->lock
- 1;
218 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
221 bgp_path_info_unlock(bpi
);
223 bgp_path_info_unlock(e
->parent
);
228 bgp_unlock(e
->bgp_orig
);
230 if ((*extra
)->bgp_fs_iprule
)
231 list_delete(&((*extra
)->bgp_fs_iprule
));
232 if ((*extra
)->bgp_fs_pbr
)
233 list_delete(&((*extra
)->bgp_fs_pbr
));
234 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
239 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
240 * allocated if required.
242 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
245 pi
->extra
= bgp_path_info_extra_new();
249 /* Free bgp route information. */
250 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
)
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
;
1282 extra
.num_labels
= num_labels
;
1283 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1284 memcpy(extra
.label
, label
,
1285 num_labels
* sizeof(mpls_label_t
));
1287 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1289 /* Apply BGP route map to the attribute. */
1290 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1292 peer
->rmap_type
= 0;
1294 if (ret
== RMAP_DENYMATCH
)
1300 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1301 struct attr
*attr
, afi_t afi
, safi_t safi
,
1302 const char *rmap_name
)
1304 struct bgp_path_info rmap_path
;
1305 route_map_result_t ret
;
1306 struct route_map
*rmap
= NULL
;
1310 * So if we get to this point and have no rmap_name
1311 * we want to just show the output as it currently
1317 /* Apply default weight value. */
1318 if (peer
->weight
[afi
][safi
])
1319 attr
->weight
= peer
->weight
[afi
][safi
];
1321 rmap
= route_map_lookup_by_name(rmap_name
);
1324 * If we have a route map name and we do not find
1325 * the routemap that means we have an implicit
1331 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1332 /* Route map apply. */
1333 /* Duplicate current value to new strucutre for modification. */
1334 rmap_path
.peer
= peer
;
1335 rmap_path
.attr
= attr
;
1337 rmap_type
= peer
->rmap_type
;
1338 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1340 /* Apply BGP route map to the attribute. */
1341 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1343 peer
->rmap_type
= rmap_type
;
1345 if (ret
== RMAP_DENYMATCH
)
1347 * caller has multiple error paths with bgp_attr_flush()
1354 /* If this is an EBGP peer with remove-private-AS */
1355 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1356 struct peer
*peer
, struct attr
*attr
)
1358 if (peer
->sort
== BGP_PEER_EBGP
1359 && (peer_af_flag_check(peer
, afi
, safi
,
1360 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1361 || peer_af_flag_check(peer
, afi
, safi
,
1362 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1363 || peer_af_flag_check(peer
, afi
, safi
,
1364 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1365 || peer_af_flag_check(peer
, afi
, safi
,
1366 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1367 // Take action on the entire aspath
1368 if (peer_af_flag_check(peer
, afi
, safi
,
1369 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1370 || peer_af_flag_check(peer
, afi
, safi
,
1371 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1372 if (peer_af_flag_check(
1374 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1375 attr
->aspath
= aspath_replace_private_asns(
1376 attr
->aspath
, bgp
->as
, peer
->as
);
1378 // The entire aspath consists of private ASNs so create
1380 else if (aspath_private_as_check(attr
->aspath
))
1381 attr
->aspath
= aspath_empty_get();
1383 // There are some public and some private ASNs, remove
1386 attr
->aspath
= aspath_remove_private_asns(
1387 attr
->aspath
, peer
->as
);
1390 // 'all' was not specified so the entire aspath must be private
1392 // for us to do anything
1393 else if (aspath_private_as_check(attr
->aspath
)) {
1394 if (peer_af_flag_check(
1396 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1397 attr
->aspath
= aspath_replace_private_asns(
1398 attr
->aspath
, bgp
->as
, peer
->as
);
1400 attr
->aspath
= aspath_empty_get();
1405 /* If this is an EBGP peer with as-override */
1406 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1407 struct peer
*peer
, struct attr
*attr
)
1409 if (peer
->sort
== BGP_PEER_EBGP
1410 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1411 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1412 attr
->aspath
= aspath_replace_specific_asn(
1413 attr
->aspath
, peer
->as
, bgp
->as
);
1417 void bgp_attr_add_gshut_community(struct attr
*attr
)
1419 struct community
*old
;
1420 struct community
*new;
1421 struct community
*merge
;
1422 struct community
*gshut
;
1424 old
= attr
->community
;
1425 gshut
= community_str2com("graceful-shutdown");
1430 merge
= community_merge(community_dup(old
), gshut
);
1432 if (old
->refcnt
== 0)
1433 community_free(&old
);
1435 new = community_uniq_sort(merge
);
1436 community_free(&merge
);
1438 new = community_dup(gshut
);
1441 community_free(&gshut
);
1442 attr
->community
= new;
1443 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1445 /* When we add the graceful-shutdown community we must also
1446 * lower the local-preference */
1447 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1448 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1452 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1454 if (family
== AF_INET
) {
1455 attr
->nexthop
.s_addr
= 0;
1456 attr
->mp_nexthop_global_in
.s_addr
= 0;
1458 if (family
== AF_INET6
)
1459 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1460 if (family
== AF_EVPN
)
1461 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1464 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1465 struct update_subgroup
*subgrp
, struct prefix
*p
,
1468 struct bgp_filter
*filter
;
1471 struct peer
*onlypeer
;
1473 struct attr
*piattr
;
1474 char buf
[PREFIX_STRLEN
];
1475 route_map_result_t ret
;
1480 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1482 if (DISABLE_BGP_ANNOUNCE
)
1485 afi
= SUBGRP_AFI(subgrp
);
1486 safi
= SUBGRP_SAFI(subgrp
);
1487 peer
= SUBGRP_PEER(subgrp
);
1489 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1490 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1493 filter
= &peer
->filter
[afi
][safi
];
1494 bgp
= SUBGRP_INST(subgrp
);
1495 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1499 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1500 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1501 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1504 * direct and direct_ext type routes originate internally even
1505 * though they can have peer pointers that reference other
1508 prefix2str(p
, buf
, PREFIX_STRLEN
);
1509 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1515 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1516 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1517 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1518 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1520 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1525 /* With addpath we may be asked to TX all kinds of paths so make sure
1527 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1528 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1529 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1533 /* If this is not the bestpath then check to see if there is an enabled
1535 * feature that requires us to advertise it */
1536 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1537 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1542 /* Aggregate-address suppress check. */
1543 if (pi
->extra
&& pi
->extra
->suppress
)
1544 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1549 * If we are doing VRF 2 VRF leaking via the import
1550 * statement, we want to prevent the route going
1551 * off box as that the RT and RD created are localy
1552 * significant and globaly useless.
1554 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1555 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1558 /* If it's labeled safi, make sure the route has a valid label. */
1559 if (safi
== SAFI_LABELED_UNICAST
) {
1560 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1561 if (!bgp_is_valid_label(&label
)) {
1562 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1563 zlog_debug("u%" PRIu64
":s%" PRIu64
1564 " %s/%d is filtered - no label (%p)",
1565 subgrp
->update_group
->id
, subgrp
->id
,
1566 inet_ntop(p
->family
, &p
->u
.prefix
,
1567 buf
, SU_ADDRSTRLEN
),
1568 p
->prefixlen
, &label
);
1573 /* Do not send back route to sender. */
1574 if (onlypeer
&& from
== onlypeer
) {
1578 /* Do not send the default route in the BGP table if the neighbor is
1579 * configured for default-originate */
1580 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1581 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1582 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1584 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1588 /* Transparency check. */
1589 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1590 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1595 /* If community is not disabled check the no-export and local. */
1596 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1597 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1599 "subgrpannouncecheck: community filter check fail");
1603 /* If the attribute has originator-id and it is same as remote
1605 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1606 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1607 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1609 "%s [Update:SEND] %s originator-id is same as "
1612 prefix2str(p
, buf
, sizeof(buf
)));
1616 /* ORF prefix-list filter check */
1617 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1618 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1619 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1620 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1621 if (peer
->orf_plist
[afi
][safi
]) {
1622 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1624 if (bgp_debug_update(NULL
, p
,
1625 subgrp
->update_group
, 0))
1627 "%s [Update:SEND] %s is filtered via ORF",
1635 /* Output filter check. */
1636 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1637 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1638 zlog_debug("%s [Update:SEND] %s is filtered",
1639 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1643 #ifdef BGP_SEND_ASPATH_CHECK
1644 /* AS path loop check. */
1645 if (onlypeer
&& aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1646 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1648 "%s [Update:SEND] suppress announcement to peer AS %u "
1649 "that is part of AS path.",
1650 onlypeer
->host
, onlypeer
->as
);
1653 #endif /* BGP_SEND_ASPATH_CHECK */
1655 /* If we're a CONFED we need to loop check the CONFED ID too */
1656 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1657 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1658 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1660 "%s [Update:SEND] suppress announcement to peer AS %u"
1662 peer
->host
, bgp
->confed_id
);
1667 /* Route-Reflect check. */
1668 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1673 /* IBGP reflection check. */
1674 if (reflect
&& !samepeer_safe
) {
1675 /* A route from a Client peer. */
1676 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1677 PEER_FLAG_REFLECTOR_CLIENT
)) {
1678 /* Reflect to all the Non-Client peers and also to the
1679 Client peers other than the originator. Originator
1681 is already done. So there is noting to do. */
1682 /* no bgp client-to-client reflection check. */
1683 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1684 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1685 PEER_FLAG_REFLECTOR_CLIENT
))
1688 /* A route from a Non-client peer. Reflect to all other
1690 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1691 PEER_FLAG_REFLECTOR_CLIENT
))
1696 /* For modify attribute, copy it to temporary structure. */
1697 bgp_attr_dup(attr
, piattr
);
1699 /* If local-preference is not set. */
1700 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1701 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1702 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1703 attr
->local_pref
= bgp
->default_local_pref
;
1706 /* If originator-id is not set and the route is to be reflected,
1707 set the originator id */
1709 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1710 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1711 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1714 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1716 if (peer
->sort
== BGP_PEER_EBGP
1717 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1718 if (from
!= bgp
->peer_self
&& !transparent
1719 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1720 PEER_FLAG_MED_UNCHANGED
))
1722 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1725 /* Since the nexthop attribute can vary per peer, it is not explicitly
1727 * in announce check, only certain flags and length (or number of
1729 * -- for IPv6/MP_REACH) are set here in order to guide the update
1731 * code in setting the nexthop(s) on a per peer basis in
1733 * Typically, the source nexthop in the attribute is preserved but in
1735 * scenarios where we know it will always be overwritten, we reset the
1736 * nexthop to "0" in an attempt to achieve better Update packing. An
1737 * example of this is when a prefix from each of 2 IBGP peers needs to
1739 * announced to an EBGP peer (and they have the same attributes barring
1743 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1745 #define NEXTHOP_IS_V6 \
1746 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1747 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1748 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1749 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1751 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1753 * the peer (group) is configured to receive link-local nexthop
1755 * and it is available in the prefix OR we're not reflecting the route
1757 * the peer (group) to whom we're going to announce is on a shared
1759 * and this is either a self-originated route or the peer is EBGP.
1761 if (NEXTHOP_IS_V6
) {
1762 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1763 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1764 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1765 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1766 || (!reflect
&& peer
->shared_network
1767 && (from
== bgp
->peer_self
1768 || peer
->sort
== BGP_PEER_EBGP
))) {
1769 attr
->mp_nexthop_len
=
1770 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1773 /* Clear off link-local nexthop in source, whenever it is not
1775 * ensure more prefixes share the same attribute for
1778 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1779 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1780 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1783 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1784 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1786 /* Route map & unsuppress-map apply. */
1787 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1788 struct bgp_path_info rmap_path
;
1789 struct bgp_path_info_extra dummy_rmap_path_extra
;
1790 struct attr dummy_attr
;
1792 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1793 rmap_path
.peer
= peer
;
1794 rmap_path
.attr
= attr
;
1797 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1798 sizeof(struct bgp_path_info_extra
));
1799 rmap_path
.extra
= &dummy_rmap_path_extra
;
1802 /* don't confuse inbound and outbound setting */
1803 RESET_FLAG(attr
->rmap_change_flags
);
1806 * The route reflector is not allowed to modify the attributes
1807 * of the reflected IBGP routes unless explicitly allowed.
1809 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1810 && !bgp_flag_check(bgp
,
1811 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1812 bgp_attr_dup(&dummy_attr
, attr
);
1813 rmap_path
.attr
= &dummy_attr
;
1816 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1818 if (pi
->extra
&& pi
->extra
->suppress
)
1819 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1820 RMAP_BGP
, &rmap_path
);
1822 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1823 RMAP_BGP
, &rmap_path
);
1825 peer
->rmap_type
= 0;
1827 if (ret
== RMAP_DENYMATCH
) {
1828 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1829 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1830 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1832 bgp_attr_flush(attr
);
1837 /* RFC 8212 to prevent route leaks.
1838 * This specification intends to improve this situation by requiring the
1839 * explicit configuration of both BGP Import and Export Policies for any
1840 * External BGP (EBGP) session such as customers, peers, or
1841 * confederation boundaries for all enabled address families. Through
1842 * codification of the aforementioned requirement, operators will
1843 * benefit from consistent behavior across different BGP
1846 if (peer
->bgp
->ebgp_requires_policy
1847 == DEFAULT_EBGP_POLICY_ENABLED
)
1848 if (!bgp_outbound_policy_exists(peer
, filter
))
1851 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1852 if (peer
->sort
== BGP_PEER_IBGP
1853 || peer
->sort
== BGP_PEER_CONFED
) {
1854 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1855 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1857 bgp_attr_add_gshut_community(attr
);
1861 /* After route-map has been applied, we check to see if the nexthop to
1862 * be carried in the attribute (that is used for the announcement) can
1863 * be cleared off or not. We do this in all cases where we would be
1864 * setting the nexthop to "ourselves". For IPv6, we only need to
1866 * the global nexthop here; the link-local nexthop would have been
1868 * already, and if not, it is required by the update formation code.
1869 * Also see earlier comments in this function.
1872 * If route-map has performed some operation on the nexthop or the peer
1873 * configuration says to pass it unchanged, we cannot reset the nexthop
1874 * here, so only attempt to do it if these aren't true. Note that the
1875 * route-map handler itself might have cleared the nexthop, if for
1877 * it is configured as 'peer-address'.
1879 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1880 piattr
->rmap_change_flags
)
1882 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1883 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1884 /* We can reset the nexthop, if setting (or forcing) it to
1886 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1887 PEER_FLAG_NEXTHOP_SELF
)
1888 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1889 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1891 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1892 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1893 subgroup_announce_reset_nhop(
1894 (peer_cap_enhe(peer
, afi
, safi
)
1898 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1899 /* Can also reset the nexthop if announcing to EBGP, but
1901 * no peer in the subgroup is on a shared subnet.
1902 * Note: 3rd party nexthop currently implemented for
1905 if ((p
->family
== AF_INET
) &&
1906 (!bgp_subgrp_multiaccess_check_v4(
1909 subgroup_announce_reset_nhop(
1910 (peer_cap_enhe(peer
, afi
, safi
)
1915 if ((p
->family
== AF_INET6
) &&
1916 (!bgp_subgrp_multiaccess_check_v6(
1917 piattr
->mp_nexthop_global
,
1919 subgroup_announce_reset_nhop(
1920 (peer_cap_enhe(peer
, afi
, safi
)
1927 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1929 * This flag is used for leaked vpn-vrf routes
1931 int family
= p
->family
;
1933 if (peer_cap_enhe(peer
, afi
, safi
))
1936 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1938 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1939 __func__
, family2str(family
));
1940 subgroup_announce_reset_nhop(family
, attr
);
1943 /* If IPv6/MP and nexthop does not have any override and happens
1945 * be a link-local address, reset it so that we don't pass along
1947 * source's link-local IPv6 address to recipients who may not be
1949 * the same interface.
1951 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1952 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1953 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1960 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1961 struct bgp_maxpaths_cfg
*mpath_cfg
,
1962 struct bgp_path_info_pair
*result
, afi_t afi
,
1965 struct bgp_path_info
*new_select
;
1966 struct bgp_path_info
*old_select
;
1967 struct bgp_path_info
*pi
;
1968 struct bgp_path_info
*pi1
;
1969 struct bgp_path_info
*pi2
;
1970 struct bgp_path_info
*nextpi
= NULL
;
1971 int paths_eq
, do_mpath
, debug
;
1972 struct list mp_list
;
1973 char pfx_buf
[PREFIX2STR_BUFFER
];
1974 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1976 bgp_mp_list_init(&mp_list
);
1978 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1980 debug
= bgp_debug_bestpath(&rn
->p
);
1983 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1985 /* bgp deterministic-med */
1987 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1989 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1990 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1992 bgp_path_info_unset_flag(rn
, pi1
,
1993 BGP_PATH_DMED_SELECTED
);
1995 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1997 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1999 if (BGP_PATH_HOLDDOWN(pi1
))
2001 if (pi1
->peer
!= bgp
->peer_self
)
2002 if (pi1
->peer
->status
!= Established
)
2007 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2008 if (CHECK_FLAG(pi2
->flags
,
2009 BGP_PATH_DMED_CHECK
))
2011 if (BGP_PATH_HOLDDOWN(pi2
))
2013 if (pi2
->peer
!= bgp
->peer_self
2016 PEER_STATUS_NSF_WAIT
))
2017 if (pi2
->peer
->status
2021 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2023 && !aspath_cmp_left_confed(
2028 if (bgp_path_info_cmp(
2029 bgp
, pi2
, new_select
,
2030 &paths_eq
, mpath_cfg
, debug
,
2033 bgp_path_info_unset_flag(
2035 BGP_PATH_DMED_SELECTED
);
2039 bgp_path_info_set_flag(
2040 rn
, pi2
, BGP_PATH_DMED_CHECK
);
2043 bgp_path_info_set_flag(rn
, new_select
,
2044 BGP_PATH_DMED_CHECK
);
2045 bgp_path_info_set_flag(rn
, new_select
,
2046 BGP_PATH_DMED_SELECTED
);
2049 bgp_path_info_path_with_addpath_rx_str(
2050 new_select
, path_buf
);
2051 zlog_debug("%s: %s is the bestpath from AS %u",
2053 aspath_get_first_as(
2054 new_select
->attr
->aspath
));
2059 /* Check old selected route and new selected route. */
2062 for (pi
= bgp_node_get_bgp_path_info(rn
);
2063 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2064 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2067 if (BGP_PATH_HOLDDOWN(pi
)) {
2068 /* reap REMOVED routes, if needs be
2069 * selected route must stay for a while longer though
2071 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2072 && (pi
!= old_select
))
2073 bgp_path_info_reap(rn
, pi
);
2076 zlog_debug("%s: pi %p in holddown", __func__
,
2082 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2083 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2084 if (pi
->peer
->status
!= Established
) {
2088 "%s: pi %p non self peer %s not estab state",
2089 __func__
, pi
, pi
->peer
->host
);
2094 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2095 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2096 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2098 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2102 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2104 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2105 debug
, pfx_buf
, afi
, safi
, &rn
->reason
)) {
2110 /* Now that we know which path is the bestpath see if any of the other
2112 * qualify as multipaths
2116 bgp_path_info_path_with_addpath_rx_str(new_select
,
2119 sprintf(path_buf
, "NONE");
2121 "%s: After path selection, newbest is %s oldbest was %s",
2123 old_select
? old_select
->peer
->host
: "NONE");
2126 if (do_mpath
&& new_select
) {
2127 for (pi
= bgp_node_get_bgp_path_info(rn
);
2128 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2131 bgp_path_info_path_with_addpath_rx_str(
2134 if (pi
== new_select
) {
2137 "%s: %s is the bestpath, add to the multipath list",
2139 bgp_mp_list_add(&mp_list
, pi
);
2143 if (BGP_PATH_HOLDDOWN(pi
))
2146 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2147 && !CHECK_FLAG(pi
->peer
->sflags
,
2148 PEER_STATUS_NSF_WAIT
))
2149 if (pi
->peer
->status
!= Established
)
2152 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2155 "%s: %s has the same nexthop as the bestpath, skip it",
2160 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2161 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2167 "%s: %s is equivalent to the bestpath, add to the multipath list",
2169 bgp_mp_list_add(&mp_list
, pi
);
2174 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2176 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2177 bgp_mp_list_clear(&mp_list
);
2179 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2181 result
->old
= old_select
;
2182 result
->new = new_select
;
2188 * A new route/change in bestpath of an existing route. Evaluate the path
2189 * for advertisement to the subgroup.
2191 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2192 struct bgp_path_info
*selected
,
2193 struct bgp_node
*rn
,
2194 uint32_t addpath_tx_id
)
2197 struct peer
*onlypeer
;
2203 afi
= SUBGRP_AFI(subgrp
);
2204 safi
= SUBGRP_SAFI(subgrp
);
2205 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2208 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2209 char buf_prefix
[PREFIX_STRLEN
];
2210 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2211 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2215 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2216 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2217 PEER_STATUS_ORF_WAIT_REFRESH
))
2220 memset(&attr
, 0, sizeof(struct attr
));
2221 /* It's initialized in bgp_announce_check() */
2223 /* Announcement to the subgroup. If the route is filtered withdraw it.
2226 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2227 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2229 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2233 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2235 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2242 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2243 * This is called at the end of route processing.
2245 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2247 struct bgp_path_info
*pi
;
2249 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2250 if (BGP_PATH_HOLDDOWN(pi
))
2252 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2253 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2258 * Has the route changed from the RIB's perspective? This is invoked only
2259 * if the route selection returns the same best route as earlier - to
2260 * determine if we need to update zebra or not.
2262 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2263 struct bgp_path_info
*selected
)
2265 struct bgp_path_info
*mpinfo
;
2267 /* If this is multipath, check all selected paths for any nexthop
2268 * change or attribute change. Some attribute changes (e.g., community)
2269 * aren't of relevance to the RIB, but we'll update zebra to ensure
2270 * we handle the case of BGP nexthop change. This is the behavior
2271 * when the best path has an attribute change anyway.
2273 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2274 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2278 * If this is multipath, check all selected paths for any nexthop change
2280 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2281 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2282 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2283 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2287 /* Nothing has changed from the RIB's perspective. */
2291 struct bgp_process_queue
{
2293 STAILQ_HEAD(, bgp_node
) pqueue
;
2294 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2296 unsigned int queued
;
2300 * old_select = The old best path
2301 * new_select = the new best path
2303 * if (!old_select && new_select)
2304 * We are sending new information on.
2306 * if (old_select && new_select) {
2307 * if (new_select != old_select)
2308 * We have a new best path send a change
2310 * We've received a update with new attributes that needs
2314 * if (old_select && !new_select)
2315 * We have no eligible route that we can announce or the rn
2318 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2319 afi_t afi
, safi_t safi
)
2321 struct bgp_path_info
*new_select
;
2322 struct bgp_path_info
*old_select
;
2323 struct bgp_path_info_pair old_and_new
;
2324 char pfx_buf
[PREFIX2STR_BUFFER
];
2327 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2329 debug
= bgp_debug_bestpath(&rn
->p
);
2331 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2333 "%s: bgp delete in progress, ignoring event, p=%s",
2338 /* Is it end of initial update? (after startup) */
2340 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2341 sizeof(bgp
->update_delay_zebra_resume_time
));
2343 bgp
->main_zebra_update_hold
= 0;
2344 FOREACH_AFI_SAFI (afi
, safi
) {
2345 if (bgp_fibupd_safi(safi
))
2346 bgp_zebra_announce_table(bgp
, afi
, safi
);
2348 bgp
->main_peers_update_hold
= 0;
2350 bgp_start_routeadv(bgp
);
2354 struct prefix
*p
= &rn
->p
;
2356 debug
= bgp_debug_bestpath(&rn
->p
);
2358 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2359 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2360 afi2str(afi
), safi2str(safi
));
2363 /* Best path selection. */
2364 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2366 old_select
= old_and_new
.old
;
2367 new_select
= old_and_new
.new;
2369 /* Do we need to allocate or free labels?
2370 * Right now, since we only deal with per-prefix labels, it is not
2371 * necessary to do this upon changes to best path. Exceptions:
2372 * - label index has changed -> recalculate resulting label
2373 * - path_info sub_type changed -> switch to/from implicit-null
2374 * - no valid label (due to removed static label binding) -> get new one
2376 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2379 || bgp_label_index_differs(new_select
, old_select
)
2380 || new_select
->sub_type
!= old_select
->sub_type
2381 || !bgp_is_valid_label(&rn
->local_label
)) {
2382 /* Enforced penultimate hop popping:
2383 * implicit-null for local routes, aggregate
2384 * and redistributed routes
2386 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2387 || new_select
->sub_type
2388 == BGP_ROUTE_AGGREGATE
2389 || new_select
->sub_type
2390 == BGP_ROUTE_REDISTRIBUTE
) {
2393 BGP_NODE_REGISTERED_FOR_LABEL
))
2394 bgp_unregister_for_label(rn
);
2395 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2397 bgp_set_valid_label(&rn
->local_label
);
2399 bgp_register_for_label(rn
, new_select
);
2401 } else if (CHECK_FLAG(rn
->flags
,
2402 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2403 bgp_unregister_for_label(rn
);
2405 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2406 bgp_unregister_for_label(rn
);
2410 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2412 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2413 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2414 old_select
, new_select
);
2417 /* If best route remains the same and this is not due to user-initiated
2418 * clear, see exactly what needs to be done.
2420 if (old_select
&& old_select
== new_select
2421 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2422 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2423 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2424 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2426 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2427 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2429 if (bgp_fibupd_safi(safi
)
2430 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2432 if (new_select
->type
== ZEBRA_ROUTE_BGP
2433 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2434 || new_select
->sub_type
2435 == BGP_ROUTE_IMPORTED
))
2437 bgp_zebra_announce(rn
, p
, old_select
,
2441 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2442 bgp_zebra_clear_route_change_flags(rn
);
2444 /* If there is a change of interest to peers, reannounce the
2446 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2447 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2448 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2450 /* unicast routes must also be annouced to
2451 * labeled-unicast update-groups */
2452 if (safi
== SAFI_UNICAST
)
2453 group_announce_route(bgp
, afi
,
2454 SAFI_LABELED_UNICAST
, rn
,
2457 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2458 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2461 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2465 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2467 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2469 /* bestpath has changed; bump version */
2470 if (old_select
|| new_select
) {
2471 bgp_bump_version(rn
);
2473 if (!bgp
->t_rmap_def_originate_eval
) {
2477 update_group_refresh_default_originate_route_map
,
2478 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2479 &bgp
->t_rmap_def_originate_eval
);
2484 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2487 zlog_debug("%s: setting SELECTED flag", __func__
);
2488 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2489 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2490 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2494 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2495 if (old_select
!= new_select
) {
2497 vnc_import_bgp_exterior_del_route(bgp
, p
,
2499 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2502 vnc_import_bgp_exterior_add_route(bgp
, p
,
2504 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2510 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2512 /* unicast routes must also be annouced to labeled-unicast update-groups
2514 if (safi
== SAFI_UNICAST
)
2515 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2519 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2520 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2521 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2522 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2523 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2524 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2526 /* if this is an evpn imported type-5 prefix,
2527 * we need to withdraw the route first to clear
2528 * the nh neigh and the RMAC entry.
2531 is_route_parent_evpn(old_select
))
2532 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2534 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2536 /* Withdraw the route from the kernel. */
2537 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2538 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2539 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2540 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2542 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2546 /* advertise/withdraw type-5 routes */
2547 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2548 if (advertise_type5_routes(bgp
, afi
) &&
2550 is_route_injectable_into_evpn(new_select
)) {
2552 /* apply the route-map */
2553 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2554 route_map_result_t ret
;
2556 ret
= route_map_apply(
2557 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2558 &rn
->p
, RMAP_BGP
, new_select
);
2559 if (ret
== RMAP_PERMITMATCH
)
2560 bgp_evpn_advertise_type5_route(
2561 bgp
, &rn
->p
, new_select
->attr
,
2564 bgp_evpn_withdraw_type5_route(
2565 bgp
, &rn
->p
, afi
, safi
);
2567 bgp_evpn_advertise_type5_route(bgp
,
2573 } else if (advertise_type5_routes(bgp
, afi
) &&
2575 is_route_injectable_into_evpn(old_select
))
2576 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2579 /* Clear any route change flags. */
2580 bgp_zebra_clear_route_change_flags(rn
);
2582 /* Reap old select bgp_path_info, if it has been removed */
2583 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2584 bgp_path_info_reap(rn
, old_select
);
2586 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2590 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2592 struct bgp_process_queue
*pqnode
= data
;
2593 struct bgp
*bgp
= pqnode
->bgp
;
2594 struct bgp_table
*table
;
2595 struct bgp_node
*rn
;
2598 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2599 bgp_process_main_one(bgp
, NULL
, 0, 0);
2600 /* should always have dedicated wq call */
2601 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2605 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2606 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2607 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2608 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2609 table
= bgp_node_table(rn
);
2610 /* note, new RNs may be added as part of processing */
2611 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2613 bgp_unlock_node(rn
);
2614 bgp_table_unlock(table
);
2620 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2622 struct bgp_process_queue
*pqnode
= data
;
2624 bgp_unlock(pqnode
->bgp
);
2626 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2629 void bgp_process_queue_init(void)
2631 if (!bm
->process_main_queue
)
2632 bm
->process_main_queue
=
2633 work_queue_new(bm
->master
, "process_main_queue");
2635 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2636 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2637 bm
->process_main_queue
->spec
.max_retries
= 0;
2638 bm
->process_main_queue
->spec
.hold
= 50;
2639 /* Use a higher yield value of 50ms for main queue processing */
2640 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2643 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2645 struct bgp_process_queue
*pqnode
;
2647 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2648 sizeof(struct bgp_process_queue
));
2650 /* unlocked in bgp_processq_del */
2651 pqnode
->bgp
= bgp_lock(bgp
);
2652 STAILQ_INIT(&pqnode
->pqueue
);
2657 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2659 #define ARBITRARY_PROCESS_QLEN 10000
2660 struct work_queue
*wq
= bm
->process_main_queue
;
2661 struct bgp_process_queue
*pqnode
;
2662 int pqnode_reuse
= 0;
2664 /* already scheduled for processing? */
2665 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2671 /* Add route nodes to an existing work queue item until reaching the
2672 limit only if is from the same BGP view and it's not an EOIU marker
2674 if (work_queue_item_count(wq
)) {
2675 struct work_queue_item
*item
= work_queue_last_item(wq
);
2676 pqnode
= item
->data
;
2678 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2679 || pqnode
->bgp
!= bgp
2680 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2681 pqnode
= bgp_processq_alloc(bgp
);
2685 pqnode
= bgp_processq_alloc(bgp
);
2686 /* all unlocked in bgp_process_wq */
2687 bgp_table_lock(bgp_node_table(rn
));
2689 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2692 /* can't be enqueued twice */
2693 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2694 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2698 work_queue_add(wq
, pqnode
);
2703 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2705 struct bgp_process_queue
*pqnode
;
2707 if (bm
->process_main_queue
== NULL
)
2710 pqnode
= bgp_processq_alloc(bgp
);
2712 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2713 work_queue_add(bm
->process_main_queue
, pqnode
);
2716 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2720 peer
= THREAD_ARG(thread
);
2721 peer
->t_pmax_restart
= NULL
;
2723 if (bgp_debug_neighbor_events(peer
))
2725 "%s Maximum-prefix restart timer expired, restore peering",
2728 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2729 zlog_debug("%s: %s peer_clear failed",
2730 __PRETTY_FUNCTION__
, peer
->host
);
2735 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2739 iana_safi_t pkt_safi
;
2741 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2744 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2745 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2746 PEER_STATUS_PREFIX_LIMIT
)
2751 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2753 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2754 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2755 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2757 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2758 PEER_FLAG_MAX_PREFIX_WARNING
))
2761 /* Convert AFI, SAFI to values for packet. */
2762 pkt_afi
= afi_int2iana(afi
);
2763 pkt_safi
= safi_int2iana(safi
);
2767 ndata
[0] = (pkt_afi
>> 8);
2769 ndata
[2] = pkt_safi
;
2770 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2771 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2772 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2773 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2775 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2776 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2777 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2781 /* Dynamic peers will just close their connection. */
2782 if (peer_dynamic_neighbor(peer
))
2785 /* restart timer start */
2786 if (peer
->pmax_restart
[afi
][safi
]) {
2787 peer
->v_pmax_restart
=
2788 peer
->pmax_restart
[afi
][safi
] * 60;
2790 if (bgp_debug_neighbor_events(peer
))
2792 "%s Maximum-prefix restart timer started for %d secs",
2793 peer
->host
, peer
->v_pmax_restart
);
2795 BGP_TIMER_ON(peer
->t_pmax_restart
,
2796 bgp_maximum_prefix_restart_timer
,
2797 peer
->v_pmax_restart
);
2802 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2803 PEER_STATUS_PREFIX_LIMIT
);
2805 if (peer
->pcount
[afi
][safi
]
2806 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2807 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2808 PEER_STATUS_PREFIX_THRESHOLD
)
2813 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2814 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2815 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2816 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2817 PEER_STATUS_PREFIX_THRESHOLD
);
2819 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2820 PEER_STATUS_PREFIX_THRESHOLD
);
2824 /* Unconditionally remove the route from the RIB, without taking
2825 * damping into consideration (eg, because the session went down)
2827 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2828 struct peer
*peer
, afi_t afi
, safi_t safi
)
2830 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2832 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2833 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2835 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, rn
, peer
, true);
2837 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2840 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2841 struct peer
*peer
, afi_t afi
, safi_t safi
,
2842 struct prefix_rd
*prd
)
2844 /* apply dampening, if result is suppressed, we'll be retaining
2845 * the bgp_path_info in the RIB for historical reference.
2847 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2848 && peer
->sort
== BGP_PEER_EBGP
)
2849 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2850 == BGP_DAMP_SUPPRESSED
) {
2851 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2857 if (safi
== SAFI_MPLS_VPN
) {
2858 struct bgp_node
*prn
= NULL
;
2859 struct bgp_table
*table
= NULL
;
2861 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2862 (struct prefix
*)prd
);
2863 if (bgp_node_has_bgp_path_info_data(prn
)) {
2864 table
= bgp_node_get_bgp_table_info(prn
);
2866 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2867 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2869 bgp_unlock_node(prn
);
2871 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2872 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2874 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2875 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2881 /* If this is an EVPN route, process for un-import. */
2882 if (safi
== SAFI_EVPN
)
2883 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2885 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2888 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2889 struct peer
*peer
, struct attr
*attr
,
2890 struct bgp_node
*rn
)
2892 struct bgp_path_info
*new;
2894 /* Make new BGP info. */
2895 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2897 new->instance
= instance
;
2898 new->sub_type
= sub_type
;
2901 new->uptime
= bgp_clock();
2906 static void overlay_index_update(struct attr
*attr
,
2907 struct eth_segment_id
*eth_s_id
,
2908 union gw_addr
*gw_ip
)
2913 if (eth_s_id
== NULL
) {
2914 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2915 sizeof(struct eth_segment_id
));
2917 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2918 sizeof(struct eth_segment_id
));
2920 if (gw_ip
== NULL
) {
2921 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2923 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2924 sizeof(union gw_addr
));
2928 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2929 struct eth_segment_id
*eth_s_id
,
2930 union gw_addr
*gw_ip
)
2932 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2933 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2935 struct eth_segment_id esi
;
2939 if (afi
!= AFI_L2VPN
)
2942 memset(&temp
, 0, sizeof(temp
));
2943 path_eth_s_id
= &temp
.esi
;
2944 path_gw_ip
= &temp
.ip
;
2946 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2949 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2950 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2953 if (gw_ip
== NULL
) {
2954 memset(&temp
, 0, sizeof(temp
));
2955 path_gw_ip_remote
= &temp
.ip
;
2957 path_gw_ip_remote
= gw_ip
;
2959 if (eth_s_id
== NULL
) {
2960 memset(&temp
, 0, sizeof(temp
));
2961 path_eth_s_id_remote
= &temp
.esi
;
2963 path_eth_s_id_remote
= eth_s_id
;
2965 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2968 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2969 sizeof(struct eth_segment_id
));
2972 /* Check if received nexthop is valid or not. */
2973 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
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
, attr
->nexthop
))
2991 /* If MP_NEXTHOP is present, validate it. */
2992 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2993 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2994 * it is not an IPv6 link-local address.
2996 if (attr
->mp_nexthop_len
) {
2997 switch (attr
->mp_nexthop_len
) {
2998 case BGP_ATTR_NHLEN_IPV4
:
2999 case BGP_ATTR_NHLEN_VPNV4
:
3000 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
3001 || IPV4_CLASS_DE(ntohl(
3002 attr
->mp_nexthop_global_in
.s_addr
))
3003 || bgp_nexthop_self(bgp
,
3004 attr
->mp_nexthop_global_in
));
3007 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3008 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3009 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3010 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
3011 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3012 || IN6_IS_ADDR_MULTICAST(
3013 &attr
->mp_nexthop_global
));
3025 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3026 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3027 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3028 uint32_t num_labels
, int soft_reconfig
,
3029 struct bgp_route_evpn
*evpn
)
3032 int aspath_loop_count
= 0;
3033 struct bgp_node
*rn
;
3035 struct attr new_attr
;
3036 struct attr
*attr_new
;
3037 struct bgp_path_info
*pi
;
3038 struct bgp_path_info
*new;
3039 struct bgp_path_info_extra
*extra
;
3041 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3043 int do_loop_check
= 1;
3044 int has_valid_label
= 0;
3046 int vnc_implicit_withdraw
= 0;
3050 memset(&new_attr
, 0, sizeof(struct attr
));
3051 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3052 new_attr
.label
= MPLS_INVALID_LABEL
;
3055 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3056 /* TODO: Check to see if we can get rid of "is_valid_label" */
3057 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3058 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3060 has_valid_label
= bgp_is_valid_label(label
);
3062 /* When peer's soft reconfiguration enabled. Record input packet in
3065 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3066 && peer
!= bgp
->peer_self
)
3067 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3069 /* Check previously received route. */
3070 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3071 if (pi
->peer
== peer
&& pi
->type
== type
3072 && pi
->sub_type
== sub_type
3073 && pi
->addpath_rx_id
== addpath_id
)
3076 /* AS path local-as loop check. */
3077 if (peer
->change_local_as
) {
3078 if (peer
->allowas_in
[afi
][safi
])
3079 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3080 else if (!CHECK_FLAG(peer
->flags
,
3081 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3082 aspath_loop_count
= 1;
3084 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3085 > aspath_loop_count
) {
3086 peer
->stat_pfx_aspath_loop
++;
3087 reason
= "as-path contains our own AS;";
3092 /* If the peer is configured for "allowas-in origin" and the last ASN in
3094 * as-path is our ASN then we do not need to call aspath_loop_check
3096 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3097 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3100 /* AS path loop check. */
3101 if (do_loop_check
) {
3102 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3103 > peer
->allowas_in
[afi
][safi
]
3104 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3105 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3106 > peer
->allowas_in
[afi
][safi
])) {
3107 peer
->stat_pfx_aspath_loop
++;
3108 reason
= "as-path contains our own AS;";
3113 /* Route reflector originator ID check. */
3114 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3115 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3116 peer
->stat_pfx_originator_loop
++;
3117 reason
= "originator is us;";
3121 /* Route reflector cluster ID check. */
3122 if (bgp_cluster_filter(peer
, attr
)) {
3123 peer
->stat_pfx_cluster_loop
++;
3124 reason
= "reflected from the same cluster;";
3128 /* Apply incoming filter. */
3129 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3130 peer
->stat_pfx_filter
++;
3135 /* RFC 8212 to prevent route leaks.
3136 * This specification intends to improve this situation by requiring the
3137 * explicit configuration of both BGP Import and Export Policies for any
3138 * External BGP (EBGP) session such as customers, peers, or
3139 * confederation boundaries for all enabled address families. Through
3140 * codification of the aforementioned requirement, operators will
3141 * benefit from consistent behavior across different BGP
3144 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3145 if (!bgp_inbound_policy_exists(peer
,
3146 &peer
->filter
[afi
][safi
])) {
3147 reason
= "inbound policy missing";
3151 bgp_attr_dup(&new_attr
, attr
);
3153 /* Apply incoming route-map.
3154 * NB: new_attr may now contain newly allocated values from route-map
3156 * commands, so we need bgp_attr_flush in the error paths, until we
3158 * the attr (which takes over the memory references) */
3159 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
,
3160 label
, num_labels
) == RMAP_DENY
) {
3161 peer
->stat_pfx_filter
++;
3162 reason
= "route-map;";
3163 bgp_attr_flush(&new_attr
);
3167 if (peer
->sort
== BGP_PEER_EBGP
) {
3169 /* If we receive the graceful-shutdown community from an eBGP
3170 * peer we must lower local-preference */
3171 if (new_attr
.community
3172 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3173 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3174 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3176 /* If graceful-shutdown is configured then add the GSHUT
3177 * community to all paths received from eBGP peers */
3178 } else if (bgp_flag_check(peer
->bgp
,
3179 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3180 bgp_attr_add_gshut_community(&new_attr
);
3184 /* next hop check. */
3185 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3186 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3187 peer
->stat_pfx_nh_invalid
++;
3188 reason
= "martian or self next-hop;";
3189 bgp_attr_flush(&new_attr
);
3193 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3194 peer
->stat_pfx_nh_invalid
++;
3195 reason
= "self mac;";
3199 attr_new
= bgp_attr_intern(&new_attr
);
3201 /* If the update is implicit withdraw. */
3203 pi
->uptime
= bgp_clock();
3204 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3206 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3208 /* Same attribute comes in. */
3209 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3210 && attrhash_cmp(pi
->attr
, attr_new
)
3211 && (!has_valid_label
3212 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3213 num_labels
* sizeof(mpls_label_t
))
3215 && (overlay_index_equal(
3216 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3217 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3218 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3219 BGP_CONFIG_DAMPENING
)
3220 && peer
->sort
== BGP_PEER_EBGP
3221 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3222 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3223 bgp_debug_rdpfxpath2str(
3224 afi
, safi
, prd
, p
, label
,
3225 num_labels
, addpath_id
? 1 : 0,
3226 addpath_id
, pfx_buf
,
3228 zlog_debug("%s rcvd %s", peer
->host
,
3232 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3233 != BGP_DAMP_SUPPRESSED
) {
3234 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3236 bgp_process(bgp
, rn
, afi
, safi
);
3238 } else /* Duplicate - odd */
3240 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3241 if (!peer
->rcvd_attr_printed
) {
3243 "%s rcvd UPDATE w/ attr: %s",
3245 peer
->rcvd_attr_str
);
3246 peer
->rcvd_attr_printed
= 1;
3249 bgp_debug_rdpfxpath2str(
3250 afi
, safi
, prd
, p
, label
,
3251 num_labels
, addpath_id
? 1 : 0,
3252 addpath_id
, pfx_buf
,
3255 "%s rcvd %s...duplicate ignored",
3256 peer
->host
, pfx_buf
);
3259 /* graceful restart STALE flag unset. */
3260 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3261 bgp_path_info_unset_flag(
3262 rn
, pi
, BGP_PATH_STALE
);
3263 bgp_process(bgp
, rn
, afi
, safi
);
3267 bgp_unlock_node(rn
);
3268 bgp_attr_unintern(&attr_new
);
3273 /* Withdraw/Announce before we fully processed the withdraw */
3274 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3275 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3276 bgp_debug_rdpfxpath2str(
3277 afi
, safi
, prd
, p
, label
, num_labels
,
3278 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3281 "%s rcvd %s, flapped quicker than processing",
3282 peer
->host
, pfx_buf
);
3285 bgp_path_info_restore(rn
, pi
);
3288 /* Received Logging. */
3289 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3290 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3291 num_labels
, addpath_id
? 1 : 0,
3292 addpath_id
, pfx_buf
,
3294 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3297 /* graceful restart STALE flag unset. */
3298 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3299 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3301 /* The attribute is changed. */
3302 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3304 /* implicit withdraw, decrement aggregate and pcount here.
3305 * only if update is accepted, they'll increment below.
3307 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3309 /* Update bgp route dampening information. */
3310 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3311 && peer
->sort
== BGP_PEER_EBGP
) {
3312 /* This is implicit withdraw so we should update
3315 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3316 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3319 if (safi
== SAFI_MPLS_VPN
) {
3320 struct bgp_node
*prn
= NULL
;
3321 struct bgp_table
*table
= NULL
;
3323 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3324 (struct prefix
*)prd
);
3325 if (bgp_node_has_bgp_path_info_data(prn
)) {
3326 table
= bgp_node_get_bgp_table_info(prn
);
3328 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3329 bgp
, prd
, table
, p
, pi
);
3331 bgp_unlock_node(prn
);
3333 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3334 && (safi
== SAFI_UNICAST
)) {
3335 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3337 * Implicit withdraw case.
3339 ++vnc_implicit_withdraw
;
3340 vnc_import_bgp_del_route(bgp
, p
, pi
);
3341 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3346 /* Special handling for EVPN update of an existing route. If the
3347 * extended community attribute has changed, we need to
3349 * the route using its existing extended community. It will be
3350 * subsequently processed for import with the new extended
3353 if (safi
== SAFI_EVPN
&& !same_attr
) {
3355 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3357 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3360 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3361 attr_new
->ecommunity
);
3363 if (bgp_debug_update(peer
, p
, NULL
, 1))
3365 "Change in EXT-COMM, existing %s new %s",
3367 pi
->attr
->ecommunity
),
3369 attr_new
->ecommunity
));
3370 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3376 /* Update to new attribute. */
3377 bgp_attr_unintern(&pi
->attr
);
3378 pi
->attr
= attr_new
;
3380 /* Update MPLS label */
3381 if (has_valid_label
) {
3382 extra
= bgp_path_info_extra_get(pi
);
3383 if (extra
->label
!= label
) {
3384 memcpy(&extra
->label
, label
,
3385 num_labels
* sizeof(mpls_label_t
));
3386 extra
->num_labels
= num_labels
;
3388 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3389 bgp_set_valid_label(&extra
->label
[0]);
3393 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3394 && (safi
== SAFI_UNICAST
)) {
3395 if (vnc_implicit_withdraw
) {
3397 * Add back the route with its new attributes
3399 * The route is still selected, until the route
3401 * queued by bgp_process actually runs. We have
3403 * update to the VNC side immediately to avoid
3405 * configuration changes (e.g., route-map
3407 * trigger re-importation of the entire RIB.
3409 vnc_import_bgp_add_route(bgp
, p
, pi
);
3410 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3414 /* Update Overlay Index */
3415 if (afi
== AFI_L2VPN
) {
3416 overlay_index_update(
3417 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3418 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3421 /* Update bgp route dampening information. */
3422 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3423 && peer
->sort
== BGP_PEER_EBGP
) {
3424 /* Now we do normal update dampening. */
3425 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3426 if (ret
== BGP_DAMP_SUPPRESSED
) {
3427 bgp_unlock_node(rn
);
3432 /* Nexthop reachability check - for unicast and
3433 * labeled-unicast.. */
3434 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3435 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3436 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3437 && !CHECK_FLAG(peer
->flags
,
3438 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3440 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3445 struct bgp
*bgp_nexthop
= bgp
;
3447 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3448 bgp_nexthop
= pi
->extra
->bgp_orig
;
3450 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3452 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3453 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3455 if (BGP_DEBUG(nht
, NHT
)) {
3456 char buf1
[INET6_ADDRSTRLEN
];
3458 (const void *)&attr_new
3460 buf1
, INET6_ADDRSTRLEN
);
3461 zlog_debug("%s(%s): NH unresolved",
3462 __FUNCTION__
, buf1
);
3464 bgp_path_info_unset_flag(rn
, pi
,
3468 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3471 if (safi
== SAFI_MPLS_VPN
) {
3472 struct bgp_node
*prn
= NULL
;
3473 struct bgp_table
*table
= NULL
;
3475 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3476 (struct prefix
*)prd
);
3477 if (bgp_node_has_bgp_path_info_data(prn
)) {
3478 table
= bgp_node_get_bgp_table_info(prn
);
3480 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3481 bgp
, prd
, table
, p
, pi
);
3483 bgp_unlock_node(prn
);
3487 /* If this is an EVPN route and some attribute has changed,
3489 * route for import. If the extended community has changed, we
3491 * have done the un-import earlier and the import would result
3493 * route getting injected into appropriate L2 VNIs. If it is
3495 * some other attribute change, the import will result in
3497 * the attributes for the route in the VNI(s).
3499 if (safi
== SAFI_EVPN
&& !same_attr
)
3500 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3502 /* Process change. */
3503 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3505 bgp_process(bgp
, rn
, afi
, safi
);
3506 bgp_unlock_node(rn
);
3508 if (SAFI_UNICAST
== safi
3509 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3510 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3512 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3514 if ((SAFI_MPLS_VPN
== safi
)
3515 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3517 vpn_leak_to_vrf_update(bgp
, pi
);
3521 if (SAFI_MPLS_VPN
== safi
) {
3522 mpls_label_t label_decoded
= decode_label(label
);
3524 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3525 type
, sub_type
, &label_decoded
);
3527 if (SAFI_ENCAP
== safi
) {
3528 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3529 type
, sub_type
, NULL
);
3534 } // End of implicit withdraw
3536 /* Received Logging. */
3537 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3538 if (!peer
->rcvd_attr_printed
) {
3539 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3540 peer
->rcvd_attr_str
);
3541 peer
->rcvd_attr_printed
= 1;
3544 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3545 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3547 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3550 /* Make new BGP info. */
3551 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3553 /* Update MPLS label */
3554 if (has_valid_label
) {
3555 extra
= bgp_path_info_extra_get(new);
3556 if (extra
->label
!= label
) {
3557 memcpy(&extra
->label
, label
,
3558 num_labels
* sizeof(mpls_label_t
));
3559 extra
->num_labels
= num_labels
;
3561 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3562 bgp_set_valid_label(&extra
->label
[0]);
3565 /* Update Overlay Index */
3566 if (afi
== AFI_L2VPN
) {
3567 overlay_index_update(new->attr
,
3568 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3569 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3571 /* Nexthop reachability check. */
3572 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3573 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3574 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3575 && !CHECK_FLAG(peer
->flags
,
3576 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3577 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3582 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3583 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3584 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3586 if (BGP_DEBUG(nht
, NHT
)) {
3587 char buf1
[INET6_ADDRSTRLEN
];
3589 (const void *)&attr_new
->nexthop
,
3590 buf1
, INET6_ADDRSTRLEN
);
3591 zlog_debug("%s(%s): NH unresolved",
3592 __FUNCTION__
, buf1
);
3594 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3597 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3600 new->addpath_rx_id
= addpath_id
;
3602 /* Increment prefix */
3603 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3605 /* Register new BGP information. */
3606 bgp_path_info_add(rn
, new);
3608 /* route_node_get lock */
3609 bgp_unlock_node(rn
);
3612 if (safi
== SAFI_MPLS_VPN
) {
3613 struct bgp_node
*prn
= NULL
;
3614 struct bgp_table
*table
= NULL
;
3616 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3617 if (bgp_node_has_bgp_path_info_data(prn
)) {
3618 table
= bgp_node_get_bgp_table_info(prn
);
3620 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3621 bgp
, prd
, table
, p
, new);
3623 bgp_unlock_node(prn
);
3627 /* If maximum prefix count is configured and current prefix
3629 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3632 /* If this is an EVPN route, process for import. */
3633 if (safi
== SAFI_EVPN
)
3634 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3636 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3638 /* Process change. */
3639 bgp_process(bgp
, rn
, afi
, safi
);
3641 if (SAFI_UNICAST
== safi
3642 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3643 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3644 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3646 if ((SAFI_MPLS_VPN
== safi
)
3647 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3649 vpn_leak_to_vrf_update(bgp
, new);
3652 if (SAFI_MPLS_VPN
== safi
) {
3653 mpls_label_t label_decoded
= decode_label(label
);
3655 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3656 sub_type
, &label_decoded
);
3658 if (SAFI_ENCAP
== safi
) {
3659 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3666 /* This BGP update is filtered. Log the reason then update BGP
3669 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3671 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3672 if (!peer
->rcvd_attr_printed
) {
3673 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3674 peer
->rcvd_attr_str
);
3675 peer
->rcvd_attr_printed
= 1;
3678 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3679 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3681 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3682 peer
->host
, pfx_buf
, reason
);
3686 /* If this is an EVPN route, un-import it as it is now filtered.
3688 if (safi
== SAFI_EVPN
)
3689 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3691 if (SAFI_UNICAST
== safi
3692 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3693 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3695 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3697 if ((SAFI_MPLS_VPN
== safi
)
3698 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3700 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3703 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3706 bgp_unlock_node(rn
);
3710 * Filtered update is treated as an implicit withdrawal (see
3712 * a few lines above)
3714 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3715 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3723 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3724 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3725 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3726 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3729 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3730 struct bgp_node
*rn
;
3731 struct bgp_path_info
*pi
;
3734 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3735 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3743 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3745 /* If peer is soft reconfiguration enabled. Record input packet for
3746 * further calculation.
3748 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3749 * routes that are filtered. This tanks out Quagga RS pretty badly due
3751 * the iteration over all RS clients.
3752 * Since we need to remove the entry from adj_in anyway, do that first
3754 * if there was no entry, we don't need to do anything more.
3756 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3757 && peer
!= bgp
->peer_self
)
3758 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3759 peer
->stat_pfx_dup_withdraw
++;
3761 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3762 bgp_debug_rdpfxpath2str(
3763 afi
, safi
, prd
, p
, label
, num_labels
,
3764 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3767 "%s withdrawing route %s not in adj-in",
3768 peer
->host
, pfx_buf
);
3770 bgp_unlock_node(rn
);
3774 /* Lookup withdrawn route. */
3775 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3776 if (pi
->peer
== peer
&& pi
->type
== type
3777 && pi
->sub_type
== sub_type
3778 && pi
->addpath_rx_id
== addpath_id
)
3782 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3783 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3784 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3786 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3790 /* Withdraw specified route from routing table. */
3791 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3792 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3793 if (SAFI_UNICAST
== safi
3794 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3795 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3796 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3798 if ((SAFI_MPLS_VPN
== safi
)
3799 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3801 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3803 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3804 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3805 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3807 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3810 /* Unlock bgp_node_get() lock. */
3811 bgp_unlock_node(rn
);
3816 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3819 struct update_subgroup
*subgrp
;
3820 subgrp
= peer_subgroup(peer
, afi
, safi
);
3821 subgroup_default_originate(subgrp
, withdraw
);
3826 * bgp_stop_announce_route_timer
3828 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3830 if (!paf
->t_announce_route
)
3833 THREAD_TIMER_OFF(paf
->t_announce_route
);
3837 * bgp_announce_route_timer_expired
3839 * Callback that is invoked when the route announcement timer for a
3842 static int bgp_announce_route_timer_expired(struct thread
*t
)
3844 struct peer_af
*paf
;
3847 paf
= THREAD_ARG(t
);
3850 if (peer
->status
!= Established
)
3853 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3856 peer_af_announce_route(paf
, 1);
3861 * bgp_announce_route
3863 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3865 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3867 struct peer_af
*paf
;
3868 struct update_subgroup
*subgrp
;
3870 paf
= peer_af_find(peer
, afi
, safi
);
3873 subgrp
= PAF_SUBGRP(paf
);
3876 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3877 * or a refresh has already been triggered.
3879 if (!subgrp
|| paf
->t_announce_route
)
3883 * Start a timer to stagger/delay the announce. This serves
3884 * two purposes - announcement can potentially be combined for
3885 * multiple peers and the announcement doesn't happen in the
3888 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3889 (subgrp
->peer_count
== 1)
3890 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3891 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3892 &paf
->t_announce_route
);
3896 * Announce routes from all AF tables to a peer.
3898 * This should ONLY be called when there is a need to refresh the
3899 * routes to the peer based on a policy change for this peer alone
3900 * or a route refresh request received from the peer.
3901 * The operation will result in splitting the peer from its existing
3902 * subgroups and putting it in new subgroups.
3904 void bgp_announce_route_all(struct peer
*peer
)
3909 FOREACH_AFI_SAFI (afi
, safi
)
3910 bgp_announce_route(peer
, afi
, safi
);
3913 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3914 struct bgp_table
*table
,
3915 struct prefix_rd
*prd
)
3918 struct bgp_node
*rn
;
3919 struct bgp_adj_in
*ain
;
3922 table
= peer
->bgp
->rib
[afi
][safi
];
3924 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3925 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3926 if (ain
->peer
!= peer
)
3929 struct bgp_path_info
*pi
=
3930 bgp_node_get_bgp_path_info(rn
);
3931 uint32_t num_labels
= 0;
3932 mpls_label_t
*label_pnt
= NULL
;
3933 struct bgp_route_evpn evpn
;
3935 if (pi
&& pi
->extra
)
3936 num_labels
= pi
->extra
->num_labels
;
3938 label_pnt
= &pi
->extra
->label
[0];
3940 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3943 memset(&evpn
, 0, sizeof(evpn
));
3945 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3946 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3947 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3948 num_labels
, 1, &evpn
);
3951 bgp_unlock_node(rn
);
3957 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3959 struct bgp_node
*rn
;
3960 struct bgp_table
*table
;
3962 if (peer
->status
!= Established
)
3965 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3966 && (safi
!= SAFI_EVPN
))
3967 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3969 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3970 rn
= bgp_route_next(rn
)) {
3971 table
= bgp_node_get_bgp_table_info(rn
);
3972 if (table
!= NULL
) {
3973 struct prefix_rd prd
;
3975 prd
.family
= AF_UNSPEC
;
3977 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3979 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3986 struct bgp_clear_node_queue
{
3987 struct bgp_node
*rn
;
3990 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3992 struct bgp_clear_node_queue
*cnq
= data
;
3993 struct bgp_node
*rn
= cnq
->rn
;
3994 struct peer
*peer
= wq
->spec
.data
;
3995 struct bgp_path_info
*pi
;
3997 afi_t afi
= bgp_node_table(rn
)->afi
;
3998 safi_t safi
= bgp_node_table(rn
)->safi
;
4003 /* It is possible that we have multiple paths for a prefix from a peer
4004 * if that peer is using AddPath.
4006 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4007 if (pi
->peer
!= peer
)
4010 /* graceful restart STALE flag set. */
4011 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4012 && peer
->nsf
[afi
][safi
]
4013 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4014 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4015 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4017 /* If this is an EVPN route, process for
4019 if (safi
== SAFI_EVPN
)
4020 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
4022 /* Handle withdraw for VRF route-leaking and L3VPN */
4023 if (SAFI_UNICAST
== safi
4024 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4025 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4026 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4029 if (SAFI_MPLS_VPN
== safi
&&
4030 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4031 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4034 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4040 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4042 struct bgp_clear_node_queue
*cnq
= data
;
4043 struct bgp_node
*rn
= cnq
->rn
;
4044 struct bgp_table
*table
= bgp_node_table(rn
);
4046 bgp_unlock_node(rn
);
4047 bgp_table_unlock(table
);
4048 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4051 static void bgp_clear_node_complete(struct work_queue
*wq
)
4053 struct peer
*peer
= wq
->spec
.data
;
4055 /* Tickle FSM to start moving again */
4056 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4058 peer_unlock(peer
); /* bgp_clear_route */
4061 static void bgp_clear_node_queue_init(struct peer
*peer
)
4063 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4065 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4066 #undef CLEAR_QUEUE_NAME_LEN
4068 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4069 peer
->clear_node_queue
->spec
.hold
= 10;
4070 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4071 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4072 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4073 peer
->clear_node_queue
->spec
.max_retries
= 0;
4075 /* we only 'lock' this peer reference when the queue is actually active
4077 peer
->clear_node_queue
->spec
.data
= peer
;
4080 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4081 struct bgp_table
*table
)
4083 struct bgp_node
*rn
;
4084 int force
= bm
->process_main_queue
? 0 : 1;
4087 table
= peer
->bgp
->rib
[afi
][safi
];
4089 /* If still no table => afi/safi isn't configured at all or smth. */
4093 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4094 struct bgp_path_info
*pi
, *next
;
4095 struct bgp_adj_in
*ain
;
4096 struct bgp_adj_in
*ain_next
;
4098 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4099 * queued for every clearing peer, regardless of whether it is
4100 * relevant to the peer at hand.
4102 * Overview: There are 3 different indices which need to be
4103 * scrubbed, potentially, when a peer is removed:
4105 * 1 peer's routes visible via the RIB (ie accepted routes)
4106 * 2 peer's routes visible by the (optional) peer's adj-in index
4107 * 3 other routes visible by the peer's adj-out index
4109 * 3 there is no hurry in scrubbing, once the struct peer is
4110 * removed from bgp->peer, we could just GC such deleted peer's
4111 * adj-outs at our leisure.
4113 * 1 and 2 must be 'scrubbed' in some way, at least made
4114 * invisible via RIB index before peer session is allowed to be
4115 * brought back up. So one needs to know when such a 'search' is
4120 * - there'd be a single global queue or a single RIB walker
4121 * - rather than tracking which route_nodes still need to be
4122 * examined on a peer basis, we'd track which peers still
4125 * Given that our per-peer prefix-counts now should be reliable,
4126 * this may actually be achievable. It doesn't seem to be a huge
4127 * problem at this time,
4129 * It is possible that we have multiple paths for a prefix from
4131 * if that peer is using AddPath.
4135 ain_next
= ain
->next
;
4137 if (ain
->peer
== peer
) {
4138 bgp_adj_in_remove(rn
, ain
);
4139 bgp_unlock_node(rn
);
4145 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4147 if (pi
->peer
!= peer
)
4151 bgp_path_info_reap(rn
, pi
);
4153 struct bgp_clear_node_queue
*cnq
;
4155 /* both unlocked in bgp_clear_node_queue_del */
4156 bgp_table_lock(bgp_node_table(rn
));
4159 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4160 sizeof(struct bgp_clear_node_queue
));
4162 work_queue_add(peer
->clear_node_queue
, cnq
);
4170 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4172 struct bgp_node
*rn
;
4173 struct bgp_table
*table
;
4175 if (peer
->clear_node_queue
== NULL
)
4176 bgp_clear_node_queue_init(peer
);
4178 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4179 * Idle until it receives a Clearing_Completed event. This protects
4180 * against peers which flap faster than we can we clear, which could
4183 * a) race with routes from the new session being installed before
4184 * clear_route_node visits the node (to delete the route of that
4186 * b) resource exhaustion, clear_route_node likely leads to an entry
4187 * on the process_main queue. Fast-flapping could cause that queue
4191 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4192 * the unlock will happen upon work-queue completion; other wise, the
4193 * unlock happens at the end of this function.
4195 if (!peer
->clear_node_queue
->thread
)
4198 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4199 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4201 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4202 rn
= bgp_route_next(rn
)) {
4203 table
= bgp_node_get_bgp_table_info(rn
);
4207 bgp_clear_route_table(peer
, afi
, safi
, table
);
4210 /* unlock if no nodes got added to the clear-node-queue. */
4211 if (!peer
->clear_node_queue
->thread
)
4215 void bgp_clear_route_all(struct peer
*peer
)
4220 FOREACH_AFI_SAFI (afi
, safi
)
4221 bgp_clear_route(peer
, afi
, safi
);
4224 rfapiProcessPeerDown(peer
);
4228 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4230 struct bgp_table
*table
;
4231 struct bgp_node
*rn
;
4232 struct bgp_adj_in
*ain
;
4233 struct bgp_adj_in
*ain_next
;
4235 table
= peer
->bgp
->rib
[afi
][safi
];
4237 /* It is possible that we have multiple paths for a prefix from a peer
4238 * if that peer is using AddPath.
4240 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4244 ain_next
= ain
->next
;
4246 if (ain
->peer
== peer
) {
4247 bgp_adj_in_remove(rn
, ain
);
4248 bgp_unlock_node(rn
);
4256 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4258 struct bgp_node
*rn
;
4259 struct bgp_path_info
*pi
;
4260 struct bgp_table
*table
;
4262 if (safi
== SAFI_MPLS_VPN
) {
4263 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4264 rn
= bgp_route_next(rn
)) {
4265 struct bgp_node
*rm
;
4267 /* look for neighbor in tables */
4268 table
= bgp_node_get_bgp_table_info(rn
);
4272 for (rm
= bgp_table_top(table
); rm
;
4273 rm
= bgp_route_next(rm
))
4274 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4276 if (pi
->peer
!= peer
)
4278 if (!CHECK_FLAG(pi
->flags
,
4282 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4287 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4288 rn
= bgp_route_next(rn
))
4289 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4291 if (pi
->peer
!= peer
)
4293 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4295 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4301 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4303 if (peer
->sort
== BGP_PEER_EBGP
4304 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4305 || FILTER_LIST_OUT_NAME(filter
)
4306 || DISTRIBUTE_OUT_NAME(filter
)))
4311 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4313 if (peer
->sort
== BGP_PEER_EBGP
4314 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4315 || FILTER_LIST_IN_NAME(filter
)
4316 || DISTRIBUTE_IN_NAME(filter
)))
4321 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4324 struct bgp_node
*rn
;
4325 struct bgp_path_info
*pi
;
4326 struct bgp_path_info
*next
;
4328 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4329 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4332 /* Unimport EVPN routes from VRFs */
4333 if (safi
== SAFI_EVPN
)
4334 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4338 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4339 && pi
->type
== ZEBRA_ROUTE_BGP
4340 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4341 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4342 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4344 if (bgp_fibupd_safi(safi
))
4345 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4347 bgp_path_info_reap(rn
, pi
);
4352 /* Delete all kernel routes. */
4353 void bgp_cleanup_routes(struct bgp
*bgp
)
4356 struct bgp_node
*rn
;
4357 struct bgp_table
*table
;
4359 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4360 if (afi
== AFI_L2VPN
)
4362 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4365 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4367 if (afi
!= AFI_L2VPN
) {
4369 safi
= SAFI_MPLS_VPN
;
4370 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4371 rn
= bgp_route_next(rn
)) {
4372 table
= bgp_node_get_bgp_table_info(rn
);
4373 if (table
!= NULL
) {
4374 bgp_cleanup_table(bgp
, table
, safi
);
4375 bgp_table_finish(&table
);
4376 bgp_node_set_bgp_table_info(rn
, NULL
);
4377 bgp_unlock_node(rn
);
4381 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4382 rn
= bgp_route_next(rn
)) {
4383 table
= bgp_node_get_bgp_table_info(rn
);
4384 if (table
!= NULL
) {
4385 bgp_cleanup_table(bgp
, table
, safi
);
4386 bgp_table_finish(&table
);
4387 bgp_node_set_bgp_table_info(rn
, NULL
);
4388 bgp_unlock_node(rn
);
4393 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4394 rn
= bgp_route_next(rn
)) {
4395 table
= bgp_node_get_bgp_table_info(rn
);
4396 if (table
!= NULL
) {
4397 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4398 bgp_table_finish(&table
);
4399 bgp_node_set_bgp_table_info(rn
, NULL
);
4400 bgp_unlock_node(rn
);
4405 void bgp_reset(void)
4408 bgp_zclient_reset();
4409 access_list_reset();
4410 prefix_list_reset();
4413 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4415 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4416 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4417 PEER_CAP_ADDPATH_AF_TX_RCV
));
4420 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4422 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4423 struct bgp_nlri
*packet
)
4432 int addpath_encoded
;
4433 uint32_t addpath_id
;
4436 lim
= pnt
+ packet
->length
;
4438 safi
= packet
->safi
;
4440 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4442 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4443 syntactic validity. If the field is syntactically incorrect,
4444 then the Error Subcode is set to Invalid Network Field. */
4445 for (; pnt
< lim
; pnt
+= psize
) {
4446 /* Clear prefix structure. */
4447 memset(&p
, 0, sizeof(struct prefix
));
4449 if (addpath_encoded
) {
4451 /* When packet overflow occurs return immediately. */
4452 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4453 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4455 addpath_id
= ntohl(*((uint32_t *)pnt
));
4456 pnt
+= BGP_ADDPATH_ID_LEN
;
4459 /* Fetch prefix length. */
4460 p
.prefixlen
= *pnt
++;
4461 /* afi/safi validity already verified by caller,
4462 * bgp_update_receive */
4463 p
.family
= afi2family(afi
);
4465 /* Prefix length check. */
4466 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4469 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4470 peer
->host
, p
.prefixlen
, packet
->afi
);
4471 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4474 /* Packet size overflow check. */
4475 psize
= PSIZE(p
.prefixlen
);
4477 /* When packet overflow occur return immediately. */
4478 if (pnt
+ psize
> lim
) {
4481 "%s [Error] Update packet error (prefix length %d overflows packet)",
4482 peer
->host
, p
.prefixlen
);
4483 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4486 /* Defensive coding, double-check the psize fits in a struct
4488 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4491 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4492 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4493 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4496 /* Fetch prefix from NLRI packet. */
4497 memcpy(p
.u
.val
, pnt
, psize
);
4499 /* Check address. */
4500 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4501 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4502 /* From RFC4271 Section 6.3:
4504 * If a prefix in the NLRI field is semantically
4506 * (e.g., an unexpected multicast IP address),
4508 * be logged locally, and the prefix SHOULD be
4513 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4514 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4519 /* Check address. */
4520 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4521 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4526 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4528 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4533 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4538 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4540 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4547 /* Normal process. */
4549 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4550 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4551 NULL
, NULL
, 0, 0, NULL
);
4553 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4554 safi
, ZEBRA_ROUTE_BGP
,
4555 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4558 /* Do not send BGP notification twice when maximum-prefix count
4560 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4561 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4563 /* Address family configuration mismatch. */
4565 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4568 /* Packet length consistency check. */
4572 "%s [Error] Update packet error (prefix length mismatch with total length)",
4574 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4577 return BGP_NLRI_PARSE_OK
;
4580 static struct bgp_static
*bgp_static_new(void)
4582 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4585 static void bgp_static_free(struct bgp_static
*bgp_static
)
4587 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4588 route_map_counter_decrement(bgp_static
->rmap
.map
);
4590 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4591 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4594 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4595 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4597 struct bgp_node
*rn
;
4598 struct bgp_path_info
*pi
;
4599 struct bgp_path_info
*new;
4600 struct bgp_path_info rmap_path
;
4602 struct attr
*attr_new
;
4603 route_map_result_t ret
;
4605 int vnc_implicit_withdraw
= 0;
4612 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4614 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4616 attr
.nexthop
= bgp_static
->igpnexthop
;
4617 attr
.med
= bgp_static
->igpmetric
;
4618 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4620 if (bgp_static
->atomic
)
4621 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4623 /* Store label index, if required. */
4624 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4625 attr
.label_index
= bgp_static
->label_index
;
4626 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4629 /* Apply route-map. */
4630 if (bgp_static
->rmap
.name
) {
4631 struct attr attr_tmp
= attr
;
4633 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4634 rmap_path
.peer
= bgp
->peer_self
;
4635 rmap_path
.attr
= &attr_tmp
;
4637 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4639 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4642 bgp
->peer_self
->rmap_type
= 0;
4644 if (ret
== RMAP_DENYMATCH
) {
4645 /* Free uninterned attribute. */
4646 bgp_attr_flush(&attr_tmp
);
4648 /* Unintern original. */
4649 aspath_unintern(&attr
.aspath
);
4650 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4654 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4655 bgp_attr_add_gshut_community(&attr_tmp
);
4657 attr_new
= bgp_attr_intern(&attr_tmp
);
4660 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4661 bgp_attr_add_gshut_community(&attr
);
4663 attr_new
= bgp_attr_intern(&attr
);
4666 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4667 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4668 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4672 if (attrhash_cmp(pi
->attr
, attr_new
)
4673 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4674 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4675 bgp_unlock_node(rn
);
4676 bgp_attr_unintern(&attr_new
);
4677 aspath_unintern(&attr
.aspath
);
4680 /* The attribute is changed. */
4681 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4683 /* Rewrite BGP route information. */
4684 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4685 bgp_path_info_restore(rn
, pi
);
4687 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4689 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4690 && (safi
== SAFI_UNICAST
)) {
4691 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4693 * Implicit withdraw case.
4694 * We have to do this before pi is
4697 ++vnc_implicit_withdraw
;
4698 vnc_import_bgp_del_route(bgp
, p
, pi
);
4699 vnc_import_bgp_exterior_del_route(
4704 bgp_attr_unintern(&pi
->attr
);
4705 pi
->attr
= attr_new
;
4706 pi
->uptime
= bgp_clock();
4708 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4709 && (safi
== SAFI_UNICAST
)) {
4710 if (vnc_implicit_withdraw
) {
4711 vnc_import_bgp_add_route(bgp
, p
, pi
);
4712 vnc_import_bgp_exterior_add_route(
4718 /* Nexthop reachability check. */
4719 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4720 && (safi
== SAFI_UNICAST
4721 || safi
== SAFI_LABELED_UNICAST
)) {
4723 struct bgp
*bgp_nexthop
= bgp
;
4725 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4726 bgp_nexthop
= pi
->extra
->bgp_orig
;
4728 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4730 bgp_path_info_set_flag(rn
, pi
,
4733 if (BGP_DEBUG(nht
, NHT
)) {
4734 char buf1
[INET6_ADDRSTRLEN
];
4735 inet_ntop(p
->family
,
4739 "%s(%s): Route not in table, not advertising",
4740 __FUNCTION__
, buf1
);
4742 bgp_path_info_unset_flag(
4743 rn
, pi
, BGP_PATH_VALID
);
4746 /* Delete the NHT structure if any, if we're
4748 * enabling/disabling import check. We
4749 * deregister the route
4750 * from NHT to avoid overloading NHT and the
4751 * process interaction
4753 bgp_unlink_nexthop(pi
);
4754 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4756 /* Process change. */
4757 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4758 bgp_process(bgp
, rn
, afi
, safi
);
4760 if (SAFI_UNICAST
== safi
4761 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4763 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4764 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4768 bgp_unlock_node(rn
);
4769 aspath_unintern(&attr
.aspath
);
4774 /* Make new BGP info. */
4775 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4777 /* Nexthop reachability check. */
4778 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4779 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4780 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4781 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4783 if (BGP_DEBUG(nht
, NHT
)) {
4784 char buf1
[INET6_ADDRSTRLEN
];
4785 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4788 "%s(%s): Route not in table, not advertising",
4789 __FUNCTION__
, buf1
);
4791 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4794 /* Delete the NHT structure if any, if we're toggling between
4795 * enabling/disabling import check. We deregister the route
4796 * from NHT to avoid overloading NHT and the process interaction
4798 bgp_unlink_nexthop(new);
4800 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4803 /* Aggregate address increment. */
4804 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4806 /* Register new BGP information. */
4807 bgp_path_info_add(rn
, new);
4809 /* route_node_get lock */
4810 bgp_unlock_node(rn
);
4812 /* Process change. */
4813 bgp_process(bgp
, rn
, afi
, safi
);
4815 if (SAFI_UNICAST
== safi
4816 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4817 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4818 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4821 /* Unintern original. */
4822 aspath_unintern(&attr
.aspath
);
4825 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4828 struct bgp_node
*rn
;
4829 struct bgp_path_info
*pi
;
4831 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4833 /* Check selected route and self inserted route. */
4834 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4835 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4836 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4839 /* Withdraw static BGP route from routing table. */
4841 if (SAFI_UNICAST
== safi
4842 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4843 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4844 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4846 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4847 bgp_unlink_nexthop(pi
);
4848 bgp_path_info_delete(rn
, pi
);
4849 bgp_process(bgp
, rn
, afi
, safi
);
4852 /* Unlock bgp_node_lookup. */
4853 bgp_unlock_node(rn
);
4857 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4859 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4860 afi_t afi
, safi_t safi
,
4861 struct prefix_rd
*prd
)
4863 struct bgp_node
*rn
;
4864 struct bgp_path_info
*pi
;
4866 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4868 /* Check selected route and self inserted route. */
4869 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4870 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4871 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4874 /* Withdraw static BGP route from routing table. */
4877 rfapiProcessWithdraw(
4878 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4879 1); /* Kill, since it is an administrative change */
4881 if (SAFI_MPLS_VPN
== safi
4882 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4883 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4885 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4886 bgp_path_info_delete(rn
, pi
);
4887 bgp_process(bgp
, rn
, afi
, safi
);
4890 /* Unlock bgp_node_lookup. */
4891 bgp_unlock_node(rn
);
4894 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4895 struct bgp_static
*bgp_static
, afi_t afi
,
4898 struct bgp_node
*rn
;
4899 struct bgp_path_info
*new;
4900 struct attr
*attr_new
;
4901 struct attr attr
= {0};
4902 struct bgp_path_info
*pi
;
4904 mpls_label_t label
= 0;
4906 uint32_t num_labels
= 0;
4911 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4913 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4916 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4918 attr
.nexthop
= bgp_static
->igpnexthop
;
4919 attr
.med
= bgp_static
->igpmetric
;
4920 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4922 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4923 || (safi
== SAFI_ENCAP
)) {
4924 if (afi
== AFI_IP
) {
4925 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4926 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4929 if (afi
== AFI_L2VPN
) {
4930 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4932 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4933 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4934 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4935 sizeof(struct in6_addr
));
4936 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4937 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4938 struct bgp_encap_type_vxlan bet
;
4939 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4940 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4941 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4943 if (bgp_static
->router_mac
) {
4944 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4947 /* Apply route-map. */
4948 if (bgp_static
->rmap
.name
) {
4949 struct attr attr_tmp
= attr
;
4950 struct bgp_path_info rmap_path
;
4951 route_map_result_t ret
;
4953 rmap_path
.peer
= bgp
->peer_self
;
4954 rmap_path
.attr
= &attr_tmp
;
4956 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4958 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4961 bgp
->peer_self
->rmap_type
= 0;
4963 if (ret
== RMAP_DENYMATCH
) {
4964 /* Free uninterned attribute. */
4965 bgp_attr_flush(&attr_tmp
);
4967 /* Unintern original. */
4968 aspath_unintern(&attr
.aspath
);
4969 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4974 attr_new
= bgp_attr_intern(&attr_tmp
);
4976 attr_new
= bgp_attr_intern(&attr
);
4979 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4980 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4981 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4985 memset(&add
, 0, sizeof(union gw_addr
));
4986 if (attrhash_cmp(pi
->attr
, attr_new
)
4987 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4988 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4989 bgp_unlock_node(rn
);
4990 bgp_attr_unintern(&attr_new
);
4991 aspath_unintern(&attr
.aspath
);
4994 /* The attribute is changed. */
4995 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4997 /* Rewrite BGP route information. */
4998 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4999 bgp_path_info_restore(rn
, pi
);
5001 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5002 bgp_attr_unintern(&pi
->attr
);
5003 pi
->attr
= attr_new
;
5004 pi
->uptime
= bgp_clock();
5007 label
= decode_label(&pi
->extra
->label
[0]);
5010 /* Process change. */
5011 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5012 bgp_process(bgp
, rn
, afi
, safi
);
5014 if (SAFI_MPLS_VPN
== safi
5015 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5016 vpn_leak_to_vrf_update(bgp
, pi
);
5019 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5020 pi
->attr
, afi
, safi
, pi
->type
,
5021 pi
->sub_type
, &label
);
5023 bgp_unlock_node(rn
);
5024 aspath_unintern(&attr
.aspath
);
5030 /* Make new BGP info. */
5031 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5033 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5034 new->extra
= bgp_path_info_extra_new();
5036 new->extra
->label
[0] = bgp_static
->label
;
5037 new->extra
->num_labels
= num_labels
;
5040 label
= decode_label(&bgp_static
->label
);
5043 /* Aggregate address increment. */
5044 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5046 /* Register new BGP information. */
5047 bgp_path_info_add(rn
, new);
5048 /* route_node_get lock */
5049 bgp_unlock_node(rn
);
5051 /* Process change. */
5052 bgp_process(bgp
, rn
, afi
, safi
);
5054 if (SAFI_MPLS_VPN
== safi
5055 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5056 vpn_leak_to_vrf_update(bgp
, new);
5059 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5060 safi
, new->type
, new->sub_type
, &label
);
5063 /* Unintern original. */
5064 aspath_unintern(&attr
.aspath
);
5067 /* Configure static BGP network. When user don't run zebra, static
5068 route should be installed as valid. */
5069 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5070 const char *ip_str
, afi_t afi
, safi_t safi
,
5071 const char *rmap
, int backdoor
, uint32_t label_index
)
5073 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5076 struct bgp_static
*bgp_static
;
5077 struct bgp_node
*rn
;
5078 uint8_t need_update
= 0;
5080 /* Convert IP prefix string to struct prefix. */
5081 ret
= str2prefix(ip_str
, &p
);
5083 vty_out(vty
, "%% Malformed prefix\n");
5084 return CMD_WARNING_CONFIG_FAILED
;
5086 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5087 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5088 return CMD_WARNING_CONFIG_FAILED
;
5095 /* Set BGP static route configuration. */
5096 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5099 vty_out(vty
, "%% Can't find static route specified\n");
5100 return CMD_WARNING_CONFIG_FAILED
;
5103 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5105 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5106 && (label_index
!= bgp_static
->label_index
)) {
5108 "%% label-index doesn't match static route\n");
5109 return CMD_WARNING_CONFIG_FAILED
;
5112 if ((rmap
&& bgp_static
->rmap
.name
)
5113 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5115 "%% route-map name doesn't match static route\n");
5116 return CMD_WARNING_CONFIG_FAILED
;
5119 /* Update BGP RIB. */
5120 if (!bgp_static
->backdoor
)
5121 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5123 /* Clear configuration. */
5124 bgp_static_free(bgp_static
);
5125 bgp_node_set_bgp_static_info(rn
, NULL
);
5126 bgp_unlock_node(rn
);
5127 bgp_unlock_node(rn
);
5130 /* Set BGP static route configuration. */
5131 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5133 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5135 /* Configuration change. */
5136 /* Label index cannot be changed. */
5137 if (bgp_static
->label_index
!= label_index
) {
5138 vty_out(vty
, "%% cannot change label-index\n");
5139 return CMD_WARNING_CONFIG_FAILED
;
5142 /* Check previous routes are installed into BGP. */
5143 if (bgp_static
->valid
5144 && bgp_static
->backdoor
!= backdoor
)
5147 bgp_static
->backdoor
= backdoor
;
5150 XFREE(MTYPE_ROUTE_MAP_NAME
,
5151 bgp_static
->rmap
.name
);
5152 route_map_counter_decrement(
5153 bgp_static
->rmap
.map
);
5154 bgp_static
->rmap
.name
=
5155 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5156 bgp_static
->rmap
.map
=
5157 route_map_lookup_by_name(rmap
);
5158 route_map_counter_increment(
5159 bgp_static
->rmap
.map
);
5161 XFREE(MTYPE_ROUTE_MAP_NAME
,
5162 bgp_static
->rmap
.name
);
5163 route_map_counter_decrement(
5164 bgp_static
->rmap
.map
);
5165 bgp_static
->rmap
.name
= NULL
;
5166 bgp_static
->rmap
.map
= NULL
;
5167 bgp_static
->valid
= 0;
5169 bgp_unlock_node(rn
);
5171 /* New configuration. */
5172 bgp_static
= bgp_static_new();
5173 bgp_static
->backdoor
= backdoor
;
5174 bgp_static
->valid
= 0;
5175 bgp_static
->igpmetric
= 0;
5176 bgp_static
->igpnexthop
.s_addr
= 0;
5177 bgp_static
->label_index
= label_index
;
5180 XFREE(MTYPE_ROUTE_MAP_NAME
,
5181 bgp_static
->rmap
.name
);
5182 route_map_counter_decrement(
5183 bgp_static
->rmap
.map
);
5184 bgp_static
->rmap
.name
=
5185 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5186 bgp_static
->rmap
.map
=
5187 route_map_lookup_by_name(rmap
);
5188 route_map_counter_increment(
5189 bgp_static
->rmap
.map
);
5191 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5194 bgp_static
->valid
= 1;
5196 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5198 if (!bgp_static
->backdoor
)
5199 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5205 void bgp_static_add(struct bgp
*bgp
)
5209 struct bgp_node
*rn
;
5210 struct bgp_node
*rm
;
5211 struct bgp_table
*table
;
5212 struct bgp_static
*bgp_static
;
5214 FOREACH_AFI_SAFI (afi
, safi
)
5215 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5216 rn
= bgp_route_next(rn
)) {
5217 if (!bgp_node_has_bgp_path_info_data(rn
))
5220 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5221 || (safi
== SAFI_EVPN
)) {
5222 table
= bgp_node_get_bgp_table_info(rn
);
5224 for (rm
= bgp_table_top(table
); rm
;
5225 rm
= bgp_route_next(rm
)) {
5227 bgp_node_get_bgp_static_info(
5229 bgp_static_update_safi(bgp
, &rm
->p
,
5236 bgp_node_get_bgp_static_info(rn
), afi
,
5242 /* Called from bgp_delete(). Delete all static routes from the BGP
5244 void bgp_static_delete(struct bgp
*bgp
)
5248 struct bgp_node
*rn
;
5249 struct bgp_node
*rm
;
5250 struct bgp_table
*table
;
5251 struct bgp_static
*bgp_static
;
5253 FOREACH_AFI_SAFI (afi
, safi
)
5254 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5255 rn
= bgp_route_next(rn
)) {
5256 if (!bgp_node_has_bgp_path_info_data(rn
))
5259 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5260 || (safi
== SAFI_EVPN
)) {
5261 table
= bgp_node_get_bgp_table_info(rn
);
5263 for (rm
= bgp_table_top(table
); rm
;
5264 rm
= bgp_route_next(rm
)) {
5266 bgp_node_get_bgp_static_info(
5271 bgp_static_withdraw_safi(
5272 bgp
, &rm
->p
, AFI_IP
, safi
,
5273 (struct prefix_rd
*)&rn
->p
);
5274 bgp_static_free(bgp_static
);
5275 bgp_node_set_bgp_static_info(rn
, NULL
);
5276 bgp_unlock_node(rn
);
5279 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5280 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5281 bgp_static_free(bgp_static
);
5282 bgp_node_set_bgp_static_info(rn
, NULL
);
5283 bgp_unlock_node(rn
);
5288 void bgp_static_redo_import_check(struct bgp
*bgp
)
5292 struct bgp_node
*rn
;
5293 struct bgp_node
*rm
;
5294 struct bgp_table
*table
;
5295 struct bgp_static
*bgp_static
;
5297 /* Use this flag to force reprocessing of the route */
5298 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5299 FOREACH_AFI_SAFI (afi
, safi
) {
5300 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5301 rn
= bgp_route_next(rn
)) {
5302 if (!bgp_node_has_bgp_path_info_data(rn
))
5305 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5306 || (safi
== SAFI_EVPN
)) {
5307 table
= bgp_node_get_bgp_table_info(rn
);
5309 for (rm
= bgp_table_top(table
); rm
;
5310 rm
= bgp_route_next(rm
)) {
5312 bgp_node_get_bgp_static_info(
5314 bgp_static_update_safi(bgp
, &rm
->p
,
5319 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5320 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5325 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5328 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5331 struct bgp_table
*table
;
5332 struct bgp_node
*rn
;
5333 struct bgp_path_info
*pi
;
5335 /* Do not install the aggregate route if BGP is in the
5336 * process of termination.
5338 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5339 (bgp
->peer_self
== NULL
))
5342 table
= bgp
->rib
[afi
][safi
];
5343 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5344 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5345 if (pi
->peer
== bgp
->peer_self
5346 && ((pi
->type
== ZEBRA_ROUTE_BGP
5347 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5348 || (pi
->type
!= ZEBRA_ROUTE_BGP
5350 == BGP_ROUTE_REDISTRIBUTE
))) {
5351 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5353 bgp_unlink_nexthop(pi
);
5354 bgp_path_info_delete(rn
, pi
);
5355 bgp_process(bgp
, rn
, afi
, safi
);
5362 * Purge all networks and redistributed routes from routing table.
5363 * Invoked upon the instance going down.
5365 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5370 FOREACH_AFI_SAFI (afi
, safi
)
5371 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5376 * Currently this is used to set static routes for VPN and ENCAP.
5377 * I think it can probably be factored with bgp_static_set.
5379 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5380 const char *ip_str
, const char *rd_str
,
5381 const char *label_str
, const char *rmap_str
,
5382 int evpn_type
, const char *esi
, const char *gwip
,
5383 const char *ethtag
, const char *routermac
)
5385 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5388 struct prefix_rd prd
;
5389 struct bgp_node
*prn
;
5390 struct bgp_node
*rn
;
5391 struct bgp_table
*table
;
5392 struct bgp_static
*bgp_static
;
5393 mpls_label_t label
= MPLS_INVALID_LABEL
;
5394 struct prefix gw_ip
;
5396 /* validate ip prefix */
5397 ret
= str2prefix(ip_str
, &p
);
5399 vty_out(vty
, "%% Malformed prefix\n");
5400 return CMD_WARNING_CONFIG_FAILED
;
5403 if ((afi
== AFI_L2VPN
)
5404 && (bgp_build_evpn_prefix(evpn_type
,
5405 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5406 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5407 return CMD_WARNING_CONFIG_FAILED
;
5410 ret
= str2prefix_rd(rd_str
, &prd
);
5412 vty_out(vty
, "%% Malformed rd\n");
5413 return CMD_WARNING_CONFIG_FAILED
;
5417 unsigned long label_val
;
5418 label_val
= strtoul(label_str
, NULL
, 10);
5419 encode_label(label_val
, &label
);
5422 if (safi
== SAFI_EVPN
) {
5423 if (esi
&& str2esi(esi
, NULL
) == 0) {
5424 vty_out(vty
, "%% Malformed ESI\n");
5425 return CMD_WARNING_CONFIG_FAILED
;
5427 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5428 vty_out(vty
, "%% Malformed Router MAC\n");
5429 return CMD_WARNING_CONFIG_FAILED
;
5432 memset(&gw_ip
, 0, sizeof(struct prefix
));
5433 ret
= str2prefix(gwip
, &gw_ip
);
5435 vty_out(vty
, "%% Malformed GatewayIp\n");
5436 return CMD_WARNING_CONFIG_FAILED
;
5438 if ((gw_ip
.family
== AF_INET
5439 && is_evpn_prefix_ipaddr_v6(
5440 (struct prefix_evpn
*)&p
))
5441 || (gw_ip
.family
== AF_INET6
5442 && is_evpn_prefix_ipaddr_v4(
5443 (struct prefix_evpn
*)&p
))) {
5445 "%% GatewayIp family differs with IP prefix\n");
5446 return CMD_WARNING_CONFIG_FAILED
;
5450 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5451 if (!bgp_node_has_bgp_path_info_data(prn
))
5452 bgp_node_set_bgp_table_info(prn
,
5453 bgp_table_init(bgp
, afi
, safi
));
5454 table
= bgp_node_get_bgp_table_info(prn
);
5456 rn
= bgp_node_get(table
, &p
);
5458 if (bgp_node_has_bgp_path_info_data(rn
)) {
5459 vty_out(vty
, "%% Same network configuration exists\n");
5460 bgp_unlock_node(rn
);
5462 /* New configuration. */
5463 bgp_static
= bgp_static_new();
5464 bgp_static
->backdoor
= 0;
5465 bgp_static
->valid
= 0;
5466 bgp_static
->igpmetric
= 0;
5467 bgp_static
->igpnexthop
.s_addr
= 0;
5468 bgp_static
->label
= label
;
5469 bgp_static
->prd
= prd
;
5472 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5473 route_map_counter_decrement(bgp_static
->rmap
.map
);
5474 bgp_static
->rmap
.name
=
5475 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5476 bgp_static
->rmap
.map
=
5477 route_map_lookup_by_name(rmap_str
);
5478 route_map_counter_increment(bgp_static
->rmap
.map
);
5481 if (safi
== SAFI_EVPN
) {
5483 bgp_static
->eth_s_id
=
5485 sizeof(struct eth_segment_id
));
5486 str2esi(esi
, bgp_static
->eth_s_id
);
5489 bgp_static
->router_mac
=
5490 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5491 (void)prefix_str2mac(routermac
,
5492 bgp_static
->router_mac
);
5495 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5497 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5499 bgp_static
->valid
= 1;
5500 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5506 /* Configure static BGP network. */
5507 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5508 const char *ip_str
, const char *rd_str
,
5509 const char *label_str
, int evpn_type
, const char *esi
,
5510 const char *gwip
, const char *ethtag
)
5512 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5515 struct prefix_rd prd
;
5516 struct bgp_node
*prn
;
5517 struct bgp_node
*rn
;
5518 struct bgp_table
*table
;
5519 struct bgp_static
*bgp_static
;
5520 mpls_label_t label
= MPLS_INVALID_LABEL
;
5522 /* Convert IP prefix string to struct prefix. */
5523 ret
= str2prefix(ip_str
, &p
);
5525 vty_out(vty
, "%% Malformed prefix\n");
5526 return CMD_WARNING_CONFIG_FAILED
;
5529 if ((afi
== AFI_L2VPN
)
5530 && (bgp_build_evpn_prefix(evpn_type
,
5531 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5532 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5533 return CMD_WARNING_CONFIG_FAILED
;
5535 ret
= str2prefix_rd(rd_str
, &prd
);
5537 vty_out(vty
, "%% Malformed rd\n");
5538 return CMD_WARNING_CONFIG_FAILED
;
5542 unsigned long label_val
;
5543 label_val
= strtoul(label_str
, NULL
, 10);
5544 encode_label(label_val
, &label
);
5547 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5548 if (!bgp_node_has_bgp_path_info_data(prn
))
5549 bgp_node_set_bgp_table_info(prn
,
5550 bgp_table_init(bgp
, afi
, safi
));
5552 bgp_unlock_node(prn
);
5553 table
= bgp_node_get_bgp_table_info(prn
);
5555 rn
= bgp_node_lookup(table
, &p
);
5558 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5560 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5561 bgp_static_free(bgp_static
);
5562 bgp_node_set_bgp_static_info(rn
, NULL
);
5563 bgp_unlock_node(rn
);
5564 bgp_unlock_node(rn
);
5566 vty_out(vty
, "%% Can't find the route\n");
5571 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5572 const char *rmap_name
)
5574 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5575 struct bgp_rmap
*rmap
;
5577 rmap
= &bgp
->table_map
[afi
][safi
];
5579 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5580 route_map_counter_decrement(rmap
->map
);
5581 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5582 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5583 route_map_counter_increment(rmap
->map
);
5585 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5586 route_map_counter_decrement(rmap
->map
);
5591 if (bgp_fibupd_safi(safi
))
5592 bgp_zebra_announce_table(bgp
, afi
, safi
);
5597 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5598 const char *rmap_name
)
5600 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5601 struct bgp_rmap
*rmap
;
5603 rmap
= &bgp
->table_map
[afi
][safi
];
5604 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5605 route_map_counter_decrement(rmap
->map
);
5609 if (bgp_fibupd_safi(safi
))
5610 bgp_zebra_announce_table(bgp
, afi
, safi
);
5615 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5618 if (bgp
->table_map
[afi
][safi
].name
) {
5619 vty_out(vty
, " table-map %s\n",
5620 bgp
->table_map
[afi
][safi
].name
);
5624 DEFUN (bgp_table_map
,
5627 "BGP table to RIB route download filter\n"
5628 "Name of the route map\n")
5631 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5632 argv
[idx_word
]->arg
);
5634 DEFUN (no_bgp_table_map
,
5635 no_bgp_table_map_cmd
,
5636 "no table-map WORD",
5638 "BGP table to RIB route download filter\n"
5639 "Name of the route map\n")
5642 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5643 argv
[idx_word
]->arg
);
5649 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5650 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5651 backdoor$backdoor}]",
5653 "Specify a network to announce via BGP\n"
5658 "Route-map to modify the attributes\n"
5659 "Name of the route map\n"
5660 "Label index to associate with the prefix\n"
5661 "Label index value\n"
5662 "Specify a BGP backdoor route\n")
5664 char addr_prefix_str
[BUFSIZ
];
5669 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5672 vty_out(vty
, "%% Inconsistent address and mask\n");
5673 return CMD_WARNING_CONFIG_FAILED
;
5677 return bgp_static_set(
5678 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5679 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5680 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5683 DEFPY(ipv6_bgp_network
,
5684 ipv6_bgp_network_cmd
,
5685 "[no] network X:X::X:X/M$prefix \
5686 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5688 "Specify a network to announce via BGP\n"
5690 "Route-map to modify the attributes\n"
5691 "Name of the route map\n"
5692 "Label index to associate with the prefix\n"
5693 "Label index value\n")
5695 return bgp_static_set(
5696 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5697 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5700 static struct bgp_aggregate
*bgp_aggregate_new(void)
5702 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5705 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5707 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
5708 route_map_counter_decrement(aggregate
->rmap
.map
);
5709 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5712 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5713 struct aspath
*aspath
,
5714 struct community
*comm
,
5715 struct ecommunity
*ecomm
,
5716 struct lcommunity
*lcomm
)
5718 static struct aspath
*ae
= NULL
;
5721 ae
= aspath_empty();
5726 if (origin
!= pi
->attr
->origin
)
5729 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5732 if (!community_cmp(pi
->attr
->community
, comm
))
5735 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5738 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5741 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5747 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5748 struct prefix
*p
, uint8_t origin
,
5749 struct aspath
*aspath
,
5750 struct community
*community
,
5751 struct ecommunity
*ecommunity
,
5752 struct lcommunity
*lcommunity
,
5753 uint8_t atomic_aggregate
,
5754 struct bgp_aggregate
*aggregate
)
5756 struct bgp_node
*rn
;
5757 struct bgp_table
*table
;
5758 struct bgp_path_info
*pi
, *orig
, *new;
5761 table
= bgp
->rib
[afi
][safi
];
5763 rn
= bgp_node_get(table
, p
);
5765 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5766 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5767 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5770 if (aggregate
->count
> 0) {
5772 * If the aggregate information has not changed
5773 * no need to re-install it again.
5775 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5776 ecommunity
, lcommunity
)) {
5777 bgp_unlock_node(rn
);
5780 aspath_free(aspath
);
5782 community_free(&community
);
5784 ecommunity_free(&ecommunity
);
5786 lcommunity_free(&lcommunity
);
5792 * Mark the old as unusable
5795 bgp_path_info_delete(rn
, pi
);
5797 attr
= bgp_attr_aggregate_intern(
5798 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
5799 aggregate
, atomic_aggregate
, p
);
5802 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
5806 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5807 bgp
->peer_self
, attr
, rn
);
5809 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5811 bgp_path_info_add(rn
, new);
5812 bgp_process(bgp
, rn
, afi
, safi
);
5814 for (pi
= orig
; pi
; pi
= pi
->next
)
5815 if (pi
->peer
== bgp
->peer_self
5816 && pi
->type
== ZEBRA_ROUTE_BGP
5817 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5820 /* Withdraw static BGP route from routing table. */
5822 bgp_path_info_delete(rn
, pi
);
5823 bgp_process(bgp
, rn
, afi
, safi
);
5827 bgp_unlock_node(rn
);
5830 /* Update an aggregate as routes are added/removed from the BGP table */
5831 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5832 afi_t afi
, safi_t safi
,
5833 struct bgp_aggregate
*aggregate
)
5835 struct bgp_table
*table
;
5836 struct bgp_node
*top
;
5837 struct bgp_node
*rn
;
5839 struct aspath
*aspath
= NULL
;
5840 struct community
*community
= NULL
;
5841 struct ecommunity
*ecommunity
= NULL
;
5842 struct lcommunity
*lcommunity
= NULL
;
5843 struct bgp_path_info
*pi
;
5844 unsigned long match
= 0;
5845 uint8_t atomic_aggregate
= 0;
5847 /* If the bgp instance is being deleted or self peer is deleted
5848 * then do not create aggregate route
5850 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5851 (bgp
->peer_self
== NULL
))
5854 /* ORIGIN attribute: If at least one route among routes that are
5855 aggregated has ORIGIN with the value INCOMPLETE, then the
5856 aggregated route must have the ORIGIN attribute with the value
5857 INCOMPLETE. Otherwise, if at least one route among routes that
5858 are aggregated has ORIGIN with the value EGP, then the aggregated
5859 route must have the origin attribute with the value EGP. In all
5860 other case the value of the ORIGIN attribute of the aggregated
5861 route is INTERNAL. */
5862 origin
= BGP_ORIGIN_IGP
;
5864 table
= bgp
->rib
[afi
][safi
];
5866 top
= bgp_node_get(table
, p
);
5867 for (rn
= bgp_node_get(table
, p
); rn
;
5868 rn
= bgp_route_next_until(rn
, top
)) {
5869 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5874 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5875 if (BGP_PATH_HOLDDOWN(pi
))
5879 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5880 atomic_aggregate
= 1;
5882 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5886 * summary-only aggregate route suppress
5887 * aggregated route announcements.
5889 if (aggregate
->summary_only
) {
5890 (bgp_path_info_extra_get(pi
))->suppress
++;
5891 bgp_path_info_set_flag(rn
, pi
,
5892 BGP_PATH_ATTR_CHANGED
);
5899 * If at least one route among routes that are
5900 * aggregated has ORIGIN with the value INCOMPLETE,
5901 * then the aggregated route MUST have the ORIGIN
5902 * attribute with the value INCOMPLETE. Otherwise, if
5903 * at least one route among routes that are aggregated
5904 * has ORIGIN with the value EGP, then the aggregated
5905 * route MUST have the ORIGIN attribute with the value
5908 switch (pi
->attr
->origin
) {
5909 case BGP_ORIGIN_INCOMPLETE
:
5910 aggregate
->incomplete_origin_count
++;
5912 case BGP_ORIGIN_EGP
:
5913 aggregate
->egp_origin_count
++;
5921 if (!aggregate
->as_set
)
5925 * as-set aggregate route generate origin, as path,
5926 * and community aggregation.
5928 /* Compute aggregate route's as-path.
5930 bgp_compute_aggregate_aspath(aggregate
,
5933 /* Compute aggregate route's community.
5935 if (pi
->attr
->community
)
5936 bgp_compute_aggregate_community(
5938 pi
->attr
->community
);
5940 /* Compute aggregate route's extended community.
5942 if (pi
->attr
->ecommunity
)
5943 bgp_compute_aggregate_ecommunity(
5945 pi
->attr
->ecommunity
);
5947 /* Compute aggregate route's large community.
5949 if (pi
->attr
->lcommunity
)
5950 bgp_compute_aggregate_lcommunity(
5952 pi
->attr
->lcommunity
);
5955 bgp_process(bgp
, rn
, afi
, safi
);
5957 bgp_unlock_node(top
);
5960 if (aggregate
->incomplete_origin_count
> 0)
5961 origin
= BGP_ORIGIN_INCOMPLETE
;
5962 else if (aggregate
->egp_origin_count
> 0)
5963 origin
= BGP_ORIGIN_EGP
;
5965 if (aggregate
->as_set
) {
5966 if (aggregate
->aspath
)
5967 /* Retrieve aggregate route's as-path.
5969 aspath
= aspath_dup(aggregate
->aspath
);
5971 if (aggregate
->community
)
5972 /* Retrieve aggregate route's community.
5974 community
= community_dup(aggregate
->community
);
5976 if (aggregate
->ecommunity
)
5977 /* Retrieve aggregate route's ecommunity.
5979 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
5981 if (aggregate
->lcommunity
)
5982 /* Retrieve aggregate route's lcommunity.
5984 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
5987 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5988 ecommunity
, lcommunity
, atomic_aggregate
,
5992 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5993 safi_t safi
, struct bgp_aggregate
*aggregate
)
5995 struct bgp_table
*table
;
5996 struct bgp_node
*top
;
5997 struct bgp_node
*rn
;
5998 struct bgp_path_info
*pi
;
5999 unsigned long match
;
6001 table
= bgp
->rib
[afi
][safi
];
6003 /* If routes exists below this node, generate aggregate routes. */
6004 top
= bgp_node_get(table
, p
);
6005 for (rn
= bgp_node_get(table
, p
); rn
;
6006 rn
= bgp_route_next_until(rn
, top
)) {
6007 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6011 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6012 if (BGP_PATH_HOLDDOWN(pi
))
6015 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6018 if (aggregate
->summary_only
&& pi
->extra
) {
6019 pi
->extra
->suppress
--;
6021 if (pi
->extra
->suppress
== 0) {
6022 bgp_path_info_set_flag(
6023 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6029 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6030 aggregate
->incomplete_origin_count
--;
6031 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6032 aggregate
->egp_origin_count
--;
6034 if (aggregate
->as_set
) {
6035 /* Remove as-path from aggregate.
6037 bgp_remove_aspath_from_aggregate(
6041 if (pi
->attr
->community
)
6042 /* Remove community from aggregate.
6044 bgp_remove_community_from_aggregate(
6046 pi
->attr
->community
);
6048 if (pi
->attr
->ecommunity
)
6049 /* Remove ecommunity from aggregate.
6051 bgp_remove_ecommunity_from_aggregate(
6053 pi
->attr
->ecommunity
);
6055 if (pi
->attr
->lcommunity
)
6056 /* Remove lcommunity from aggregate.
6058 bgp_remove_lcommunity_from_aggregate(
6060 pi
->attr
->lcommunity
);
6065 /* If this node was suppressed, process the change. */
6067 bgp_process(bgp
, rn
, afi
, safi
);
6069 bgp_unlock_node(top
);
6072 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6073 struct bgp_path_info
*pinew
, afi_t afi
,
6075 struct bgp_aggregate
*aggregate
)
6078 struct aspath
*aspath
= NULL
;
6079 uint8_t atomic_aggregate
= 0;
6080 struct community
*community
= NULL
;
6081 struct ecommunity
*ecommunity
= NULL
;
6082 struct lcommunity
*lcommunity
= NULL
;
6084 /* ORIGIN attribute: If at least one route among routes that are
6085 * aggregated has ORIGIN with the value INCOMPLETE, then the
6086 * aggregated route must have the ORIGIN attribute with the value
6087 * INCOMPLETE. Otherwise, if at least one route among routes that
6088 * are aggregated has ORIGIN with the value EGP, then the aggregated
6089 * route must have the origin attribute with the value EGP. In all
6090 * other case the value of the ORIGIN attribute of the aggregated
6091 * route is INTERNAL.
6093 origin
= BGP_ORIGIN_IGP
;
6097 if (aggregate
->summary_only
)
6098 (bgp_path_info_extra_get(pinew
))->suppress
++;
6100 switch (pinew
->attr
->origin
) {
6101 case BGP_ORIGIN_INCOMPLETE
:
6102 aggregate
->incomplete_origin_count
++;
6104 case BGP_ORIGIN_EGP
:
6105 aggregate
->egp_origin_count
++;
6113 if (aggregate
->incomplete_origin_count
> 0)
6114 origin
= BGP_ORIGIN_INCOMPLETE
;
6115 else if (aggregate
->egp_origin_count
> 0)
6116 origin
= BGP_ORIGIN_EGP
;
6118 if (aggregate
->as_set
) {
6119 /* Compute aggregate route's as-path.
6121 bgp_compute_aggregate_aspath(aggregate
,
6122 pinew
->attr
->aspath
);
6124 /* Compute aggregate route's community.
6126 if (pinew
->attr
->community
)
6127 bgp_compute_aggregate_community(
6129 pinew
->attr
->community
);
6131 /* Compute aggregate route's extended community.
6133 if (pinew
->attr
->ecommunity
)
6134 bgp_compute_aggregate_ecommunity(
6136 pinew
->attr
->ecommunity
);
6138 /* Compute aggregate route's large community.
6140 if (pinew
->attr
->lcommunity
)
6141 bgp_compute_aggregate_lcommunity(
6143 pinew
->attr
->lcommunity
);
6145 /* Retrieve aggregate route's as-path.
6147 if (aggregate
->aspath
)
6148 aspath
= aspath_dup(aggregate
->aspath
);
6150 /* Retrieve aggregate route's community.
6152 if (aggregate
->community
)
6153 community
= community_dup(aggregate
->community
);
6155 /* Retrieve aggregate route's ecommunity.
6157 if (aggregate
->ecommunity
)
6158 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6160 /* Retrieve aggregate route's lcommunity.
6162 if (aggregate
->lcommunity
)
6163 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6166 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6167 aspath
, community
, ecommunity
,
6168 lcommunity
, atomic_aggregate
, aggregate
);
6171 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6173 struct bgp_path_info
*pi
,
6174 struct bgp_aggregate
*aggregate
,
6175 struct prefix
*aggr_p
)
6178 struct aspath
*aspath
= NULL
;
6179 uint8_t atomic_aggregate
= 0;
6180 struct community
*community
= NULL
;
6181 struct ecommunity
*ecommunity
= NULL
;
6182 struct lcommunity
*lcommunity
= NULL
;
6183 unsigned long match
= 0;
6185 if (BGP_PATH_HOLDDOWN(pi
))
6188 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6191 if (aggregate
->summary_only
6193 && pi
->extra
->suppress
> 0) {
6194 pi
->extra
->suppress
--;
6196 if (pi
->extra
->suppress
== 0) {
6197 bgp_path_info_set_flag(pi
->net
, pi
,
6198 BGP_PATH_ATTR_CHANGED
);
6203 if (aggregate
->count
> 0)
6206 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6207 aggregate
->incomplete_origin_count
--;
6208 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6209 aggregate
->egp_origin_count
--;
6211 if (aggregate
->as_set
) {
6212 /* Remove as-path from aggregate.
6214 bgp_remove_aspath_from_aggregate(aggregate
,
6217 if (pi
->attr
->community
)
6218 /* Remove community from aggregate.
6220 bgp_remove_community_from_aggregate(
6222 pi
->attr
->community
);
6224 if (pi
->attr
->ecommunity
)
6225 /* Remove ecommunity from aggregate.
6227 bgp_remove_ecommunity_from_aggregate(
6229 pi
->attr
->ecommunity
);
6231 if (pi
->attr
->lcommunity
)
6232 /* Remove lcommunity from aggregate.
6234 bgp_remove_lcommunity_from_aggregate(
6236 pi
->attr
->lcommunity
);
6239 /* If this node was suppressed, process the change. */
6241 bgp_process(bgp
, pi
->net
, afi
, safi
);
6243 origin
= BGP_ORIGIN_IGP
;
6244 if (aggregate
->incomplete_origin_count
> 0)
6245 origin
= BGP_ORIGIN_INCOMPLETE
;
6246 else if (aggregate
->egp_origin_count
> 0)
6247 origin
= BGP_ORIGIN_EGP
;
6249 if (aggregate
->as_set
) {
6250 /* Retrieve aggregate route's as-path.
6252 if (aggregate
->aspath
)
6253 aspath
= aspath_dup(aggregate
->aspath
);
6255 /* Retrieve aggregate route's community.
6257 if (aggregate
->community
)
6258 community
= community_dup(aggregate
->community
);
6260 /* Retrieve aggregate route's ecommunity.
6262 if (aggregate
->ecommunity
)
6263 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6265 /* Retrieve aggregate route's lcommunity.
6267 if (aggregate
->lcommunity
)
6268 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6271 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6272 aspath
, community
, ecommunity
,
6273 lcommunity
, atomic_aggregate
, aggregate
);
6276 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6277 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6279 struct bgp_node
*child
;
6280 struct bgp_node
*rn
;
6281 struct bgp_aggregate
*aggregate
;
6282 struct bgp_table
*table
;
6284 table
= bgp
->aggregate
[afi
][safi
];
6286 /* No aggregates configured. */
6287 if (bgp_table_top_nolock(table
) == NULL
)
6290 if (p
->prefixlen
== 0)
6293 if (BGP_PATH_HOLDDOWN(pi
))
6296 child
= bgp_node_get(table
, p
);
6298 /* Aggregate address configuration check. */
6299 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6300 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6301 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6302 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6306 bgp_unlock_node(child
);
6309 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6310 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6312 struct bgp_node
*child
;
6313 struct bgp_node
*rn
;
6314 struct bgp_aggregate
*aggregate
;
6315 struct bgp_table
*table
;
6317 table
= bgp
->aggregate
[afi
][safi
];
6319 /* No aggregates configured. */
6320 if (bgp_table_top_nolock(table
) == NULL
)
6323 if (p
->prefixlen
== 0)
6326 child
= bgp_node_get(table
, p
);
6328 /* Aggregate address configuration check. */
6329 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6330 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6331 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6332 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6333 del
, aggregate
, &rn
->p
);
6336 bgp_unlock_node(child
);
6339 /* Aggregate route attribute. */
6340 #define AGGREGATE_SUMMARY_ONLY 1
6341 #define AGGREGATE_AS_SET 1
6343 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6344 afi_t afi
, safi_t safi
)
6346 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6349 struct bgp_node
*rn
;
6350 struct bgp_aggregate
*aggregate
;
6352 /* Convert string to prefix structure. */
6353 ret
= str2prefix(prefix_str
, &p
);
6355 vty_out(vty
, "Malformed prefix\n");
6356 return CMD_WARNING_CONFIG_FAILED
;
6360 /* Old configuration check. */
6361 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6364 "%% There is no aggregate-address configuration.\n");
6365 return CMD_WARNING_CONFIG_FAILED
;
6368 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6369 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6370 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6371 NULL
, NULL
, 0, aggregate
);
6373 /* Unlock aggregate address configuration. */
6374 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6376 if (aggregate
->community
)
6377 community_free(&aggregate
->community
);
6379 if (aggregate
->community_hash
) {
6380 /* Delete all communities in the hash.
6382 hash_clean(aggregate
->community_hash
,
6383 bgp_aggr_community_remove
);
6384 /* Free up the community_hash.
6386 hash_free(aggregate
->community_hash
);
6389 if (aggregate
->ecommunity
)
6390 ecommunity_free(&aggregate
->ecommunity
);
6392 if (aggregate
->ecommunity_hash
) {
6393 /* Delete all ecommunities in the hash.
6395 hash_clean(aggregate
->ecommunity_hash
,
6396 bgp_aggr_ecommunity_remove
);
6397 /* Free up the ecommunity_hash.
6399 hash_free(aggregate
->ecommunity_hash
);
6402 if (aggregate
->lcommunity
)
6403 lcommunity_free(&aggregate
->lcommunity
);
6405 if (aggregate
->lcommunity_hash
) {
6406 /* Delete all lcommunities in the hash.
6408 hash_clean(aggregate
->lcommunity_hash
,
6409 bgp_aggr_lcommunity_remove
);
6410 /* Free up the lcommunity_hash.
6412 hash_free(aggregate
->lcommunity_hash
);
6415 if (aggregate
->aspath
)
6416 aspath_free(aggregate
->aspath
);
6418 if (aggregate
->aspath_hash
) {
6419 /* Delete all as-paths in the hash.
6421 hash_clean(aggregate
->aspath_hash
,
6422 bgp_aggr_aspath_remove
);
6423 /* Free up the aspath_hash.
6425 hash_free(aggregate
->aspath_hash
);
6428 bgp_aggregate_free(aggregate
);
6429 bgp_unlock_node(rn
);
6430 bgp_unlock_node(rn
);
6435 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6436 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6439 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6442 struct bgp_node
*rn
;
6443 struct bgp_aggregate
*aggregate
;
6445 /* Convert string to prefix structure. */
6446 ret
= str2prefix(prefix_str
, &p
);
6448 vty_out(vty
, "Malformed prefix\n");
6449 return CMD_WARNING_CONFIG_FAILED
;
6453 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6454 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6455 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6457 return CMD_WARNING_CONFIG_FAILED
;
6460 /* Old configuration check. */
6461 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6462 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6465 vty_out(vty
, "There is already same aggregate network.\n");
6466 /* try to remove the old entry */
6467 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6469 vty_out(vty
, "Error deleting aggregate.\n");
6470 bgp_unlock_node(rn
);
6471 return CMD_WARNING_CONFIG_FAILED
;
6475 /* Make aggregate address structure. */
6476 aggregate
= bgp_aggregate_new();
6477 aggregate
->summary_only
= summary_only
;
6478 aggregate
->as_set
= as_set
;
6479 aggregate
->safi
= safi
;
6482 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6483 route_map_counter_decrement(aggregate
->rmap
.map
);
6484 aggregate
->rmap
.name
=
6485 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6486 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6487 route_map_counter_increment(aggregate
->rmap
.map
);
6489 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6491 /* Aggregate address insert into BGP routing table. */
6492 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6497 DEFUN (aggregate_address
,
6498 aggregate_address_cmd
,
6499 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6500 "Configure BGP aggregate entries\n"
6501 "Aggregate prefix\n"
6502 "Generate AS set path information\n"
6503 "Filter more specific routes from updates\n"
6504 "Filter more specific routes from updates\n"
6505 "Generate AS set path information\n"
6506 "Apply route map to aggregate network\n"
6507 "Name of route map\n")
6510 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6511 char *prefix
= argv
[idx
]->arg
;
6514 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6516 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6517 ? AGGREGATE_SUMMARY_ONLY
6521 argv_find(argv
, argc
, "WORD", &idx
);
6523 rmap
= argv
[idx
]->arg
;
6525 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6526 rmap
, summary_only
, as_set
);
6529 DEFUN (aggregate_address_mask
,
6530 aggregate_address_mask_cmd
,
6531 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6532 "Configure BGP aggregate entries\n"
6533 "Aggregate address\n"
6535 "Generate AS set path information\n"
6536 "Filter more specific routes from updates\n"
6537 "Filter more specific routes from updates\n"
6538 "Generate AS set path information\n"
6539 "Apply route map to aggregate network\n"
6540 "Name of route map\n")
6543 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6544 char *prefix
= argv
[idx
]->arg
;
6545 char *mask
= argv
[idx
+ 1]->arg
;
6549 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6551 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6552 ? AGGREGATE_SUMMARY_ONLY
6555 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6557 rmap
= argv
[idx
]->arg
;
6559 char prefix_str
[BUFSIZ
];
6560 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6563 vty_out(vty
, "%% Inconsistent address and mask\n");
6564 return CMD_WARNING_CONFIG_FAILED
;
6567 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6568 rmap
, summary_only
, as_set
);
6571 DEFUN (no_aggregate_address
,
6572 no_aggregate_address_cmd
,
6573 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6575 "Configure BGP aggregate entries\n"
6576 "Aggregate prefix\n"
6577 "Generate AS set path information\n"
6578 "Filter more specific routes from updates\n"
6579 "Filter more specific routes from updates\n"
6580 "Generate AS set path information\n")
6583 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6584 char *prefix
= argv
[idx
]->arg
;
6585 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6588 DEFUN (no_aggregate_address_mask
,
6589 no_aggregate_address_mask_cmd
,
6590 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6592 "Configure BGP aggregate entries\n"
6593 "Aggregate address\n"
6595 "Generate AS set path information\n"
6596 "Filter more specific routes from updates\n"
6597 "Filter more specific routes from updates\n"
6598 "Generate AS set path information\n")
6601 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6602 char *prefix
= argv
[idx
]->arg
;
6603 char *mask
= argv
[idx
+ 1]->arg
;
6605 char prefix_str
[BUFSIZ
];
6606 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6609 vty_out(vty
, "%% Inconsistent address and mask\n");
6610 return CMD_WARNING_CONFIG_FAILED
;
6613 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6616 DEFUN (ipv6_aggregate_address
,
6617 ipv6_aggregate_address_cmd
,
6618 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6619 "Configure BGP aggregate entries\n"
6620 "Aggregate prefix\n"
6621 "Generate AS set path information\n"
6622 "Filter more specific routes from updates\n"
6623 "Filter more specific routes from updates\n"
6624 "Generate AS set path information\n"
6625 "Apply route map to aggregate network\n"
6626 "Name of route map\n")
6629 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6630 char *prefix
= argv
[idx
]->arg
;
6634 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6637 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6638 ? AGGREGATE_SUMMARY_ONLY
6641 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6643 rmap
= argv
[idx
]->arg
;
6645 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6649 DEFUN (no_ipv6_aggregate_address
,
6650 no_ipv6_aggregate_address_cmd
,
6651 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>]",
6653 "Configure BGP aggregate entries\n"
6654 "Aggregate prefix\n"
6655 "Generate AS set path information\n"
6656 "Filter more specific routes from updates\n"
6657 "Filter more specific routes from updates\n"
6658 "Generate AS set path information\n")
6661 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6662 char *prefix
= argv
[idx
]->arg
;
6663 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6666 /* Redistribute route treatment. */
6667 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6668 const union g_addr
*nexthop
, ifindex_t ifindex
,
6669 enum nexthop_types_t nhtype
, uint32_t metric
,
6670 uint8_t type
, unsigned short instance
,
6673 struct bgp_path_info
*new;
6674 struct bgp_path_info
*bpi
;
6675 struct bgp_path_info rmap_path
;
6676 struct bgp_node
*bn
;
6678 struct attr
*new_attr
;
6680 route_map_result_t ret
;
6681 struct bgp_redist
*red
;
6683 /* Make default attribute. */
6684 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6687 case NEXTHOP_TYPE_IFINDEX
:
6689 case NEXTHOP_TYPE_IPV4
:
6690 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6691 attr
.nexthop
= nexthop
->ipv4
;
6693 case NEXTHOP_TYPE_IPV6
:
6694 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6695 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6696 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6698 case NEXTHOP_TYPE_BLACKHOLE
:
6699 switch (p
->family
) {
6701 attr
.nexthop
.s_addr
= INADDR_ANY
;
6704 memset(&attr
.mp_nexthop_global
, 0,
6705 sizeof(attr
.mp_nexthop_global
));
6706 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6711 attr
.nh_ifindex
= ifindex
;
6714 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6717 afi
= family2afi(p
->family
);
6719 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6721 struct attr attr_new
;
6723 /* Copy attribute for modification. */
6724 bgp_attr_dup(&attr_new
, &attr
);
6726 if (red
->redist_metric_flag
)
6727 attr_new
.med
= red
->redist_metric
;
6729 /* Apply route-map. */
6730 if (red
->rmap
.name
) {
6731 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6732 rmap_path
.peer
= bgp
->peer_self
;
6733 rmap_path
.attr
= &attr_new
;
6735 SET_FLAG(bgp
->peer_self
->rmap_type
,
6736 PEER_RMAP_TYPE_REDISTRIBUTE
);
6738 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6741 bgp
->peer_self
->rmap_type
= 0;
6743 if (ret
== RMAP_DENYMATCH
) {
6744 /* Free uninterned attribute. */
6745 bgp_attr_flush(&attr_new
);
6747 /* Unintern original. */
6748 aspath_unintern(&attr
.aspath
);
6749 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6754 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6755 bgp_attr_add_gshut_community(&attr_new
);
6757 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6758 SAFI_UNICAST
, p
, NULL
);
6760 new_attr
= bgp_attr_intern(&attr_new
);
6762 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6764 if (bpi
->peer
== bgp
->peer_self
6765 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6769 /* Ensure the (source route) type is updated. */
6771 if (attrhash_cmp(bpi
->attr
, new_attr
)
6772 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6773 bgp_attr_unintern(&new_attr
);
6774 aspath_unintern(&attr
.aspath
);
6775 bgp_unlock_node(bn
);
6778 /* The attribute is changed. */
6779 bgp_path_info_set_flag(bn
, bpi
,
6780 BGP_PATH_ATTR_CHANGED
);
6782 /* Rewrite BGP route information. */
6783 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6784 bgp_path_info_restore(bn
, bpi
);
6786 bgp_aggregate_decrement(
6787 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6788 bgp_attr_unintern(&bpi
->attr
);
6789 bpi
->attr
= new_attr
;
6790 bpi
->uptime
= bgp_clock();
6792 /* Process change. */
6793 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6795 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6796 bgp_unlock_node(bn
);
6797 aspath_unintern(&attr
.aspath
);
6799 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6801 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6803 vpn_leak_from_vrf_update(
6804 bgp_get_default(), bgp
, bpi
);
6810 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6811 bgp
->peer_self
, new_attr
, bn
);
6812 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6814 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6815 bgp_path_info_add(bn
, new);
6816 bgp_unlock_node(bn
);
6817 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6819 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6820 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6822 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6826 /* Unintern original. */
6827 aspath_unintern(&attr
.aspath
);
6830 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6831 unsigned short instance
)
6834 struct bgp_node
*rn
;
6835 struct bgp_path_info
*pi
;
6836 struct bgp_redist
*red
;
6838 afi
= family2afi(p
->family
);
6840 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6842 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6843 SAFI_UNICAST
, p
, NULL
);
6845 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6846 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6850 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6851 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6853 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6856 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6857 bgp_path_info_delete(rn
, pi
);
6858 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6860 bgp_unlock_node(rn
);
6864 /* Withdraw specified route type's route. */
6865 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6866 unsigned short instance
)
6868 struct bgp_node
*rn
;
6869 struct bgp_path_info
*pi
;
6870 struct bgp_table
*table
;
6872 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6874 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6875 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6876 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6877 && pi
->instance
== instance
)
6881 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6882 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6884 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6887 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6889 bgp_path_info_delete(rn
, pi
);
6890 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6895 /* Static function to display route. */
6896 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6903 if (p
->family
== AF_INET
) {
6907 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6910 json_object_string_add(json
, "prefix",
6911 inet_ntop(p
->family
,
6914 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6915 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6916 json_object_string_add(json
, "network", buf2
);
6918 } else if (p
->family
== AF_ETHERNET
) {
6919 prefix2str(p
, buf
, PREFIX_STRLEN
);
6920 len
= vty_out(vty
, "%s", buf
);
6921 } else if (p
->family
== AF_EVPN
) {
6925 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6928 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6929 } else if (p
->family
== AF_FLOWSPEC
) {
6930 route_vty_out_flowspec(vty
, p
, NULL
,
6932 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6933 NLRI_STRING_FORMAT_MIN
, json
);
6938 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6941 json_object_string_add(json
, "prefix",
6942 inet_ntop(p
->family
,
6945 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6946 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6947 json_object_string_add(json
, "network", buf2
);
6954 vty_out(vty
, "\n%*s", 20, " ");
6956 vty_out(vty
, "%*s", len
, " ");
6960 enum bgp_display_type
{
6964 /* Print the short form route status for a bgp_path_info */
6965 static void route_vty_short_status_out(struct vty
*vty
,
6966 struct bgp_path_info
*path
,
6967 json_object
*json_path
)
6971 /* Route status display. */
6972 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6973 json_object_boolean_true_add(json_path
, "removed");
6975 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6976 json_object_boolean_true_add(json_path
, "stale");
6978 if (path
->extra
&& path
->extra
->suppress
)
6979 json_object_boolean_true_add(json_path
, "suppressed");
6981 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6982 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6983 json_object_boolean_true_add(json_path
, "valid");
6986 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6987 json_object_boolean_true_add(json_path
, "history");
6989 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6990 json_object_boolean_true_add(json_path
, "damped");
6992 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6993 json_object_boolean_true_add(json_path
, "bestpath");
6995 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6996 json_object_boolean_true_add(json_path
, "multipath");
6998 /* Internal route. */
6999 if ((path
->peer
->as
)
7000 && (path
->peer
->as
== path
->peer
->local_as
))
7001 json_object_string_add(json_path
, "pathFrom",
7004 json_object_string_add(json_path
, "pathFrom",
7010 /* Route status display. */
7011 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7013 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7015 else if (path
->extra
&& path
->extra
->suppress
)
7017 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7018 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7024 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7026 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7028 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7030 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7035 /* Internal route. */
7036 if (path
->peer
&& (path
->peer
->as
)
7037 && (path
->peer
->as
== path
->peer
->local_as
))
7043 static char *bgp_nexthop_fqdn(struct peer
*peer
)
7045 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
))
7046 return peer
->hostname
;
7050 /* called from terminal list command */
7051 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7052 struct bgp_path_info
*path
, int display
, safi_t safi
,
7053 json_object
*json_paths
)
7056 json_object
*json_path
= NULL
;
7057 json_object
*json_nexthops
= NULL
;
7058 json_object
*json_nexthop_global
= NULL
;
7059 json_object
*json_nexthop_ll
= NULL
;
7060 json_object
*json_ext_community
= NULL
;
7061 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7063 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7064 bool nexthop_othervrf
= false;
7065 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7066 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7067 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
7070 json_path
= json_object_new_object();
7072 /* short status lead text */
7073 route_vty_short_status_out(vty
, path
, json_path
);
7076 /* print prefix and mask */
7078 route_vty_out_route(p
, vty
, json_path
);
7080 vty_out(vty
, "%*s", 17, " ");
7082 route_vty_out_route(p
, vty
, json_path
);
7085 /* Print attribute */
7089 json_object_array_add(json_paths
, json_path
);
7097 * If vrf id of nexthop is different from that of prefix,
7098 * set up printable string to append
7100 if (path
->extra
&& path
->extra
->bgp_orig
) {
7101 const char *self
= "";
7106 nexthop_othervrf
= true;
7107 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7109 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7110 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7111 "@%s%s", VRFID_NONE_STR
, self
);
7113 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7114 path
->extra
->bgp_orig
->vrf_id
, self
);
7116 if (path
->extra
->bgp_orig
->inst_type
7117 != BGP_INSTANCE_TYPE_DEFAULT
)
7119 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7121 const char *self
= "";
7126 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7130 * For ENCAP and EVPN routes, nexthop address family is not
7131 * neccessarily the same as the prefix address family.
7132 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7133 * EVPN routes are also exchanged with a MP nexthop. Currently,
7135 * is only IPv4, the value will be present in either
7137 * attr->mp_nexthop_global_in
7139 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7142 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7146 sprintf(nexthop
, "%s",
7147 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7151 sprintf(nexthop
, "%s",
7152 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7156 sprintf(nexthop
, "?");
7161 json_nexthop_global
= json_object_new_object();
7163 json_object_string_add(
7164 json_nexthop_global
, "afi",
7165 nexthop_fqdn
? "fqdn"
7166 : (af
== AF_INET
) ? "ip" : "ipv6");
7167 json_object_string_add(
7168 json_nexthop_global
,
7169 nexthop_fqdn
? "fqdn"
7170 : (af
== AF_INET
) ? "ip" : "ipv6",
7171 nexthop_fqdn
? nexthop_fqdn
: nexthop
);
7172 json_object_boolean_true_add(json_nexthop_global
,
7175 vty_out(vty
, "%s%s",
7176 nexthop_fqdn
? nexthop_fqdn
: nexthop
,
7178 } else if (safi
== SAFI_EVPN
) {
7180 json_nexthop_global
= json_object_new_object();
7182 json_object_string_add(
7183 json_nexthop_global
,
7184 nexthop_fqdn
? "fqdn" : "ip",
7185 nexthop_fqdn
? nexthop_fqdn
7186 : inet_ntoa(attr
->nexthop
));
7187 json_object_string_add(json_nexthop_global
, "afi",
7189 json_object_boolean_true_add(json_nexthop_global
,
7192 vty_out(vty
, "%-16s%s",
7193 nexthop_fqdn
?: inet_ntoa(attr
->nexthop
),
7195 } else if (safi
== SAFI_FLOWSPEC
) {
7196 if (attr
->nexthop
.s_addr
!= 0) {
7198 json_nexthop_global
= json_object_new_object();
7199 json_object_string_add(
7200 json_nexthop_global
,
7201 nexthop_fqdn
? "fqdn" : "ip",
7204 : inet_ntoa(attr
->nexthop
));
7205 json_object_string_add(json_nexthop_global
,
7207 json_object_boolean_true_add(
7208 json_nexthop_global
,
7211 vty_out(vty
, "%-16s",
7214 : inet_ntoa(attr
->nexthop
));
7217 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7219 json_nexthop_global
= json_object_new_object();
7221 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
7222 json_object_string_add(
7223 json_nexthop_global
,
7224 nexthop_fqdn
? "fqdn" : "ip",
7228 attr
->mp_nexthop_global_in
));
7230 json_object_string_add(
7231 json_nexthop_global
,
7232 nexthop_fqdn
? "fqdn" : "ip",
7235 : inet_ntoa(attr
->nexthop
));
7237 json_object_string_add(json_nexthop_global
, "afi",
7239 json_object_boolean_true_add(json_nexthop_global
,
7244 snprintf(buf
, sizeof(buf
), "%s%s",
7245 nexthop_fqdn
? nexthop_fqdn
7246 : inet_ntoa(attr
->nexthop
),
7248 vty_out(vty
, "%-16s", buf
);
7253 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7258 json_nexthop_global
= json_object_new_object();
7259 json_object_string_add(
7260 json_nexthop_global
,
7261 nexthop_fqdn
? "fqdn" : "ip",
7264 : inet_ntop(AF_INET6
,
7265 &attr
->mp_nexthop_global
,
7267 json_object_string_add(json_nexthop_global
, "afi",
7269 json_object_string_add(json_nexthop_global
, "scope",
7272 /* We display both LL & GL if both have been
7274 if ((attr
->mp_nexthop_len
== 32)
7275 || (path
->peer
->conf_if
)) {
7276 json_nexthop_ll
= json_object_new_object();
7277 json_object_string_add(
7279 nexthop_fqdn
? "fqdn" : "ip",
7284 &attr
->mp_nexthop_local
,
7286 json_object_string_add(json_nexthop_ll
, "afi",
7288 json_object_string_add(json_nexthop_ll
, "scope",
7291 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7292 &attr
->mp_nexthop_local
)
7294 && !attr
->mp_nexthop_prefer_global
)
7295 json_object_boolean_true_add(
7296 json_nexthop_ll
, "used");
7298 json_object_boolean_true_add(
7299 json_nexthop_global
, "used");
7301 json_object_boolean_true_add(
7302 json_nexthop_global
, "used");
7304 /* Display LL if LL/Global both in table unless
7305 * prefer-global is set */
7306 if (((attr
->mp_nexthop_len
== 32)
7307 && !attr
->mp_nexthop_prefer_global
)
7308 || (path
->peer
->conf_if
)) {
7309 if (path
->peer
->conf_if
) {
7310 len
= vty_out(vty
, "%s",
7311 path
->peer
->conf_if
);
7312 len
= 16 - len
; /* len of IPv6
7318 vty_out(vty
, "\n%*s", 36, " ");
7320 vty_out(vty
, "%*s", len
, " ");
7328 &attr
->mp_nexthop_local
,
7334 vty_out(vty
, "\n%*s", 36, " ");
7336 vty_out(vty
, "%*s", len
, " ");
7345 &attr
->mp_nexthop_global
,
7351 vty_out(vty
, "\n%*s", 36, " ");
7353 vty_out(vty
, "%*s", len
, " ");
7359 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7363 * Adding "metric" field to match with corresponding
7364 * CLI. "med" will be deprecated in future.
7366 json_object_int_add(json_path
, "med", attr
->med
);
7367 json_object_int_add(json_path
, "metric", attr
->med
);
7369 vty_out(vty
, "%10u", attr
->med
);
7370 else if (!json_paths
)
7374 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7378 * Adding "locPrf" field to match with corresponding
7379 * CLI. "localPref" will be deprecated in future.
7381 json_object_int_add(json_path
, "localpref",
7383 json_object_int_add(json_path
, "locPrf",
7386 vty_out(vty
, "%7u", attr
->local_pref
);
7387 else if (!json_paths
)
7391 json_object_int_add(json_path
, "weight", attr
->weight
);
7393 vty_out(vty
, "%7u ", attr
->weight
);
7397 json_object_string_add(
7398 json_path
, "peerId",
7399 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7407 * Adding "path" field to match with corresponding
7408 * CLI. "aspath" will be deprecated in future.
7410 json_object_string_add(json_path
, "aspath",
7412 json_object_string_add(json_path
, "path",
7415 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7420 json_object_string_add(json_path
, "origin",
7421 bgp_origin_long_str
[attr
->origin
]);
7423 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7426 if (safi
== SAFI_EVPN
&&
7427 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7428 json_ext_community
= json_object_new_object();
7429 json_object_string_add(json_ext_community
,
7431 attr
->ecommunity
->str
);
7432 json_object_object_add(json_path
,
7433 "extendedCommunity",
7434 json_ext_community
);
7438 json_object_boolean_true_add(json_path
,
7439 "announceNexthopSelf");
7440 if (nexthop_othervrf
) {
7441 json_object_string_add(json_path
, "nhVrfName",
7444 json_object_int_add(json_path
, "nhVrfId",
7445 ((nexthop_vrfid
== VRF_UNKNOWN
)
7447 : (int)nexthop_vrfid
));
7452 if (json_nexthop_global
|| json_nexthop_ll
) {
7453 json_nexthops
= json_object_new_array();
7455 if (json_nexthop_global
)
7456 json_object_array_add(json_nexthops
,
7457 json_nexthop_global
);
7459 if (json_nexthop_ll
)
7460 json_object_array_add(json_nexthops
,
7463 json_object_object_add(json_path
, "nexthops",
7467 json_object_array_add(json_paths
, json_path
);
7471 if (safi
== SAFI_EVPN
&&
7472 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7473 vty_out(vty
, "%*s", 20, " ");
7474 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7478 /* prints an additional line, indented, with VNC info, if
7480 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7481 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7486 /* called from terminal list command */
7487 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7488 safi_t safi
, bool use_json
, json_object
*json_ar
)
7490 json_object
*json_status
= NULL
;
7491 json_object
*json_net
= NULL
;
7494 /* Route status display. */
7496 json_status
= json_object_new_object();
7497 json_net
= json_object_new_object();
7504 /* print prefix and mask */
7506 json_object_string_add(
7507 json_net
, "addrPrefix",
7508 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
7509 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
7510 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7511 json_object_string_add(json_net
, "network", buf2
);
7513 route_vty_out_route(p
, vty
, NULL
);
7515 /* Print attribute */
7518 if (p
->family
== AF_INET
7519 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7520 || safi
== SAFI_EVPN
7521 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7522 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7523 || safi
== SAFI_EVPN
)
7524 json_object_string_add(
7525 json_net
, "nextHop",
7527 attr
->mp_nexthop_global_in
));
7529 json_object_string_add(
7530 json_net
, "nextHop",
7531 inet_ntoa(attr
->nexthop
));
7532 } else if (p
->family
== AF_INET6
7533 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7536 json_object_string_add(
7537 json_net
, "nextHopGlobal",
7539 &attr
->mp_nexthop_global
, buf
,
7544 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7545 json_object_int_add(json_net
, "metric",
7548 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7551 * Adding "locPrf" field to match with
7552 * corresponding CLI. "localPref" will be
7553 * deprecated in future.
7555 json_object_int_add(json_net
, "localPref",
7557 json_object_int_add(json_net
, "locPrf",
7561 json_object_int_add(json_net
, "weight", attr
->weight
);
7567 * Adding "path" field to match with
7568 * corresponding CLI. "localPref" will be
7569 * deprecated in future.
7571 json_object_string_add(json_net
, "asPath",
7573 json_object_string_add(json_net
, "path",
7578 json_object_string_add(json_net
, "bgpOriginCode",
7579 bgp_origin_str
[attr
->origin
]);
7581 if (p
->family
== AF_INET
7582 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7583 || safi
== SAFI_EVPN
7584 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7585 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7586 || safi
== SAFI_EVPN
)
7587 vty_out(vty
, "%-16s",
7589 attr
->mp_nexthop_global_in
));
7591 vty_out(vty
, "%-16s",
7592 inet_ntoa(attr
->nexthop
));
7593 } else if (p
->family
== AF_INET6
7594 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7601 &attr
->mp_nexthop_global
, buf
,
7605 vty_out(vty
, "\n%*s", 36, " ");
7607 vty_out(vty
, "%*s", len
, " ");
7610 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7611 vty_out(vty
, "%10u", attr
->med
);
7615 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7616 vty_out(vty
, "%7u", attr
->local_pref
);
7620 vty_out(vty
, "%7u ", attr
->weight
);
7624 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7627 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7631 json_object_boolean_true_add(json_status
, "*");
7632 json_object_boolean_true_add(json_status
, ">");
7633 json_object_object_add(json_net
, "appliedStatusSymbols",
7635 char buf_cut
[BUFSIZ
];
7637 prefix2str(p
, buf_cut
, PREFIX_STRLEN
);
7638 json_object_object_add(json_ar
, buf_cut
, json_net
);
7643 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7644 struct bgp_path_info
*path
, int display
, safi_t safi
,
7647 json_object
*json_out
= NULL
;
7649 mpls_label_t label
= MPLS_INVALID_LABEL
;
7655 json_out
= json_object_new_object();
7657 /* short status lead text */
7658 route_vty_short_status_out(vty
, path
, json_out
);
7660 /* print prefix and mask */
7663 route_vty_out_route(p
, vty
, NULL
);
7665 vty_out(vty
, "%*s", 17, " ");
7668 /* Print attribute */
7671 if (((p
->family
== AF_INET
)
7672 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7673 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7674 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7675 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7676 || safi
== SAFI_EVPN
) {
7678 json_object_string_add(
7679 json_out
, "mpNexthopGlobalIn",
7681 attr
->mp_nexthop_global_in
));
7683 vty_out(vty
, "%-16s",
7685 attr
->mp_nexthop_global_in
));
7688 json_object_string_add(
7689 json_out
, "nexthop",
7690 inet_ntoa(attr
->nexthop
));
7692 vty_out(vty
, "%-16s",
7693 inet_ntoa(attr
->nexthop
));
7695 } else if (((p
->family
== AF_INET6
)
7696 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7697 || (safi
== SAFI_EVPN
7698 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7699 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7701 if (attr
->mp_nexthop_len
7702 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7704 json_object_string_add(
7705 json_out
, "mpNexthopGlobalIn",
7708 &attr
->mp_nexthop_global
,
7709 buf_a
, sizeof(buf_a
)));
7714 &attr
->mp_nexthop_global
,
7715 buf_a
, sizeof(buf_a
)));
7716 } else if (attr
->mp_nexthop_len
7717 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7718 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
7719 &attr
->mp_nexthop_global
,
7720 &attr
->mp_nexthop_local
);
7722 json_object_string_add(
7724 "mpNexthopGlobalLocal", buf_a
);
7726 vty_out(vty
, "%s", buf_a
);
7731 label
= decode_label(&path
->extra
->label
[0]);
7733 if (bgp_is_valid_label(&label
)) {
7735 json_object_int_add(json_out
, "notag", label
);
7736 json_object_array_add(json
, json_out
);
7738 vty_out(vty
, "notag/%d", label
);
7744 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7745 struct bgp_path_info
*path
, int display
,
7746 json_object
*json_paths
)
7749 char buf
[BUFSIZ
] = {0};
7750 json_object
*json_path
= NULL
;
7751 json_object
*json_nexthop
= NULL
;
7752 json_object
*json_overlay
= NULL
;
7758 json_path
= json_object_new_object();
7759 json_overlay
= json_object_new_object();
7760 json_nexthop
= json_object_new_object();
7763 /* short status lead text */
7764 route_vty_short_status_out(vty
, path
, json_path
);
7766 /* print prefix and mask */
7768 route_vty_out_route(p
, vty
, json_path
);
7770 vty_out(vty
, "%*s", 17, " ");
7772 /* Print attribute */
7776 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7780 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
7782 vty_out(vty
, "%-16s", buf
);
7784 json_object_string_add(json_nexthop
, "ip", buf
);
7786 json_object_string_add(json_nexthop
, "afi",
7789 json_object_object_add(json_path
, "nexthop",
7794 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
7795 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
7797 vty_out(vty
, "%s(%s)", buf
, buf1
);
7799 json_object_string_add(json_nexthop
,
7802 json_object_string_add(json_nexthop
,
7803 "ipv6LinkLocal", buf1
);
7805 json_object_string_add(json_nexthop
, "afi",
7808 json_object_object_add(json_path
, "nexthop",
7816 json_object_string_add(json_nexthop
, "Error",
7817 "Unsupported address-family");
7821 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7824 vty_out(vty
, "%s", str
);
7826 json_object_string_add(json_overlay
, "esi", str
);
7828 XFREE(MTYPE_TMP
, str
);
7830 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7831 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
),
7833 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7834 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
),
7839 vty_out(vty
, "/%s", buf
);
7841 json_object_string_add(json_overlay
, "gw", buf
);
7843 if (attr
->ecommunity
) {
7845 struct ecommunity_val
*routermac
= ecommunity_lookup(
7846 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7847 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7849 mac
= ecom_mac2str((char *)routermac
->val
);
7852 vty_out(vty
, "/%s", (char *)mac
);
7854 json_object_string_add(json_overlay
,
7857 XFREE(MTYPE_TMP
, mac
);
7864 json_object_object_add(json_path
, "overlay",
7867 json_object_array_add(json_paths
, json_path
);
7872 /* dampening route */
7873 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7874 struct bgp_path_info
*path
, int display
,
7875 safi_t safi
, bool use_json
, json_object
*json
)
7879 char timebuf
[BGP_UPTIME_LEN
];
7881 /* short status lead text */
7882 route_vty_short_status_out(vty
, path
, json
);
7884 /* print prefix and mask */
7887 route_vty_out_route(p
, vty
, NULL
);
7889 vty_out(vty
, "%*s", 17, " ");
7892 len
= vty_out(vty
, "%s", path
->peer
->host
);
7896 vty_out(vty
, "\n%*s", 34, " ");
7899 json_object_int_add(json
, "peerHost", len
);
7901 vty_out(vty
, "%*s", len
, " ");
7905 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7909 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7910 BGP_UPTIME_LEN
, use_json
,
7913 /* Print attribute */
7919 json_object_string_add(json
, "asPath",
7922 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7927 json_object_string_add(json
, "origin",
7928 bgp_origin_str
[attr
->origin
]);
7930 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7937 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7938 struct bgp_path_info
*path
, int display
,
7939 safi_t safi
, bool use_json
, json_object
*json
)
7942 struct bgp_damp_info
*bdi
;
7943 char timebuf
[BGP_UPTIME_LEN
];
7949 bdi
= path
->extra
->damp_info
;
7951 /* short status lead text */
7952 route_vty_short_status_out(vty
, path
, json
);
7954 /* print prefix and mask */
7957 route_vty_out_route(p
, vty
, NULL
);
7959 vty_out(vty
, "%*s", 17, " ");
7962 len
= vty_out(vty
, "%s", path
->peer
->host
);
7966 vty_out(vty
, "\n%*s", 33, " ");
7969 json_object_int_add(json
, "peerHost", len
);
7971 vty_out(vty
, "%*s", len
, " ");
7974 len
= vty_out(vty
, "%d", bdi
->flap
);
7981 json_object_int_add(json
, "bdiFlap", len
);
7983 vty_out(vty
, "%*s", len
, " ");
7987 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7990 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7991 BGP_UPTIME_LEN
, 0, NULL
));
7993 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7994 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7996 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7997 BGP_UPTIME_LEN
, use_json
, json
);
8000 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8005 vty_out(vty
, "%*s ", 8, " ");
8008 /* Print attribute */
8014 json_object_string_add(json
, "asPath",
8017 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8022 json_object_string_add(json
, "origin",
8023 bgp_origin_str
[attr
->origin
]);
8025 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8031 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8032 int *first
, const char *header
,
8033 json_object
*json_adv_to
)
8035 char buf1
[INET6_ADDRSTRLEN
];
8036 json_object
*json_peer
= NULL
;
8039 /* 'advertised-to' is a dictionary of peers we have advertised
8041 * prefix too. The key is the peer's IP or swpX, the value is
8043 * hostname if we know it and "" if not.
8045 json_peer
= json_object_new_object();
8048 json_object_string_add(json_peer
, "hostname",
8052 json_object_object_add(json_adv_to
, peer
->conf_if
,
8055 json_object_object_add(
8057 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8061 vty_out(vty
, "%s", header
);
8066 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8068 vty_out(vty
, " %s(%s)", peer
->hostname
,
8071 vty_out(vty
, " %s(%s)", peer
->hostname
,
8072 sockunion2str(&peer
->su
, buf1
,
8076 vty_out(vty
, " %s", peer
->conf_if
);
8079 sockunion2str(&peer
->su
, buf1
,
8085 static void route_vty_out_tx_ids(struct vty
*vty
,
8086 struct bgp_addpath_info_data
*d
)
8090 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8091 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8092 d
->addpath_tx_id
[i
],
8093 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8097 static const char *bgp_path_selection_reason2str(
8098 enum bgp_path_selection_reason reason
)
8101 case bgp_path_selection_none
:
8102 return "Nothing to Select";
8104 case bgp_path_selection_first
:
8105 return "First path received";
8107 case bgp_path_selection_evpn_sticky_mac
:
8108 return "EVPN Sticky Mac";
8110 case bgp_path_selection_evpn_seq
:
8111 return "EVPN sequence number";
8113 case bgp_path_selection_evpn_lower_ip
:
8114 return "EVPN lower IP";
8116 case bgp_path_selection_weight
:
8119 case bgp_path_selection_local_pref
:
8120 return "Local Pref";
8122 case bgp_path_selection_local_route
:
8123 return "Local Route";
8125 case bgp_path_selection_confed_as_path
:
8126 return "Confederation based AS Path";
8128 case bgp_path_selection_as_path
:
8131 case bgp_path_selection_origin
:
8134 case bgp_path_selection_med
:
8137 case bgp_path_selection_peer
:
8140 case bgp_path_selection_confed
:
8141 return "Confed Peer Type";
8143 case bgp_path_selection_igp_metric
:
8144 return "IGP Metric";
8146 case bgp_path_selection_older
:
8147 return "Older Path";
8149 case bgp_path_selection_router_id
:
8152 case bgp_path_selection_cluster_length
:
8153 return "Cluser length";
8155 case bgp_path_selection_stale
:
8156 return "Path Staleness";
8158 case bgp_path_selection_local_configured
:
8159 return "Locally configured route";
8161 case bgp_path_selection_neighbor_ip
:
8162 return "Neighbor IP";
8164 case bgp_path_selection_default
:
8165 return "Nothing left to compare";
8168 return "Invalid (internal error)";
8171 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8172 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8173 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8175 char buf
[INET6_ADDRSTRLEN
];
8177 char buf2
[EVPN_ROUTE_STRLEN
];
8179 int sockunion_vty_out(struct vty
*, union sockunion
*);
8181 json_object
*json_bestpath
= NULL
;
8182 json_object
*json_cluster_list
= NULL
;
8183 json_object
*json_cluster_list_list
= NULL
;
8184 json_object
*json_ext_community
= NULL
;
8185 json_object
*json_last_update
= NULL
;
8186 json_object
*json_pmsi
= NULL
;
8187 json_object
*json_nexthop_global
= NULL
;
8188 json_object
*json_nexthop_ll
= NULL
;
8189 json_object
*json_nexthops
= NULL
;
8190 json_object
*json_path
= NULL
;
8191 json_object
*json_peer
= NULL
;
8192 json_object
*json_string
= NULL
;
8193 json_object
*json_adv_to
= NULL
;
8195 struct listnode
*node
, *nnode
;
8197 int addpath_capable
;
8199 unsigned int first_as
;
8201 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8203 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
8206 json_path
= json_object_new_object();
8207 json_peer
= json_object_new_object();
8208 json_nexthop_global
= json_object_new_object();
8211 if (!json_paths
&& path
->extra
) {
8216 if (path
->extra
&& path
->extra
->num_labels
) {
8217 bgp_evpn_label2str(path
->extra
->label
,
8218 path
->extra
->num_labels
, tag_buf
,
8221 if (safi
== SAFI_EVPN
) {
8222 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8223 buf2
, sizeof(buf2
));
8224 vty_out(vty
, " Route %s", buf2
);
8225 if (tag_buf
[0] != '\0')
8226 vty_out(vty
, " VNI %s", tag_buf
);
8230 if (path
->extra
&& path
->extra
->parent
) {
8231 struct bgp_path_info
*parent_ri
;
8232 struct bgp_node
*rn
, *prn
;
8234 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8235 rn
= parent_ri
->net
;
8236 if (rn
&& rn
->prn
) {
8238 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8239 buf1
, sizeof(buf1
));
8240 if (is_pi_family_evpn(parent_ri
)) {
8241 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8242 buf2
, sizeof(buf2
));
8243 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8245 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8253 /* Line1 display AS-path, Aggregator */
8256 if (!attr
->aspath
->json
)
8257 aspath_str_update(attr
->aspath
, true);
8258 json_object_lock(attr
->aspath
->json
);
8259 json_object_object_add(json_path
, "aspath",
8260 attr
->aspath
->json
);
8262 if (attr
->aspath
->segments
)
8263 aspath_print_vty(vty
, " %s",
8266 vty_out(vty
, " Local");
8270 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8272 json_object_boolean_true_add(json_path
,
8275 vty_out(vty
, ", (removed)");
8278 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8280 json_object_boolean_true_add(json_path
,
8283 vty_out(vty
, ", (stale)");
8286 if (CHECK_FLAG(attr
->flag
,
8287 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8289 json_object_int_add(json_path
, "aggregatorAs",
8290 attr
->aggregator_as
);
8291 json_object_string_add(
8292 json_path
, "aggregatorId",
8293 inet_ntoa(attr
->aggregator_addr
));
8295 vty_out(vty
, ", (aggregated by %u %s)",
8296 attr
->aggregator_as
,
8297 inet_ntoa(attr
->aggregator_addr
));
8301 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8302 PEER_FLAG_REFLECTOR_CLIENT
)) {
8304 json_object_boolean_true_add(
8305 json_path
, "rxedFromRrClient");
8307 vty_out(vty
, ", (Received from a RR-client)");
8310 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8311 PEER_FLAG_RSERVER_CLIENT
)) {
8313 json_object_boolean_true_add(
8314 json_path
, "rxedFromRsClient");
8316 vty_out(vty
, ", (Received from a RS-client)");
8319 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8321 json_object_boolean_true_add(
8322 json_path
, "dampeningHistoryEntry");
8324 vty_out(vty
, ", (history entry)");
8325 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8327 json_object_boolean_true_add(
8328 json_path
, "dampeningSuppressed");
8330 vty_out(vty
, ", (suppressed due to dampening)");
8336 /* Line2 display Next-hop, Neighbor, Router-id */
8337 /* Display the nexthop */
8338 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8339 || bn
->p
.family
== AF_EVPN
)
8340 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8341 || safi
== SAFI_EVPN
8342 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8343 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8344 || safi
== SAFI_EVPN
) {
8346 json_object_string_add(
8347 json_nexthop_global
,
8348 nexthop_fqdn
? "fqdn" : "ip",
8352 attr
->mp_nexthop_global_in
));
8358 attr
->mp_nexthop_global_in
));
8361 json_object_string_add(
8362 json_nexthop_global
,
8363 nexthop_fqdn
? "fqdn" : "ip",
8377 json_object_string_add(json_nexthop_global
,
8381 json_object_string_add(
8382 json_nexthop_global
,
8383 nexthop_fqdn
? "fqdn" : "ip",
8388 &attr
->mp_nexthop_global
,
8391 json_object_string_add(json_nexthop_global
,
8393 json_object_string_add(json_nexthop_global
,
8401 &attr
->mp_nexthop_global
,
8407 /* Display the IGP cost or 'inaccessible' */
8408 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8410 json_object_boolean_false_add(
8411 json_nexthop_global
, "accessible");
8413 vty_out(vty
, " (inaccessible)");
8415 if (path
->extra
&& path
->extra
->igpmetric
) {
8417 json_object_int_add(
8418 json_nexthop_global
, "metric",
8419 path
->extra
->igpmetric
);
8421 vty_out(vty
, " (metric %u)",
8422 path
->extra
->igpmetric
);
8425 /* IGP cost is 0, display this only for json */
8428 json_object_int_add(json_nexthop_global
,
8433 json_object_boolean_true_add(
8434 json_nexthop_global
, "accessible");
8437 /* Display peer "from" output */
8438 /* This path was originated locally */
8439 if (path
->peer
== bgp
->peer_self
) {
8441 if (safi
== SAFI_EVPN
8442 || (bn
->p
.family
== AF_INET
8443 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8445 json_object_string_add(
8446 json_peer
, "peerId", "0.0.0.0");
8448 vty_out(vty
, " from 0.0.0.0 ");
8451 json_object_string_add(json_peer
,
8454 vty_out(vty
, " from :: ");
8458 json_object_string_add(
8459 json_peer
, "routerId",
8460 inet_ntoa(bgp
->router_id
));
8462 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8465 /* We RXed this path from one of our peers */
8469 json_object_string_add(
8470 json_peer
, "peerId",
8471 sockunion2str(&path
->peer
->su
, buf
,
8473 json_object_string_add(
8474 json_peer
, "routerId",
8476 &path
->peer
->remote_id
, buf1
,
8479 if (path
->peer
->hostname
)
8480 json_object_string_add(
8481 json_peer
, "hostname",
8482 path
->peer
->hostname
);
8484 if (path
->peer
->domainname
)
8485 json_object_string_add(
8486 json_peer
, "domainname",
8487 path
->peer
->domainname
);
8489 if (path
->peer
->conf_if
)
8490 json_object_string_add(
8491 json_peer
, "interface",
8492 path
->peer
->conf_if
);
8494 if (path
->peer
->conf_if
) {
8495 if (path
->peer
->hostname
8498 BGP_FLAG_SHOW_HOSTNAME
))
8499 vty_out(vty
, " from %s(%s)",
8500 path
->peer
->hostname
,
8501 path
->peer
->conf_if
);
8503 vty_out(vty
, " from %s",
8504 path
->peer
->conf_if
);
8506 if (path
->peer
->hostname
8509 BGP_FLAG_SHOW_HOSTNAME
))
8510 vty_out(vty
, " from %s(%s)",
8511 path
->peer
->hostname
,
8514 vty_out(vty
, " from %s",
8522 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8523 vty_out(vty
, " (%s)",
8524 inet_ntoa(attr
->originator_id
));
8526 vty_out(vty
, " (%s)",
8529 &path
->peer
->remote_id
,
8530 buf1
, sizeof(buf1
)));
8535 * Note when vrfid of nexthop is different from that of prefix
8537 if (path
->extra
&& path
->extra
->bgp_orig
) {
8538 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8543 if (path
->extra
->bgp_orig
->inst_type
8544 == BGP_INSTANCE_TYPE_DEFAULT
)
8546 vn
= VRF_DEFAULT_NAME
;
8548 vn
= path
->extra
->bgp_orig
->name
;
8550 json_object_string_add(json_path
, "nhVrfName",
8553 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8554 json_object_int_add(json_path
,
8557 json_object_int_add(json_path
,
8558 "nhVrfId", (int)nexthop_vrfid
);
8561 if (nexthop_vrfid
== VRF_UNKNOWN
)
8562 vty_out(vty
, " vrf ?");
8564 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8570 json_object_boolean_true_add(json_path
,
8571 "announceNexthopSelf");
8573 vty_out(vty
, " announce-nh-self");
8580 /* display the link-local nexthop */
8581 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8583 json_nexthop_ll
= json_object_new_object();
8584 json_object_string_add(
8586 nexthop_fqdn
? "fqdn" : "ip",
8591 &attr
->mp_nexthop_local
,
8594 json_object_string_add(json_nexthop_ll
, "afi",
8596 json_object_string_add(json_nexthop_ll
, "scope",
8599 json_object_boolean_true_add(json_nexthop_ll
,
8602 if (!attr
->mp_nexthop_prefer_global
)
8603 json_object_boolean_true_add(
8604 json_nexthop_ll
, "used");
8606 json_object_boolean_true_add(
8607 json_nexthop_global
, "used");
8609 vty_out(vty
, " (%s) %s\n",
8611 &attr
->mp_nexthop_local
, buf
,
8613 attr
->mp_nexthop_prefer_global
8618 /* If we do not have a link-local nexthop then we must flag the
8622 json_object_boolean_true_add(
8623 json_nexthop_global
, "used");
8626 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8627 * Int/Ext/Local, Atomic, best */
8629 json_object_string_add(
8630 json_path
, "origin",
8631 bgp_origin_long_str
[attr
->origin
]);
8633 vty_out(vty
, " Origin %s",
8634 bgp_origin_long_str
[attr
->origin
]);
8636 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8640 * Adding "metric" field to match with
8641 * corresponding CLI. "med" will be
8642 * deprecated in future.
8644 json_object_int_add(json_path
, "med",
8646 json_object_int_add(json_path
, "metric",
8649 vty_out(vty
, ", metric %u", attr
->med
);
8652 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8654 json_object_int_add(json_path
, "localpref",
8657 vty_out(vty
, ", localpref %u",
8661 if (attr
->weight
!= 0) {
8663 json_object_int_add(json_path
, "weight",
8666 vty_out(vty
, ", weight %u", attr
->weight
);
8669 if (attr
->tag
!= 0) {
8671 json_object_int_add(json_path
, "tag",
8674 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8678 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8680 json_object_boolean_false_add(json_path
,
8683 vty_out(vty
, ", invalid");
8684 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8686 json_object_boolean_true_add(json_path
,
8689 vty_out(vty
, ", valid");
8692 if (path
->peer
!= bgp
->peer_self
) {
8693 if (path
->peer
->as
== path
->peer
->local_as
) {
8694 if (CHECK_FLAG(bgp
->config
,
8695 BGP_CONFIG_CONFEDERATION
)) {
8697 json_object_string_add(
8702 ", confed-internal");
8705 json_object_string_add(
8709 vty_out(vty
, ", internal");
8712 if (bgp_confederation_peers_check(
8713 bgp
, path
->peer
->as
)) {
8715 json_object_string_add(
8720 ", confed-external");
8723 json_object_string_add(
8727 vty_out(vty
, ", external");
8730 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8732 json_object_boolean_true_add(json_path
,
8734 json_object_boolean_true_add(json_path
,
8737 vty_out(vty
, ", aggregated, local");
8739 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8741 json_object_boolean_true_add(json_path
,
8744 vty_out(vty
, ", sourced");
8747 json_object_boolean_true_add(json_path
,
8749 json_object_boolean_true_add(json_path
,
8752 vty_out(vty
, ", sourced, local");
8756 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8758 json_object_boolean_true_add(json_path
,
8761 vty_out(vty
, ", atomic-aggregate");
8764 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8765 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8766 && bgp_path_info_mpath_count(path
))) {
8768 json_object_boolean_true_add(json_path
,
8771 vty_out(vty
, ", multipath");
8774 // Mark the bestpath(s)
8775 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8776 first_as
= aspath_get_first_as(attr
->aspath
);
8781 json_object_new_object();
8782 json_object_int_add(json_bestpath
,
8783 "bestpathFromAs", first_as
);
8786 vty_out(vty
, ", bestpath-from-AS %u",
8790 ", bestpath-from-AS Local");
8794 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8798 json_object_new_object();
8799 json_object_boolean_true_add(json_bestpath
,
8801 json_object_string_add(json_bestpath
,
8803 bgp_path_selection_reason2str(bn
->reason
));
8805 vty_out(vty
, ", best");
8806 vty_out(vty
, " (%s)",
8807 bgp_path_selection_reason2str(bn
->reason
));
8812 json_object_object_add(json_path
, "bestpath",
8818 /* Line 4 display Community */
8819 if (attr
->community
) {
8821 if (!attr
->community
->json
)
8822 community_str(attr
->community
, true);
8823 json_object_lock(attr
->community
->json
);
8824 json_object_object_add(json_path
, "community",
8825 attr
->community
->json
);
8827 vty_out(vty
, " Community: %s\n",
8828 attr
->community
->str
);
8832 /* Line 5 display Extended-community */
8833 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8835 json_ext_community
= json_object_new_object();
8836 json_object_string_add(json_ext_community
,
8838 attr
->ecommunity
->str
);
8839 json_object_object_add(json_path
,
8840 "extendedCommunity",
8841 json_ext_community
);
8843 vty_out(vty
, " Extended Community: %s\n",
8844 attr
->ecommunity
->str
);
8848 /* Line 6 display Large community */
8849 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8851 if (!attr
->lcommunity
->json
)
8852 lcommunity_str(attr
->lcommunity
, true);
8853 json_object_lock(attr
->lcommunity
->json
);
8854 json_object_object_add(json_path
,
8856 attr
->lcommunity
->json
);
8858 vty_out(vty
, " Large Community: %s\n",
8859 attr
->lcommunity
->str
);
8863 /* Line 7 display Originator, Cluster-id */
8864 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8865 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8867 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8869 json_object_string_add(
8870 json_path
, "originatorId",
8871 inet_ntoa(attr
->originator_id
));
8873 vty_out(vty
, " Originator: %s",
8874 inet_ntoa(attr
->originator_id
));
8877 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8882 json_object_new_object();
8883 json_cluster_list_list
=
8884 json_object_new_array();
8887 i
< attr
->cluster
->length
/ 4;
8889 json_string
= json_object_new_string(
8893 json_object_array_add(
8894 json_cluster_list_list
,
8898 /* struct cluster_list does not have
8900 * aspath and community do. Add this
8903 json_object_string_add(json_cluster_list,
8904 "string", attr->cluster->str);
8906 json_object_object_add(
8907 json_cluster_list
, "list",
8908 json_cluster_list_list
);
8909 json_object_object_add(
8910 json_path
, "clusterList",
8913 vty_out(vty
, ", Cluster list: ");
8916 i
< attr
->cluster
->length
/ 4;
8930 if (path
->extra
&& path
->extra
->damp_info
)
8931 bgp_damp_info_vty(vty
, path
, json_path
);
8934 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8935 && safi
!= SAFI_EVPN
) {
8936 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8939 json_object_int_add(json_path
, "remoteLabel",
8942 vty_out(vty
, " Remote label: %d\n", label
);
8946 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8948 json_object_int_add(json_path
, "labelIndex",
8951 vty_out(vty
, " Label Index: %d\n",
8955 /* Line 8 display Addpath IDs */
8956 if (path
->addpath_rx_id
8957 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8959 json_object_int_add(json_path
, "addpathRxId",
8960 path
->addpath_rx_id
);
8962 /* Keep backwards compatibility with the old API
8963 * by putting TX All's ID in the old field
8965 json_object_int_add(
8966 json_path
, "addpathTxId",
8967 path
->tx_addpath
.addpath_tx_id
8970 /* ... but create a specific field for each
8973 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8974 json_object_int_add(
8976 bgp_addpath_names(i
)
8982 vty_out(vty
, " AddPath ID: RX %u, ",
8983 path
->addpath_rx_id
);
8985 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8989 /* If we used addpath to TX a non-bestpath we need to display
8990 * "Advertised to" on a path-by-path basis
8992 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8995 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8997 bgp_addpath_encode_tx(peer
, afi
, safi
);
8998 has_adj
= bgp_adj_out_lookup(
9000 bgp_addpath_id_for_peer(
9002 &path
->tx_addpath
));
9004 if ((addpath_capable
&& has_adj
)
9005 || (!addpath_capable
&& has_adj
9006 && CHECK_FLAG(path
->flags
,
9007 BGP_PATH_SELECTED
))) {
9008 if (json_path
&& !json_adv_to
)
9010 json_object_new_object();
9012 route_vty_out_advertised_to(
9021 json_object_object_add(json_path
,
9032 /* Line 9 display Uptime */
9033 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9035 json_last_update
= json_object_new_object();
9036 json_object_int_add(json_last_update
, "epoch", tbuf
);
9037 json_object_string_add(json_last_update
, "string",
9039 json_object_object_add(json_path
, "lastUpdate",
9042 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9044 /* Line 10 display PMSI tunnel attribute, if present */
9045 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9046 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
9047 attr
->pmsi_tnl_type
,
9048 PMSI_TNLTYPE_STR_DEFAULT
);
9051 json_pmsi
= json_object_new_object();
9052 json_object_string_add(json_pmsi
,
9054 json_object_int_add(json_pmsi
,
9056 label2vni(&attr
->label
));
9057 json_object_object_add(json_path
, "pmsi",
9061 " PMSI Tunnel Type: %s, label: %d\n",
9062 str
, label2vni(&attr
->label
));
9067 /* We've constructed the json object for this path, add it to the json
9071 if (json_nexthop_global
|| json_nexthop_ll
) {
9072 json_nexthops
= json_object_new_array();
9074 if (json_nexthop_global
)
9075 json_object_array_add(json_nexthops
,
9076 json_nexthop_global
);
9078 if (json_nexthop_ll
)
9079 json_object_array_add(json_nexthops
,
9082 json_object_object_add(json_path
, "nexthops",
9086 json_object_object_add(json_path
, "peer", json_peer
);
9087 json_object_array_add(json_paths
, json_path
);
9092 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9093 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9094 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9096 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9097 const char *prefix_list_str
, afi_t afi
,
9098 safi_t safi
, enum bgp_show_type type
);
9099 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9100 const char *filter
, afi_t afi
, safi_t safi
,
9101 enum bgp_show_type type
);
9102 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9103 const char *rmap_str
, afi_t afi
, safi_t safi
,
9104 enum bgp_show_type type
);
9105 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9106 const char *com
, int exact
, afi_t afi
,
9108 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9109 const char *prefix
, afi_t afi
, safi_t safi
,
9110 enum bgp_show_type type
);
9111 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9112 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
9113 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9114 const char *comstr
, int exact
, afi_t afi
,
9115 safi_t safi
, bool use_json
);
9118 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9119 struct bgp_table
*table
, enum bgp_show_type type
,
9120 void *output_arg
, bool use_json
, char *rd
,
9121 int is_last
, unsigned long *output_cum
,
9122 unsigned long *total_cum
,
9123 unsigned long *json_header_depth
)
9125 struct bgp_path_info
*pi
;
9126 struct bgp_node
*rn
;
9129 unsigned long output_count
= 0;
9130 unsigned long total_count
= 0;
9133 json_object
*json_paths
= NULL
;
9136 if (output_cum
&& *output_cum
!= 0)
9139 if (use_json
&& !*json_header_depth
) {
9141 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9142 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9143 " \"localAS\": %u,\n \"routes\": { ",
9144 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9145 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9148 table
->version
, inet_ntoa(bgp
->router_id
),
9149 bgp
->default_local_pref
, bgp
->as
);
9150 *json_header_depth
= 2;
9152 vty_out(vty
, " \"routeDistinguishers\" : {");
9153 ++*json_header_depth
;
9157 if (use_json
&& rd
) {
9158 vty_out(vty
, " \"%s\" : { ", rd
);
9161 /* Start processing of routes. */
9162 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9163 pi
= bgp_node_get_bgp_path_info(rn
);
9169 json_paths
= json_object_new_array();
9173 for (; pi
; pi
= pi
->next
) {
9175 if (type
== bgp_show_type_flap_statistics
9176 || type
== bgp_show_type_flap_neighbor
9177 || type
== bgp_show_type_dampend_paths
9178 || type
== bgp_show_type_damp_neighbor
) {
9179 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9182 if (type
== bgp_show_type_regexp
) {
9183 regex_t
*regex
= output_arg
;
9185 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9189 if (type
== bgp_show_type_prefix_list
) {
9190 struct prefix_list
*plist
= output_arg
;
9192 if (prefix_list_apply(plist
, &rn
->p
)
9196 if (type
== bgp_show_type_filter_list
) {
9197 struct as_list
*as_list
= output_arg
;
9199 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9200 != AS_FILTER_PERMIT
)
9203 if (type
== bgp_show_type_route_map
) {
9204 struct route_map
*rmap
= output_arg
;
9205 struct bgp_path_info path
;
9206 struct attr dummy_attr
;
9207 route_map_result_t ret
;
9209 bgp_attr_dup(&dummy_attr
, pi
->attr
);
9211 path
.peer
= pi
->peer
;
9212 path
.attr
= &dummy_attr
;
9214 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9216 if (ret
== RMAP_DENYMATCH
)
9219 if (type
== bgp_show_type_neighbor
9220 || type
== bgp_show_type_flap_neighbor
9221 || type
== bgp_show_type_damp_neighbor
) {
9222 union sockunion
*su
= output_arg
;
9224 if (pi
->peer
== NULL
9225 || pi
->peer
->su_remote
== NULL
9226 || !sockunion_same(pi
->peer
->su_remote
, su
))
9229 if (type
== bgp_show_type_cidr_only
) {
9230 uint32_t destination
;
9232 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9233 if (IN_CLASSC(destination
)
9234 && rn
->p
.prefixlen
== 24)
9236 if (IN_CLASSB(destination
)
9237 && rn
->p
.prefixlen
== 16)
9239 if (IN_CLASSA(destination
)
9240 && rn
->p
.prefixlen
== 8)
9243 if (type
== bgp_show_type_prefix_longer
) {
9245 if (!prefix_match(p
, &rn
->p
))
9248 if (type
== bgp_show_type_community_all
) {
9249 if (!pi
->attr
->community
)
9252 if (type
== bgp_show_type_community
) {
9253 struct community
*com
= output_arg
;
9255 if (!pi
->attr
->community
9256 || !community_match(pi
->attr
->community
,
9260 if (type
== bgp_show_type_community_exact
) {
9261 struct community
*com
= output_arg
;
9263 if (!pi
->attr
->community
9264 || !community_cmp(pi
->attr
->community
, com
))
9267 if (type
== bgp_show_type_community_list
) {
9268 struct community_list
*list
= output_arg
;
9270 if (!community_list_match(pi
->attr
->community
,
9274 if (type
== bgp_show_type_community_list_exact
) {
9275 struct community_list
*list
= output_arg
;
9277 if (!community_list_exact_match(
9278 pi
->attr
->community
, list
))
9281 if (type
== bgp_show_type_lcommunity
) {
9282 struct lcommunity
*lcom
= output_arg
;
9284 if (!pi
->attr
->lcommunity
9285 || !lcommunity_match(pi
->attr
->lcommunity
,
9290 if (type
== bgp_show_type_lcommunity_exact
) {
9291 struct lcommunity
*lcom
= output_arg
;
9293 if (!pi
->attr
->lcommunity
9294 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9298 if (type
== bgp_show_type_lcommunity_list
) {
9299 struct community_list
*list
= output_arg
;
9301 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9306 == bgp_show_type_lcommunity_list_exact
) {
9307 struct community_list
*list
= output_arg
;
9309 if (!lcommunity_list_exact_match(
9310 pi
->attr
->lcommunity
, list
))
9313 if (type
== bgp_show_type_lcommunity_all
) {
9314 if (!pi
->attr
->lcommunity
)
9317 if (type
== bgp_show_type_dampend_paths
9318 || type
== bgp_show_type_damp_neighbor
) {
9319 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9320 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9324 if (!use_json
&& header
) {
9325 vty_out(vty
, "BGP table version is %" PRIu64
9326 ", local router ID is %s, vrf id ",
9328 inet_ntoa(bgp
->router_id
));
9329 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9330 vty_out(vty
, "%s", VRFID_NONE_STR
);
9332 vty_out(vty
, "%u", bgp
->vrf_id
);
9334 vty_out(vty
, "Default local pref %u, ",
9335 bgp
->default_local_pref
);
9336 vty_out(vty
, "local AS %u\n", bgp
->as
);
9337 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9338 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9339 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9340 if (type
== bgp_show_type_dampend_paths
9341 || type
== bgp_show_type_damp_neighbor
)
9342 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9343 else if (type
== bgp_show_type_flap_statistics
9344 || type
== bgp_show_type_flap_neighbor
)
9345 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9347 vty_out(vty
, BGP_SHOW_HEADER
);
9350 if (rd
!= NULL
&& !display
&& !output_count
) {
9353 "Route Distinguisher: %s\n",
9356 if (type
== bgp_show_type_dampend_paths
9357 || type
== bgp_show_type_damp_neighbor
)
9358 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
9359 safi
, use_json
, json_paths
);
9360 else if (type
== bgp_show_type_flap_statistics
9361 || type
== bgp_show_type_flap_neighbor
)
9362 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
9363 safi
, use_json
, json_paths
);
9365 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9377 if (p
->family
== AF_FLOWSPEC
) {
9378 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9380 bgp_fs_nlri_get_string((unsigned char *)
9381 p
->u
.prefix_flowspec
.ptr
,
9382 p
->u
.prefix_flowspec
9385 NLRI_STRING_FORMAT_MIN
,
9388 vty_out(vty
, "\"%s/%d\": ",
9390 p
->u
.prefix_flowspec
.prefixlen
);
9392 vty_out(vty
, ",\"%s/%d\": ",
9394 p
->u
.prefix_flowspec
.prefixlen
);
9396 prefix2str(p
, buf2
, sizeof(buf2
));
9398 vty_out(vty
, "\"%s\": ", buf2
);
9400 vty_out(vty
, ",\"%s\": ", buf2
);
9403 json_object_to_json_string(json_paths
));
9404 json_object_free(json_paths
);
9411 output_count
+= *output_cum
;
9412 *output_cum
= output_count
;
9415 total_count
+= *total_cum
;
9416 *total_cum
= total_count
;
9420 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9424 for (i
= 0; i
< *json_header_depth
; ++i
)
9425 vty_out(vty
, " } ");
9430 /* No route is displayed */
9431 if (output_count
== 0) {
9432 if (type
== bgp_show_type_normal
)
9434 "No BGP prefixes displayed, %ld exist\n",
9438 "\nDisplayed %ld routes and %ld total paths\n",
9439 output_count
, total_count
);
9446 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9447 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9448 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9450 struct bgp_node
*rn
, *next
;
9451 unsigned long output_cum
= 0;
9452 unsigned long total_cum
= 0;
9453 unsigned long json_header_depth
= 0;
9454 struct bgp_table
*itable
;
9457 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9459 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9460 next
= bgp_route_next(rn
);
9461 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9464 itable
= bgp_node_get_bgp_table_info(rn
);
9465 if (itable
!= NULL
) {
9466 struct prefix_rd prd
;
9467 char rd
[RD_ADDRSTRLEN
];
9469 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9470 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9471 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9472 use_json
, rd
, next
== NULL
, &output_cum
,
9473 &total_cum
, &json_header_depth
);
9479 if (output_cum
== 0)
9480 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9484 "\nDisplayed %ld routes and %ld total paths\n",
9485 output_cum
, total_cum
);
9489 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9490 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9492 struct bgp_table
*table
;
9493 unsigned long json_header_depth
= 0;
9496 bgp
= bgp_get_default();
9501 vty_out(vty
, "No BGP process is configured\n");
9503 vty_out(vty
, "{}\n");
9507 table
= bgp
->rib
[afi
][safi
];
9508 /* use MPLS and ENCAP specific shows until they are merged */
9509 if (safi
== SAFI_MPLS_VPN
) {
9510 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9511 output_arg
, use_json
);
9514 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9515 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9516 output_arg
, use_json
,
9519 /* labeled-unicast routes live in the unicast table */
9520 else if (safi
== SAFI_LABELED_UNICAST
)
9521 safi
= SAFI_UNICAST
;
9523 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9524 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9527 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9528 safi_t safi
, bool use_json
)
9530 struct listnode
*node
, *nnode
;
9533 bool route_output
= false;
9536 vty_out(vty
, "{\n");
9538 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9539 route_output
= true;
9542 vty_out(vty
, ",\n");
9546 vty_out(vty
, "\"%s\":",
9547 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9551 vty_out(vty
, "\nInstance %s:\n",
9552 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9556 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9561 vty_out(vty
, "}\n");
9562 else if (!route_output
)
9563 vty_out(vty
, "%% BGP instance not found\n");
9566 /* Header of detailed BGP route information */
9567 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9568 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9569 afi_t afi
, safi_t safi
, json_object
*json
)
9571 struct bgp_path_info
*pi
;
9574 struct listnode
*node
, *nnode
;
9575 char buf1
[RD_ADDRSTRLEN
];
9576 char buf2
[INET6_ADDRSTRLEN
];
9577 char buf3
[EVPN_ROUTE_STRLEN
];
9578 char prefix_str
[BUFSIZ
];
9583 int route_filter_translated_v4
= 0;
9584 int route_filter_v4
= 0;
9585 int route_filter_translated_v6
= 0;
9586 int route_filter_v6
= 0;
9589 int accept_own_nexthop
= 0;
9592 int no_advertise
= 0;
9596 int has_valid_label
= 0;
9597 mpls_label_t label
= 0;
9598 json_object
*json_adv_to
= NULL
;
9601 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9603 if (has_valid_label
)
9604 label
= label_pton(&rn
->local_label
);
9607 if (has_valid_label
)
9608 json_object_int_add(json
, "localLabel", label
);
9610 json_object_string_add(
9612 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9614 if (safi
== SAFI_EVPN
)
9615 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9616 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9619 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9620 buf3
, sizeof(buf3
)));
9622 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9623 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9624 ? prefix_rd2str(prd
, buf1
,
9627 safi
== SAFI_MPLS_VPN
? ":" : "",
9628 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9632 if (has_valid_label
)
9633 vty_out(vty
, "Local label: %d\n", label
);
9634 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9635 vty_out(vty
, "not allocated\n");
9638 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9640 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9642 if (pi
->extra
&& pi
->extra
->suppress
)
9645 if (pi
->attr
->community
== NULL
)
9648 no_advertise
+= community_include(
9649 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9650 no_export
+= community_include(pi
->attr
->community
,
9651 COMMUNITY_NO_EXPORT
);
9652 local_as
+= community_include(pi
->attr
->community
,
9653 COMMUNITY_LOCAL_AS
);
9654 accept_own
+= community_include(pi
->attr
->community
,
9655 COMMUNITY_ACCEPT_OWN
);
9656 route_filter_translated_v4
+= community_include(
9657 pi
->attr
->community
,
9658 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9659 route_filter_translated_v6
+= community_include(
9660 pi
->attr
->community
,
9661 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9662 route_filter_v4
+= community_include(
9663 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9664 route_filter_v6
+= community_include(
9665 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9666 llgr_stale
+= community_include(pi
->attr
->community
,
9667 COMMUNITY_LLGR_STALE
);
9668 no_llgr
+= community_include(pi
->attr
->community
,
9670 accept_own_nexthop
+=
9671 community_include(pi
->attr
->community
,
9672 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9673 blackhole
+= community_include(pi
->attr
->community
,
9674 COMMUNITY_BLACKHOLE
);
9675 no_peer
+= community_include(pi
->attr
->community
,
9681 vty_out(vty
, "Paths: (%d available", count
);
9683 vty_out(vty
, ", best #%d", best
);
9684 if (safi
== SAFI_UNICAST
) {
9685 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9686 vty_out(vty
, ", table %s",
9689 vty_out(vty
, ", vrf %s",
9693 vty_out(vty
, ", no best path");
9697 ", accept own local route exported and imported in different VRF");
9698 else if (route_filter_translated_v4
)
9700 ", mark translated RTs for VPNv4 route filtering");
9701 else if (route_filter_v4
)
9703 ", attach RT as-is for VPNv4 route filtering");
9704 else if (route_filter_translated_v6
)
9706 ", mark translated RTs for VPNv6 route filtering");
9707 else if (route_filter_v6
)
9709 ", attach RT as-is for VPNv6 route filtering");
9710 else if (llgr_stale
)
9712 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9715 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9716 else if (accept_own_nexthop
)
9718 ", accept local nexthop");
9720 vty_out(vty
, ", inform peer to blackhole prefix");
9722 vty_out(vty
, ", not advertised to EBGP peer");
9723 else if (no_advertise
)
9724 vty_out(vty
, ", not advertised to any peer");
9726 vty_out(vty
, ", not advertised outside local AS");
9729 ", inform EBGP peer not to advertise to their EBGP peers");
9733 ", Advertisements suppressed by an aggregate.");
9734 vty_out(vty
, ")\n");
9737 /* If we are not using addpath then we can display Advertised to and
9739 * show what peers we advertised the bestpath to. If we are using
9741 * though then we must display Advertised to on a path-by-path basis. */
9742 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9743 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9744 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9745 if (json
&& !json_adv_to
)
9746 json_adv_to
= json_object_new_object();
9748 route_vty_out_advertised_to(
9750 " Advertised to non peer-group peers:\n ",
9757 json_object_object_add(json
, "advertisedTo",
9762 vty_out(vty
, " Not advertised to any peer");
9768 /* Display specified route of BGP table. */
9769 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9770 struct bgp_table
*rib
, const char *ip_str
,
9771 afi_t afi
, safi_t safi
,
9772 struct prefix_rd
*prd
, int prefix_check
,
9773 enum bgp_path_type pathtype
, bool use_json
)
9778 struct prefix match
;
9779 struct bgp_node
*rn
;
9780 struct bgp_node
*rm
;
9781 struct bgp_path_info
*pi
;
9782 struct bgp_table
*table
;
9783 json_object
*json
= NULL
;
9784 json_object
*json_paths
= NULL
;
9786 /* Check IP address argument. */
9787 ret
= str2prefix(ip_str
, &match
);
9789 vty_out(vty
, "address is malformed\n");
9793 match
.family
= afi2family(afi
);
9796 json
= json_object_new_object();
9797 json_paths
= json_object_new_array();
9800 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9801 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9802 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9804 table
= bgp_node_get_bgp_table_info(rn
);
9810 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9814 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9815 bgp_unlock_node(rm
);
9819 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9822 route_vty_out_detail_header(
9824 (struct prefix_rd
*)&rn
->p
,
9825 AFI_IP
, safi
, json
);
9830 if (pathtype
== BGP_PATH_SHOW_ALL
9831 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9832 && CHECK_FLAG(pi
->flags
,
9834 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9835 && (CHECK_FLAG(pi
->flags
,
9837 || CHECK_FLAG(pi
->flags
,
9838 BGP_PATH_SELECTED
))))
9839 route_vty_out_detail(vty
, bgp
, rm
,
9844 bgp_unlock_node(rm
);
9846 } else if (safi
== SAFI_FLOWSPEC
) {
9847 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9848 &match
, prefix_check
,
9855 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9857 || rn
->p
.prefixlen
== match
.prefixlen
) {
9858 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9861 route_vty_out_detail_header(
9862 vty
, bgp
, rn
, NULL
, afi
,
9868 if (pathtype
== BGP_PATH_SHOW_ALL
9870 == BGP_PATH_SHOW_BESTPATH
9875 == BGP_PATH_SHOW_MULTIPATH
9881 BGP_PATH_SELECTED
))))
9882 route_vty_out_detail(
9884 afi
, safi
, json_paths
);
9888 bgp_unlock_node(rn
);
9894 json_object_object_add(json
, "paths", json_paths
);
9896 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9897 json
, JSON_C_TO_STRING_PRETTY
));
9898 json_object_free(json
);
9901 vty_out(vty
, "%% Network not in table\n");
9909 /* Display specified route of Main RIB */
9910 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9911 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9912 int prefix_check
, enum bgp_path_type pathtype
,
9916 bgp
= bgp_get_default();
9919 vty_out(vty
, "No BGP process is configured\n");
9921 vty_out(vty
, "{}\n");
9926 /* labeled-unicast routes live in the unicast table */
9927 if (safi
== SAFI_LABELED_UNICAST
)
9928 safi
= SAFI_UNICAST
;
9930 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9931 afi
, safi
, prd
, prefix_check
, pathtype
,
9935 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9936 struct cmd_token
**argv
, bool exact
, afi_t afi
,
9937 safi_t safi
, bool uj
)
9939 struct lcommunity
*lcom
;
9945 b
= buffer_new(1024);
9946 for (i
= 0; i
< argc
; i
++) {
9948 buffer_putc(b
, ' ');
9950 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9952 buffer_putstr(b
, argv
[i
]->arg
);
9956 buffer_putc(b
, '\0');
9958 str
= buffer_getstr(b
);
9961 lcom
= lcommunity_str2com(str
);
9962 XFREE(MTYPE_TMP
, str
);
9964 vty_out(vty
, "%% Large-community malformed\n");
9968 return bgp_show(vty
, bgp
, afi
, safi
,
9969 (exact
? bgp_show_type_lcommunity_exact
9970 : bgp_show_type_lcommunity
),
9974 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9975 const char *lcom
, bool exact
, afi_t afi
,
9976 safi_t safi
, bool uj
)
9978 struct community_list
*list
;
9980 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9981 LARGE_COMMUNITY_LIST_MASTER
);
9983 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9988 return bgp_show(vty
, bgp
, afi
, safi
,
9989 (exact
? bgp_show_type_lcommunity_list_exact
9990 : bgp_show_type_lcommunity_list
),
9994 DEFUN (show_ip_bgp_large_community_list
,
9995 show_ip_bgp_large_community_list_cmd
,
9996 "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]",
10000 BGP_INSTANCE_HELP_STR
10002 BGP_SAFI_WITH_LABEL_HELP_STR
10003 "Display routes matching the large-community-list\n"
10004 "large-community-list number\n"
10005 "large-community-list name\n"
10006 "Exact match of the large-communities\n"
10010 afi_t afi
= AFI_IP6
;
10011 safi_t safi
= SAFI_UNICAST
;
10013 bool exact_match
= 0;
10015 if (argv_find(argv
, argc
, "ip", &idx
))
10017 if (argv_find(argv
, argc
, "view", &idx
)
10018 || argv_find(argv
, argc
, "vrf", &idx
))
10019 vrf
= argv
[++idx
]->arg
;
10020 if (argv_find(argv
, argc
, "ipv4", &idx
)
10021 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10022 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10023 if (argv_find(argv
, argc
, "unicast", &idx
)
10024 || argv_find(argv
, argc
, "multicast", &idx
))
10025 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10028 bool uj
= use_json(argc
, argv
);
10030 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10032 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10033 return CMD_WARNING
;
10036 argv_find(argv
, argc
, "large-community-list", &idx
);
10038 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10040 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10043 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10044 exact_match
, afi
, safi
, uj
);
10046 DEFUN (show_ip_bgp_large_community
,
10047 show_ip_bgp_large_community_cmd
,
10048 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10052 BGP_INSTANCE_HELP_STR
10054 BGP_SAFI_WITH_LABEL_HELP_STR
10055 "Display routes matching the large-communities\n"
10056 "List of large-community numbers\n"
10057 "Exact match of the large-communities\n"
10061 afi_t afi
= AFI_IP6
;
10062 safi_t safi
= SAFI_UNICAST
;
10064 bool exact_match
= 0;
10066 if (argv_find(argv
, argc
, "ip", &idx
))
10068 if (argv_find(argv
, argc
, "view", &idx
)
10069 || argv_find(argv
, argc
, "vrf", &idx
))
10070 vrf
= argv
[++idx
]->arg
;
10071 if (argv_find(argv
, argc
, "ipv4", &idx
)
10072 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10073 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10074 if (argv_find(argv
, argc
, "unicast", &idx
)
10075 || argv_find(argv
, argc
, "multicast", &idx
))
10076 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10079 bool uj
= use_json(argc
, argv
);
10081 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10083 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10084 return CMD_WARNING
;
10087 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10088 if (argv_find(argv
, argc
, "exact-match", &idx
))
10090 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10091 exact_match
, afi
, safi
, uj
);
10093 return bgp_show(vty
, bgp
, afi
, safi
,
10094 bgp_show_type_lcommunity_all
, NULL
, uj
);
10097 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10101 /* BGP route print out function without JSON */
10102 DEFUN (show_ip_bgp
,
10104 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10105 <dampening <parameters>\
10110 |community-list <(1-500)|WORD> [exact-match]\
10111 |A.B.C.D/M longer-prefixes\
10112 |X:X::X:X/M longer-prefixes\
10117 BGP_INSTANCE_HELP_STR
10119 BGP_SAFI_WITH_LABEL_HELP_STR
10120 "Display detailed information about dampening\n"
10121 "Display detail of configured dampening parameters\n"
10122 "Display routes matching the route-map\n"
10123 "A route-map to match on\n"
10124 "Display routes conforming to the prefix-list\n"
10125 "Prefix-list name\n"
10126 "Display routes conforming to the filter-list\n"
10127 "Regular expression access list name\n"
10128 "BGP RIB advertisement statistics\n"
10129 "Display routes matching the community-list\n"
10130 "community-list number\n"
10131 "community-list name\n"
10132 "Exact match of the communities\n"
10134 "Display route and more specific routes\n"
10136 "Display route and more specific routes\n")
10138 afi_t afi
= AFI_IP6
;
10139 safi_t safi
= SAFI_UNICAST
;
10140 int exact_match
= 0;
10141 struct bgp
*bgp
= NULL
;
10144 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10147 return CMD_WARNING
;
10149 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10150 if (argv_find(argv
, argc
, "parameters", &idx
))
10151 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10154 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10155 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10156 safi
, bgp_show_type_prefix_list
);
10158 if (argv_find(argv
, argc
, "filter-list", &idx
))
10159 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10160 safi
, bgp_show_type_filter_list
);
10162 if (argv_find(argv
, argc
, "statistics", &idx
))
10163 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10165 if (argv_find(argv
, argc
, "route-map", &idx
))
10166 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10167 safi
, bgp_show_type_route_map
);
10169 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10170 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10171 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10173 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10174 exact_match
, afi
, safi
);
10176 /* prefix-longer */
10177 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10178 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10179 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10181 bgp_show_type_prefix_longer
);
10183 return CMD_WARNING
;
10186 /* BGP route print out function with JSON */
10187 DEFUN (show_ip_bgp_json
,
10188 show_ip_bgp_json_cmd
,
10189 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10191 |dampening <flap-statistics|dampened-paths>\
10192 |community [AA:NN|local-AS|no-advertise|no-export\
10193 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10194 |accept-own|accept-own-nexthop|route-filter-v6\
10195 |route-filter-v4|route-filter-translated-v6\
10196 |route-filter-translated-v4] [exact-match]\
10201 BGP_INSTANCE_HELP_STR
10203 BGP_SAFI_WITH_LABEL_HELP_STR
10204 "Display only routes with non-natural netmasks\n"
10205 "Display detailed information about dampening\n"
10206 "Display flap statistics of routes\n"
10207 "Display paths suppressed due to dampening\n"
10208 "Display routes matching the communities\n"
10210 "Do not send outside local AS (well-known community)\n"
10211 "Do not advertise to any peer (well-known community)\n"
10212 "Do not export to next AS (well-known community)\n"
10213 "Graceful shutdown (well-known community)\n"
10214 "Do not export to any peer (well-known community)\n"
10215 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10216 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10217 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10218 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10219 "Should accept VPN route with local nexthop (well-known community)\n"
10220 "RT VPNv6 route filtering (well-known community)\n"
10221 "RT VPNv4 route filtering (well-known community)\n"
10222 "RT translated VPNv6 route filtering (well-known community)\n"
10223 "RT translated VPNv4 route filtering (well-known community)\n"
10224 "Exact match of the communities\n"
10227 afi_t afi
= AFI_IP6
;
10228 safi_t safi
= SAFI_UNICAST
;
10229 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10230 struct bgp
*bgp
= NULL
;
10232 int exact_match
= 0;
10233 bool uj
= use_json(argc
, argv
);
10238 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10241 return CMD_WARNING
;
10243 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10244 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10247 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10248 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10249 return bgp_show(vty
, bgp
, afi
, safi
,
10250 bgp_show_type_dampend_paths
, NULL
, uj
);
10251 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10252 return bgp_show(vty
, bgp
, afi
, safi
,
10253 bgp_show_type_flap_statistics
, NULL
,
10257 if (argv_find(argv
, argc
, "community", &idx
)) {
10258 char *maybecomm
= NULL
;
10259 char *community
= NULL
;
10261 if (idx
+ 1 < argc
) {
10262 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10263 maybecomm
= argv
[idx
+ 1]->arg
;
10265 maybecomm
= argv
[idx
+ 1]->text
;
10268 if (maybecomm
&& !strmatch(maybecomm
, "json")
10269 && !strmatch(maybecomm
, "exact-match"))
10270 community
= maybecomm
;
10272 if (argv_find(argv
, argc
, "exact-match", &idx
))
10276 return bgp_show_community(vty
, bgp
, community
,
10277 exact_match
, afi
, safi
, uj
);
10279 return (bgp_show(vty
, bgp
, afi
, safi
,
10280 bgp_show_type_community_all
, NULL
,
10284 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10287 DEFUN (show_ip_bgp_route
,
10288 show_ip_bgp_route_cmd
,
10289 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10290 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10294 BGP_INSTANCE_HELP_STR
10296 BGP_SAFI_WITH_LABEL_HELP_STR
10297 "Network in the BGP routing table to display\n"
10299 "Network in the BGP routing table to display\n"
10301 "Display only the bestpath\n"
10302 "Display only multipaths\n"
10305 int prefix_check
= 0;
10307 afi_t afi
= AFI_IP6
;
10308 safi_t safi
= SAFI_UNICAST
;
10309 char *prefix
= NULL
;
10310 struct bgp
*bgp
= NULL
;
10311 enum bgp_path_type path_type
;
10312 bool uj
= use_json(argc
, argv
);
10316 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10319 return CMD_WARNING
;
10323 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10324 return CMD_WARNING
;
10327 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10328 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10329 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10331 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10332 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10335 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10336 && afi
!= AFI_IP6
) {
10338 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10339 return CMD_WARNING
;
10341 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10342 && afi
!= AFI_IP
) {
10344 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10345 return CMD_WARNING
;
10348 prefix
= argv
[idx
]->arg
;
10350 /* [<bestpath|multipath>] */
10351 if (argv_find(argv
, argc
, "bestpath", &idx
))
10352 path_type
= BGP_PATH_SHOW_BESTPATH
;
10353 else if (argv_find(argv
, argc
, "multipath", &idx
))
10354 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10356 path_type
= BGP_PATH_SHOW_ALL
;
10358 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10362 DEFUN (show_ip_bgp_regexp
,
10363 show_ip_bgp_regexp_cmd
,
10364 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10368 BGP_INSTANCE_HELP_STR
10370 BGP_SAFI_WITH_LABEL_HELP_STR
10371 "Display routes matching the AS path regular expression\n"
10372 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10374 afi_t afi
= AFI_IP6
;
10375 safi_t safi
= SAFI_UNICAST
;
10376 struct bgp
*bgp
= NULL
;
10379 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10382 return CMD_WARNING
;
10384 // get index of regex
10385 argv_find(argv
, argc
, "regexp", &idx
);
10388 char *regstr
= argv_concat(argv
, argc
, idx
);
10389 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10390 bgp_show_type_regexp
);
10391 XFREE(MTYPE_TMP
, regstr
);
10395 DEFUN (show_ip_bgp_instance_all
,
10396 show_ip_bgp_instance_all_cmd
,
10397 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10401 BGP_INSTANCE_ALL_HELP_STR
10403 BGP_SAFI_WITH_LABEL_HELP_STR
10406 afi_t afi
= AFI_IP
;
10407 safi_t safi
= SAFI_UNICAST
;
10408 struct bgp
*bgp
= NULL
;
10410 bool uj
= use_json(argc
, argv
);
10415 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10418 return CMD_WARNING
;
10420 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10421 return CMD_SUCCESS
;
10424 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10425 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10430 if (!config_bgp_aspath_validate(regstr
)) {
10431 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10433 return CMD_WARNING_CONFIG_FAILED
;
10436 regex
= bgp_regcomp(regstr
);
10438 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10439 return CMD_WARNING
;
10442 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10443 bgp_regex_free(regex
);
10447 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10448 const char *prefix_list_str
, afi_t afi
,
10449 safi_t safi
, enum bgp_show_type type
)
10451 struct prefix_list
*plist
;
10453 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10454 if (plist
== NULL
) {
10455 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10457 return CMD_WARNING
;
10460 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10463 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10464 const char *filter
, afi_t afi
, safi_t safi
,
10465 enum bgp_show_type type
)
10467 struct as_list
*as_list
;
10469 as_list
= as_list_lookup(filter
);
10470 if (as_list
== NULL
) {
10471 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10473 return CMD_WARNING
;
10476 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10479 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10480 const char *rmap_str
, afi_t afi
, safi_t safi
,
10481 enum bgp_show_type type
)
10483 struct route_map
*rmap
;
10485 rmap
= route_map_lookup_by_name(rmap_str
);
10487 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10488 return CMD_WARNING
;
10491 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10494 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10495 const char *comstr
, int exact
, afi_t afi
,
10496 safi_t safi
, bool use_json
)
10498 struct community
*com
;
10501 com
= community_str2com(comstr
);
10503 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10504 return CMD_WARNING
;
10507 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10508 (exact
? bgp_show_type_community_exact
10509 : bgp_show_type_community
),
10511 community_free(&com
);
10516 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10517 const char *com
, int exact
, afi_t afi
,
10520 struct community_list
*list
;
10522 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10523 if (list
== NULL
) {
10524 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10525 return CMD_WARNING
;
10528 return bgp_show(vty
, bgp
, afi
, safi
,
10529 (exact
? bgp_show_type_community_list_exact
10530 : bgp_show_type_community_list
),
10534 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10535 const char *prefix
, afi_t afi
, safi_t safi
,
10536 enum bgp_show_type type
)
10543 ret
= str2prefix(prefix
, p
);
10545 vty_out(vty
, "%% Malformed Prefix\n");
10546 return CMD_WARNING
;
10549 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10555 BGP_STATS_MAXBITLEN
= 0,
10557 BGP_STATS_PREFIXES
,
10559 BGP_STATS_UNAGGREGATEABLE
,
10560 BGP_STATS_MAX_AGGREGATEABLE
,
10561 BGP_STATS_AGGREGATES
,
10563 BGP_STATS_ASPATH_COUNT
,
10564 BGP_STATS_ASPATH_MAXHOPS
,
10565 BGP_STATS_ASPATH_TOTHOPS
,
10566 BGP_STATS_ASPATH_MAXSIZE
,
10567 BGP_STATS_ASPATH_TOTSIZE
,
10568 BGP_STATS_ASN_HIGHEST
,
10572 static const char *table_stats_strs
[] = {
10573 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10574 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10575 [BGP_STATS_RIB
] = "Total Advertisements",
10576 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10577 [BGP_STATS_MAX_AGGREGATEABLE
] =
10578 "Maximum aggregateable prefixes",
10579 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10580 [BGP_STATS_SPACE
] = "Address space advertised",
10581 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10582 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10583 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10584 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10585 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10586 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10587 [BGP_STATS_MAX
] = NULL
,
10590 struct bgp_table_stats
{
10591 struct bgp_table
*table
;
10592 unsigned long long counts
[BGP_STATS_MAX
];
10593 double total_space
;
10597 #define TALLY_SIGFIG 100000
10598 static unsigned long
10599 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10601 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10602 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10603 unsigned long ret
= newtot
/ count
;
10605 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10612 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10613 struct bgp_table_stats
*ts
, unsigned int space
)
10615 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10616 struct bgp_path_info
*pi
;
10621 if (!bgp_node_has_bgp_path_info_data(rn
))
10624 ts
->counts
[BGP_STATS_PREFIXES
]++;
10625 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10628 ts
->counts
[BGP_STATS_AVGPLEN
]
10629 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10630 ts
->counts
[BGP_STATS_AVGPLEN
],
10634 /* check if the prefix is included by any other announcements */
10635 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10636 prn
= bgp_node_parent_nolock(prn
);
10638 if (prn
== NULL
|| prn
== top
) {
10639 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10640 /* announced address space */
10642 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10643 } else if (bgp_node_has_bgp_path_info_data(prn
))
10644 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10647 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10648 ts
->counts
[BGP_STATS_RIB
]++;
10651 && (CHECK_FLAG(pi
->attr
->flag
,
10652 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))))
10653 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10655 /* as-path stats */
10656 if (pi
->attr
&& pi
->attr
->aspath
) {
10657 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10658 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10659 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10661 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10663 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10664 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10666 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10667 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10669 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10670 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10672 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10673 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10674 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10676 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10677 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10678 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10681 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10682 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10687 static int bgp_table_stats_walker(struct thread
*t
)
10689 struct bgp_node
*rn
, *nrn
;
10690 struct bgp_node
*top
;
10691 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10692 unsigned int space
= 0;
10694 if (!(top
= bgp_table_top(ts
->table
)))
10697 switch (ts
->table
->afi
) {
10699 space
= IPV4_MAX_BITLEN
;
10702 space
= IPV6_MAX_BITLEN
;
10708 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10710 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10711 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10712 struct bgp_table
*table
;
10714 table
= bgp_node_get_bgp_table_info(rn
);
10718 top
= bgp_table_top(table
);
10719 for (nrn
= bgp_table_top(table
); nrn
;
10720 nrn
= bgp_route_next(nrn
))
10721 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10723 bgp_table_stats_rn(rn
, top
, ts
, space
);
10730 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10733 struct bgp_table_stats ts
;
10736 if (!bgp
->rib
[afi
][safi
]) {
10737 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10739 return CMD_WARNING
;
10742 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
10744 /* labeled-unicast routes live in the unicast table */
10745 if (safi
== SAFI_LABELED_UNICAST
)
10746 safi
= SAFI_UNICAST
;
10748 memset(&ts
, 0, sizeof(ts
));
10749 ts
.table
= bgp
->rib
[afi
][safi
];
10750 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10752 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10753 if (!table_stats_strs
[i
])
10758 case BGP_STATS_ASPATH_AVGHOPS
:
10759 case BGP_STATS_ASPATH_AVGSIZE
:
10760 case BGP_STATS_AVGPLEN
:
10761 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10762 vty_out (vty
, "%12.2f",
10763 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10766 case BGP_STATS_ASPATH_TOTHOPS
:
10767 case BGP_STATS_ASPATH_TOTSIZE
:
10768 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10769 vty_out(vty
, "%12.2f",
10771 ? (float)ts
.counts
[i
]
10773 [BGP_STATS_ASPATH_COUNT
]
10776 case BGP_STATS_TOTPLEN
:
10777 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10778 vty_out(vty
, "%12.2f",
10780 ? (float)ts
.counts
[i
]
10782 [BGP_STATS_PREFIXES
]
10785 case BGP_STATS_SPACE
:
10786 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10787 vty_out(vty
, "%12g\n", ts
.total_space
);
10789 if (afi
== AFI_IP6
) {
10790 vty_out(vty
, "%30s: ", "/32 equivalent ");
10791 vty_out(vty
, "%12g\n",
10792 ts
.total_space
* pow(2.0, -128 + 32));
10793 vty_out(vty
, "%30s: ", "/48 equivalent ");
10794 vty_out(vty
, "%12g\n",
10795 ts
.total_space
* pow(2.0, -128 + 48));
10797 vty_out(vty
, "%30s: ", "% announced ");
10798 vty_out(vty
, "%12.2f\n",
10799 ts
.total_space
* 100. * pow(2.0, -32));
10800 vty_out(vty
, "%30s: ", "/8 equivalent ");
10801 vty_out(vty
, "%12.2f\n",
10802 ts
.total_space
* pow(2.0, -32 + 8));
10803 vty_out(vty
, "%30s: ", "/24 equivalent ");
10804 vty_out(vty
, "%12.2f\n",
10805 ts
.total_space
* pow(2.0, -32 + 24));
10809 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10810 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10813 vty_out(vty
, "\n");
10815 return CMD_SUCCESS
;
10827 PCOUNT_PFCNT
, /* the figure we display to users */
10831 static const char *pcount_strs
[] = {
10832 [PCOUNT_ADJ_IN
] = "Adj-in",
10833 [PCOUNT_DAMPED
] = "Damped",
10834 [PCOUNT_REMOVED
] = "Removed",
10835 [PCOUNT_HISTORY
] = "History",
10836 [PCOUNT_STALE
] = "Stale",
10837 [PCOUNT_VALID
] = "Valid",
10838 [PCOUNT_ALL
] = "All RIB",
10839 [PCOUNT_COUNTED
] = "PfxCt counted",
10840 [PCOUNT_PFCNT
] = "Useable",
10841 [PCOUNT_MAX
] = NULL
,
10844 struct peer_pcounts
{
10845 unsigned int count
[PCOUNT_MAX
];
10846 const struct peer
*peer
;
10847 const struct bgp_table
*table
;
10850 static int bgp_peer_count_walker(struct thread
*t
)
10852 struct bgp_node
*rn
;
10853 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10854 const struct peer
*peer
= pc
->peer
;
10856 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10857 struct bgp_adj_in
*ain
;
10858 struct bgp_path_info
*pi
;
10860 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10861 if (ain
->peer
== peer
)
10862 pc
->count
[PCOUNT_ADJ_IN
]++;
10864 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10866 if (pi
->peer
!= peer
)
10869 pc
->count
[PCOUNT_ALL
]++;
10871 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10872 pc
->count
[PCOUNT_DAMPED
]++;
10873 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10874 pc
->count
[PCOUNT_HISTORY
]++;
10875 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10876 pc
->count
[PCOUNT_REMOVED
]++;
10877 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10878 pc
->count
[PCOUNT_STALE
]++;
10879 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10880 pc
->count
[PCOUNT_VALID
]++;
10881 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10882 pc
->count
[PCOUNT_PFCNT
]++;
10884 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10885 pc
->count
[PCOUNT_COUNTED
]++;
10886 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10888 EC_LIB_DEVELOPMENT
,
10889 "Attempting to count but flags say it is unusable");
10891 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10893 EC_LIB_DEVELOPMENT
,
10894 "Not counted but flags say we should");
10901 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10902 safi_t safi
, bool use_json
)
10904 struct peer_pcounts pcounts
= {.peer
= peer
};
10906 json_object
*json
= NULL
;
10907 json_object
*json_loop
= NULL
;
10910 json
= json_object_new_object();
10911 json_loop
= json_object_new_object();
10914 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10915 || !peer
->bgp
->rib
[afi
][safi
]) {
10917 json_object_string_add(
10919 "No such neighbor or address family");
10920 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10921 json_object_free(json
);
10923 vty_out(vty
, "%% No such neighbor or address family\n");
10925 return CMD_WARNING
;
10928 memset(&pcounts
, 0, sizeof(pcounts
));
10929 pcounts
.peer
= peer
;
10930 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10932 /* in-place call via thread subsystem so as to record execution time
10933 * stats for the thread-walk (i.e. ensure this can't be blamed on
10934 * on just vty_read()).
10936 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10939 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10940 json_object_string_add(json
, "multiProtocol",
10941 get_afi_safi_str(afi
, safi
, true));
10942 json_object_int_add(json
, "pfxCounter",
10943 peer
->pcount
[afi
][safi
]);
10945 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10946 json_object_int_add(json_loop
, pcount_strs
[i
],
10949 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10951 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10952 json_object_string_add(json
, "pfxctDriftFor",
10954 json_object_string_add(
10955 json
, "recommended",
10956 "Please report this bug, with the above command output");
10958 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10959 json
, JSON_C_TO_STRING_PRETTY
));
10960 json_object_free(json
);
10964 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10965 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10966 peer
->hostname
, peer
->host
,
10967 get_afi_safi_str(afi
, safi
, false));
10969 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10970 get_afi_safi_str(afi
, safi
, false));
10973 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10974 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10976 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10977 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10980 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10981 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10983 "Please report this bug, with the above command output\n");
10987 return CMD_SUCCESS
;
10990 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10991 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10992 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10993 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10997 BGP_INSTANCE_HELP_STR
11000 "Detailed information on TCP and BGP neighbor connections\n"
11001 "Neighbor to display information about\n"
11002 "Neighbor to display information about\n"
11003 "Neighbor on BGP configured interface\n"
11004 "Display detailed prefix count information\n"
11007 afi_t afi
= AFI_IP6
;
11008 safi_t safi
= SAFI_UNICAST
;
11011 struct bgp
*bgp
= NULL
;
11012 bool uj
= use_json(argc
, argv
);
11017 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11020 return CMD_WARNING
;
11022 argv_find(argv
, argc
, "neighbors", &idx
);
11023 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11025 return CMD_WARNING
;
11027 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11030 #ifdef KEEP_OLD_VPN_COMMANDS
11031 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11032 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11033 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11038 "Display information about all VPNv4 NLRIs\n"
11039 "Detailed information on TCP and BGP neighbor connections\n"
11040 "Neighbor to display information about\n"
11041 "Neighbor to display information about\n"
11042 "Neighbor on BGP configured interface\n"
11043 "Display detailed prefix count information\n"
11048 bool uj
= use_json(argc
, argv
);
11050 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11052 return CMD_WARNING
;
11054 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11057 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11058 show_ip_bgp_vpn_all_route_prefix_cmd
,
11059 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11064 "Display information about all VPNv4 NLRIs\n"
11065 "Network in the BGP routing table to display\n"
11066 "Network in the BGP routing table to display\n"
11070 char *network
= NULL
;
11071 struct bgp
*bgp
= bgp_get_default();
11073 vty_out(vty
, "Can't find default instance\n");
11074 return CMD_WARNING
;
11077 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11078 network
= argv
[idx
]->arg
;
11079 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11080 network
= argv
[idx
]->arg
;
11082 vty_out(vty
, "Unable to figure out Network\n");
11083 return CMD_WARNING
;
11086 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11087 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11089 #endif /* KEEP_OLD_VPN_COMMANDS */
11091 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
11092 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
11093 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
11099 "Display information about all EVPN NLRIs\n"
11100 "Network in the BGP routing table to display\n"
11101 "Network in the BGP routing table to display\n"
11105 char *network
= NULL
;
11107 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11108 network
= argv
[idx
]->arg
;
11109 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11110 network
= argv
[idx
]->arg
;
11112 vty_out(vty
, "Unable to figure out Network\n");
11113 return CMD_WARNING
;
11115 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
11116 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11119 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11120 safi_t safi
, enum bgp_show_adj_route_type type
,
11121 const char *rmap_name
, bool use_json
,
11124 struct bgp_table
*table
;
11125 struct bgp_adj_in
*ain
;
11126 struct bgp_adj_out
*adj
;
11127 unsigned long output_count
;
11128 unsigned long filtered_count
;
11129 struct bgp_node
*rn
;
11135 struct update_subgroup
*subgrp
;
11136 json_object
*json_scode
= NULL
;
11137 json_object
*json_ocode
= NULL
;
11138 json_object
*json_ar
= NULL
;
11139 struct peer_af
*paf
;
11140 bool route_filtered
;
11143 json_scode
= json_object_new_object();
11144 json_ocode
= json_object_new_object();
11145 json_ar
= json_object_new_object();
11147 json_object_string_add(json_scode
, "suppressed", "s");
11148 json_object_string_add(json_scode
, "damped", "d");
11149 json_object_string_add(json_scode
, "history", "h");
11150 json_object_string_add(json_scode
, "valid", "*");
11151 json_object_string_add(json_scode
, "best", ">");
11152 json_object_string_add(json_scode
, "multipath", "=");
11153 json_object_string_add(json_scode
, "internal", "i");
11154 json_object_string_add(json_scode
, "ribFailure", "r");
11155 json_object_string_add(json_scode
, "stale", "S");
11156 json_object_string_add(json_scode
, "removed", "R");
11158 json_object_string_add(json_ocode
, "igp", "i");
11159 json_object_string_add(json_ocode
, "egp", "e");
11160 json_object_string_add(json_ocode
, "incomplete", "?");
11167 json_object_string_add(json
, "alert", "no BGP");
11168 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11169 json_object_free(json
);
11171 vty_out(vty
, "%% No bgp\n");
11175 /* labeled-unicast routes live in the unicast table */
11176 if (safi
== SAFI_LABELED_UNICAST
)
11177 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11179 table
= bgp
->rib
[afi
][safi
];
11181 output_count
= filtered_count
= 0;
11182 subgrp
= peer_subgroup(peer
, afi
, safi
);
11184 if (type
== bgp_show_adj_route_advertised
&& subgrp
11185 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11187 json_object_int_add(json
, "bgpTableVersion",
11189 json_object_string_add(json
, "bgpLocalRouterId",
11190 inet_ntoa(bgp
->router_id
));
11191 json_object_int_add(json
, "defaultLocPrf",
11192 bgp
->default_local_pref
);
11193 json_object_int_add(json
, "localAS", bgp
->as
);
11194 json_object_object_add(json
, "bgpStatusCodes",
11196 json_object_object_add(json
, "bgpOriginCodes",
11198 json_object_string_add(
11199 json
, "bgpOriginatingDefaultNetwork",
11200 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11202 vty_out(vty
, "BGP table version is %" PRIu64
11203 ", local router ID is %s, vrf id ",
11204 table
->version
, inet_ntoa(bgp
->router_id
));
11205 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11206 vty_out(vty
, "%s", VRFID_NONE_STR
);
11208 vty_out(vty
, "%u", bgp
->vrf_id
);
11209 vty_out(vty
, "\n");
11210 vty_out(vty
, "Default local pref %u, ",
11211 bgp
->default_local_pref
);
11212 vty_out(vty
, "local AS %u\n", bgp
->as
);
11213 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11214 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11215 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11217 vty_out(vty
, "Originating default network %s\n\n",
11218 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11223 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11224 if (type
== bgp_show_adj_route_received
11225 || type
== bgp_show_adj_route_filtered
) {
11226 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11227 if (ain
->peer
!= peer
|| !ain
->attr
)
11232 json_object_int_add(
11233 json
, "bgpTableVersion",
11235 json_object_string_add(
11237 "bgpLocalRouterId",
11240 json_object_int_add(json
,
11242 bgp
->default_local_pref
);
11243 json_object_int_add(json
,
11244 "localAS", bgp
->as
);
11245 json_object_object_add(
11246 json
, "bgpStatusCodes",
11248 json_object_object_add(
11249 json
, "bgpOriginCodes",
11253 "BGP table version is 0, local router ID is %s, vrf id ",
11256 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11262 vty_out(vty
, "\n");
11264 "Default local pref %u, ",
11265 bgp
->default_local_pref
);
11266 vty_out(vty
, "local AS %u\n",
11269 BGP_SHOW_SCODE_HEADER
);
11271 BGP_SHOW_NCODE_HEADER
);
11273 BGP_SHOW_OCODE_HEADER
);
11279 vty_out(vty
, BGP_SHOW_HEADER
);
11283 bgp_attr_dup(&attr
, ain
->attr
);
11284 route_filtered
= false;
11286 /* Filter prefix using distribute list,
11287 * filter list or prefix list
11289 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11290 safi
)) == FILTER_DENY
)
11291 route_filtered
= true;
11293 /* Filter prefix using route-map */
11294 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11295 afi
, safi
, rmap_name
, NULL
, 0);
11297 if (type
== bgp_show_adj_route_filtered
&&
11298 !route_filtered
&& ret
!= RMAP_DENY
) {
11299 bgp_attr_undup(&attr
, ain
->attr
);
11303 if (type
== bgp_show_adj_route_received
&&
11304 (route_filtered
|| ret
== RMAP_DENY
))
11307 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11308 use_json
, json_ar
);
11309 bgp_attr_undup(&attr
, ain
->attr
);
11312 } else if (type
== bgp_show_adj_route_advertised
) {
11313 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11314 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11315 if (paf
->peer
!= peer
|| !adj
->attr
)
11320 json_object_int_add(
11324 json_object_string_add(
11326 "bgpLocalRouterId",
11329 json_object_int_add(
11330 json
, "defaultLocPrf",
11331 bgp
->default_local_pref
11333 json_object_int_add(
11336 json_object_object_add(
11340 json_object_object_add(
11346 "BGP table version is %" PRIu64
11347 ", local router ID is %s, vrf id ",
11360 vty_out(vty
, "\n");
11362 "Default local pref %u, ",
11363 bgp
->default_local_pref
11369 BGP_SHOW_SCODE_HEADER
);
11371 BGP_SHOW_NCODE_HEADER
);
11373 BGP_SHOW_OCODE_HEADER
);
11384 bgp_attr_dup(&attr
, adj
->attr
);
11385 ret
= bgp_output_modifier(
11386 peer
, &rn
->p
, &attr
, afi
, safi
,
11389 if (ret
!= RMAP_DENY
) {
11390 route_vty_out_tmp(vty
, &rn
->p
,
11399 bgp_attr_undup(&attr
, adj
->attr
);
11405 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11406 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11407 json_object_int_add(json
, "filteredPrefixCounter",
11410 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11411 json
, JSON_C_TO_STRING_PRETTY
));
11412 json_object_free(json
);
11413 } else if (output_count
> 0) {
11414 if (filtered_count
> 0)
11416 "\nTotal number of prefixes %ld (%ld filtered)\n",
11417 output_count
, filtered_count
);
11419 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11424 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11425 safi_t safi
, enum bgp_show_adj_route_type type
,
11426 const char *rmap_name
, bool use_json
)
11428 json_object
*json
= NULL
;
11431 json
= json_object_new_object();
11433 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11435 json_object_string_add(
11437 "No such neighbor or address family");
11438 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11439 json_object_free(json
);
11441 vty_out(vty
, "%% No such neighbor or address family\n");
11443 return CMD_WARNING
;
11446 if ((type
== bgp_show_adj_route_received
11447 || type
== bgp_show_adj_route_filtered
)
11448 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11449 PEER_FLAG_SOFT_RECONFIG
)) {
11451 json_object_string_add(
11453 "Inbound soft reconfiguration not enabled");
11454 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11455 json_object_free(json
);
11458 "%% Inbound soft reconfiguration not enabled\n");
11460 return CMD_WARNING
;
11463 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11465 return CMD_SUCCESS
;
11468 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11469 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11470 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11471 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11475 BGP_INSTANCE_HELP_STR
11477 BGP_SAFI_WITH_LABEL_HELP_STR
11478 "Detailed information on TCP and BGP neighbor connections\n"
11479 "Neighbor to display information about\n"
11480 "Neighbor to display information about\n"
11481 "Neighbor on BGP configured interface\n"
11482 "Display the routes advertised to a BGP neighbor\n"
11483 "Display the received routes from neighbor\n"
11484 "Display the filtered routes received from neighbor\n"
11485 "Route-map to modify the attributes\n"
11486 "Name of the route map\n"
11489 afi_t afi
= AFI_IP6
;
11490 safi_t safi
= SAFI_UNICAST
;
11491 char *rmap_name
= NULL
;
11492 char *peerstr
= NULL
;
11493 struct bgp
*bgp
= NULL
;
11495 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11497 bool uj
= use_json(argc
, argv
);
11502 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11505 return CMD_WARNING
;
11507 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11508 argv_find(argv
, argc
, "neighbors", &idx
);
11509 peerstr
= argv
[++idx
]->arg
;
11511 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11513 return CMD_WARNING
;
11515 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11516 type
= bgp_show_adj_route_advertised
;
11517 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11518 type
= bgp_show_adj_route_received
;
11519 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11520 type
= bgp_show_adj_route_filtered
;
11522 if (argv_find(argv
, argc
, "route-map", &idx
))
11523 rmap_name
= argv
[++idx
]->arg
;
11525 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11528 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11529 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11530 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11536 "Address Family modifier\n"
11537 "Detailed information on TCP and BGP neighbor connections\n"
11538 "Neighbor to display information about\n"
11539 "Neighbor to display information about\n"
11540 "Neighbor on BGP configured interface\n"
11541 "Display information received from a BGP neighbor\n"
11542 "Display the prefixlist filter\n"
11545 afi_t afi
= AFI_IP6
;
11546 safi_t safi
= SAFI_UNICAST
;
11547 char *peerstr
= NULL
;
11550 union sockunion su
;
11556 /* show [ip] bgp */
11557 if (argv_find(argv
, argc
, "ip", &idx
))
11559 /* [<ipv4|ipv6> [unicast]] */
11560 if (argv_find(argv
, argc
, "ipv4", &idx
))
11562 if (argv_find(argv
, argc
, "ipv6", &idx
))
11564 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11565 argv_find(argv
, argc
, "neighbors", &idx
);
11566 peerstr
= argv
[++idx
]->arg
;
11568 bool uj
= use_json(argc
, argv
);
11570 ret
= str2sockunion(peerstr
, &su
);
11572 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11575 vty_out(vty
, "{}\n");
11578 "%% Malformed address or name: %s\n",
11580 return CMD_WARNING
;
11583 peer
= peer_lookup(NULL
, &su
);
11586 vty_out(vty
, "{}\n");
11588 vty_out(vty
, "No peer\n");
11589 return CMD_WARNING
;
11593 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11594 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11597 vty_out(vty
, "Address Family: %s\n",
11598 get_afi_safi_str(afi
, safi
, false));
11599 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11602 vty_out(vty
, "{}\n");
11604 vty_out(vty
, "No functional output\n");
11607 return CMD_SUCCESS
;
11610 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11611 afi_t afi
, safi_t safi
,
11612 enum bgp_show_type type
, bool use_json
)
11614 /* labeled-unicast routes live in the unicast table */
11615 if (safi
== SAFI_LABELED_UNICAST
)
11616 safi
= SAFI_UNICAST
;
11618 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11620 json_object
*json_no
= NULL
;
11621 json_no
= json_object_new_object();
11622 json_object_string_add(
11623 json_no
, "warning",
11624 "No such neighbor or address family");
11625 vty_out(vty
, "%s\n",
11626 json_object_to_json_string(json_no
));
11627 json_object_free(json_no
);
11629 vty_out(vty
, "%% No such neighbor or address family\n");
11630 return CMD_WARNING
;
11633 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11636 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11637 show_ip_bgp_flowspec_routes_detailed_cmd
,
11638 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11642 BGP_INSTANCE_HELP_STR
11645 "Detailed information on flowspec entries\n"
11648 afi_t afi
= AFI_IP
;
11649 safi_t safi
= SAFI_UNICAST
;
11650 struct bgp
*bgp
= NULL
;
11652 bool uj
= use_json(argc
, argv
);
11657 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11660 return CMD_WARNING
;
11662 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11665 DEFUN (show_ip_bgp_neighbor_routes
,
11666 show_ip_bgp_neighbor_routes_cmd
,
11667 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11668 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11672 BGP_INSTANCE_HELP_STR
11674 BGP_SAFI_WITH_LABEL_HELP_STR
11675 "Detailed information on TCP and BGP neighbor connections\n"
11676 "Neighbor to display information about\n"
11677 "Neighbor to display information about\n"
11678 "Neighbor on BGP configured interface\n"
11679 "Display flap statistics of the routes learned from neighbor\n"
11680 "Display the dampened routes received from neighbor\n"
11681 "Display routes learned from neighbor\n"
11684 char *peerstr
= NULL
;
11685 struct bgp
*bgp
= NULL
;
11686 afi_t afi
= AFI_IP6
;
11687 safi_t safi
= SAFI_UNICAST
;
11689 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11691 bool uj
= use_json(argc
, argv
);
11696 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11699 return CMD_WARNING
;
11701 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11702 argv_find(argv
, argc
, "neighbors", &idx
);
11703 peerstr
= argv
[++idx
]->arg
;
11705 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11707 return CMD_WARNING
;
11709 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11710 sh_type
= bgp_show_type_flap_neighbor
;
11711 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11712 sh_type
= bgp_show_type_damp_neighbor
;
11713 else if (argv_find(argv
, argc
, "routes", &idx
))
11714 sh_type
= bgp_show_type_neighbor
;
11716 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11719 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11721 struct bgp_distance
{
11722 /* Distance value for the IP source prefix. */
11725 /* Name of the access-list to be matched. */
11729 DEFUN (show_bgp_afi_vpn_rd_route
,
11730 show_bgp_afi_vpn_rd_route_cmd
,
11731 "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]",
11735 "Address Family modifier\n"
11736 "Display information for a route distinguisher\n"
11737 "Route Distinguisher\n"
11738 "Network in the BGP routing table to display\n"
11739 "Network in the BGP routing table to display\n"
11743 struct prefix_rd prd
;
11744 afi_t afi
= AFI_MAX
;
11747 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11748 vty_out(vty
, "%% Malformed Address Family\n");
11749 return CMD_WARNING
;
11752 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11754 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11755 return CMD_WARNING
;
11758 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11759 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11762 static struct bgp_distance
*bgp_distance_new(void)
11764 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11767 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11769 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11772 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11773 const char *ip_str
, const char *access_list_str
)
11780 struct bgp_node
*rn
;
11781 struct bgp_distance
*bdistance
;
11783 afi
= bgp_node_afi(vty
);
11784 safi
= bgp_node_safi(vty
);
11786 ret
= str2prefix(ip_str
, &p
);
11788 vty_out(vty
, "Malformed prefix\n");
11789 return CMD_WARNING_CONFIG_FAILED
;
11792 distance
= atoi(distance_str
);
11794 /* Get BGP distance node. */
11795 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11796 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11798 bgp_unlock_node(rn
);
11800 bdistance
= bgp_distance_new();
11801 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11804 /* Set distance value. */
11805 bdistance
->distance
= distance
;
11807 /* Reset access-list configuration. */
11808 if (bdistance
->access_list
) {
11809 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11810 bdistance
->access_list
= NULL
;
11812 if (access_list_str
)
11813 bdistance
->access_list
=
11814 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11816 return CMD_SUCCESS
;
11819 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11820 const char *ip_str
, const char *access_list_str
)
11827 struct bgp_node
*rn
;
11828 struct bgp_distance
*bdistance
;
11830 afi
= bgp_node_afi(vty
);
11831 safi
= bgp_node_safi(vty
);
11833 ret
= str2prefix(ip_str
, &p
);
11835 vty_out(vty
, "Malformed prefix\n");
11836 return CMD_WARNING_CONFIG_FAILED
;
11839 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11840 (struct prefix
*)&p
);
11842 vty_out(vty
, "Can't find specified prefix\n");
11843 return CMD_WARNING_CONFIG_FAILED
;
11846 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11847 distance
= atoi(distance_str
);
11849 if (bdistance
->distance
!= distance
) {
11850 vty_out(vty
, "Distance does not match configured\n");
11851 return CMD_WARNING_CONFIG_FAILED
;
11854 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11855 bgp_distance_free(bdistance
);
11857 bgp_node_set_bgp_path_info(rn
, NULL
);
11858 bgp_unlock_node(rn
);
11859 bgp_unlock_node(rn
);
11861 return CMD_SUCCESS
;
11864 /* Apply BGP information to distance method. */
11865 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11866 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11868 struct bgp_node
*rn
;
11871 struct bgp_distance
*bdistance
;
11872 struct access_list
*alist
;
11873 struct bgp_static
*bgp_static
;
11878 peer
= pinfo
->peer
;
11880 /* Check source address. */
11881 sockunion2hostprefix(&peer
->su
, &q
);
11882 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11884 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11885 bgp_unlock_node(rn
);
11887 if (bdistance
->access_list
) {
11888 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11890 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11891 return bdistance
->distance
;
11893 return bdistance
->distance
;
11896 /* Backdoor check. */
11897 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11899 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11900 bgp_unlock_node(rn
);
11902 if (bgp_static
->backdoor
) {
11903 if (bgp
->distance_local
[afi
][safi
])
11904 return bgp
->distance_local
[afi
][safi
];
11906 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11910 if (peer
->sort
== BGP_PEER_EBGP
) {
11911 if (bgp
->distance_ebgp
[afi
][safi
])
11912 return bgp
->distance_ebgp
[afi
][safi
];
11913 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11915 if (bgp
->distance_ibgp
[afi
][safi
])
11916 return bgp
->distance_ibgp
[afi
][safi
];
11917 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11921 DEFUN (bgp_distance
,
11923 "distance bgp (1-255) (1-255) (1-255)",
11924 "Define an administrative distance\n"
11926 "Distance for routes external to the AS\n"
11927 "Distance for routes internal to the AS\n"
11928 "Distance for local routes\n")
11930 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11931 int idx_number
= 2;
11932 int idx_number_2
= 3;
11933 int idx_number_3
= 4;
11937 afi
= bgp_node_afi(vty
);
11938 safi
= bgp_node_safi(vty
);
11940 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11941 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11942 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11943 return CMD_SUCCESS
;
11946 DEFUN (no_bgp_distance
,
11947 no_bgp_distance_cmd
,
11948 "no distance bgp [(1-255) (1-255) (1-255)]",
11950 "Define an administrative distance\n"
11952 "Distance for routes external to the AS\n"
11953 "Distance for routes internal to the AS\n"
11954 "Distance for local routes\n")
11956 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11960 afi
= bgp_node_afi(vty
);
11961 safi
= bgp_node_safi(vty
);
11963 bgp
->distance_ebgp
[afi
][safi
] = 0;
11964 bgp
->distance_ibgp
[afi
][safi
] = 0;
11965 bgp
->distance_local
[afi
][safi
] = 0;
11966 return CMD_SUCCESS
;
11970 DEFUN (bgp_distance_source
,
11971 bgp_distance_source_cmd
,
11972 "distance (1-255) A.B.C.D/M",
11973 "Define an administrative distance\n"
11974 "Administrative distance\n"
11975 "IP source prefix\n")
11977 int idx_number
= 1;
11978 int idx_ipv4_prefixlen
= 2;
11979 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11980 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11981 return CMD_SUCCESS
;
11984 DEFUN (no_bgp_distance_source
,
11985 no_bgp_distance_source_cmd
,
11986 "no distance (1-255) A.B.C.D/M",
11988 "Define an administrative distance\n"
11989 "Administrative distance\n"
11990 "IP source prefix\n")
11992 int idx_number
= 2;
11993 int idx_ipv4_prefixlen
= 3;
11994 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11995 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11996 return CMD_SUCCESS
;
11999 DEFUN (bgp_distance_source_access_list
,
12000 bgp_distance_source_access_list_cmd
,
12001 "distance (1-255) A.B.C.D/M WORD",
12002 "Define an administrative distance\n"
12003 "Administrative distance\n"
12004 "IP source prefix\n"
12005 "Access list name\n")
12007 int idx_number
= 1;
12008 int idx_ipv4_prefixlen
= 2;
12010 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12011 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12012 return CMD_SUCCESS
;
12015 DEFUN (no_bgp_distance_source_access_list
,
12016 no_bgp_distance_source_access_list_cmd
,
12017 "no distance (1-255) A.B.C.D/M WORD",
12019 "Define an administrative distance\n"
12020 "Administrative distance\n"
12021 "IP source prefix\n"
12022 "Access list name\n")
12024 int idx_number
= 2;
12025 int idx_ipv4_prefixlen
= 3;
12027 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12028 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12029 return CMD_SUCCESS
;
12032 DEFUN (ipv6_bgp_distance_source
,
12033 ipv6_bgp_distance_source_cmd
,
12034 "distance (1-255) X:X::X:X/M",
12035 "Define an administrative distance\n"
12036 "Administrative distance\n"
12037 "IP source prefix\n")
12039 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12040 return CMD_SUCCESS
;
12043 DEFUN (no_ipv6_bgp_distance_source
,
12044 no_ipv6_bgp_distance_source_cmd
,
12045 "no distance (1-255) X:X::X:X/M",
12047 "Define an administrative distance\n"
12048 "Administrative distance\n"
12049 "IP source prefix\n")
12051 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12052 return CMD_SUCCESS
;
12055 DEFUN (ipv6_bgp_distance_source_access_list
,
12056 ipv6_bgp_distance_source_access_list_cmd
,
12057 "distance (1-255) X:X::X:X/M WORD",
12058 "Define an administrative distance\n"
12059 "Administrative distance\n"
12060 "IP source prefix\n"
12061 "Access list name\n")
12063 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12064 return CMD_SUCCESS
;
12067 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12068 no_ipv6_bgp_distance_source_access_list_cmd
,
12069 "no distance (1-255) X:X::X:X/M WORD",
12071 "Define an administrative distance\n"
12072 "Administrative distance\n"
12073 "IP source prefix\n"
12074 "Access list name\n")
12076 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12077 return CMD_SUCCESS
;
12080 DEFUN (bgp_damp_set
,
12082 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12083 "BGP Specific commands\n"
12084 "Enable route-flap dampening\n"
12085 "Half-life time for the penalty\n"
12086 "Value to start reusing a route\n"
12087 "Value to start suppressing a route\n"
12088 "Maximum duration to suppress a stable route\n")
12090 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12091 int idx_half_life
= 2;
12093 int idx_suppress
= 4;
12094 int idx_max_suppress
= 5;
12095 int half
= DEFAULT_HALF_LIFE
* 60;
12096 int reuse
= DEFAULT_REUSE
;
12097 int suppress
= DEFAULT_SUPPRESS
;
12098 int max
= 4 * half
;
12101 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12102 reuse
= atoi(argv
[idx_reuse
]->arg
);
12103 suppress
= atoi(argv
[idx_suppress
]->arg
);
12104 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12105 } else if (argc
== 3) {
12106 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12110 if (suppress
< reuse
) {
12112 "Suppress value cannot be less than reuse value \n");
12116 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12117 reuse
, suppress
, max
);
12120 DEFUN (bgp_damp_unset
,
12121 bgp_damp_unset_cmd
,
12122 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12124 "BGP Specific commands\n"
12125 "Enable route-flap dampening\n"
12126 "Half-life time for the penalty\n"
12127 "Value to start reusing a route\n"
12128 "Value to start suppressing a route\n"
12129 "Maximum duration to suppress a stable route\n")
12131 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12132 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12135 /* Display specified route of BGP table. */
12136 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12137 const char *ip_str
, afi_t afi
, safi_t safi
,
12138 struct prefix_rd
*prd
, int prefix_check
)
12141 struct prefix match
;
12142 struct bgp_node
*rn
;
12143 struct bgp_node
*rm
;
12144 struct bgp_path_info
*pi
;
12145 struct bgp_path_info
*pi_temp
;
12147 struct bgp_table
*table
;
12149 /* BGP structure lookup. */
12151 bgp
= bgp_lookup_by_name(view_name
);
12153 vty_out(vty
, "%% Can't find BGP instance %s\n",
12155 return CMD_WARNING
;
12158 bgp
= bgp_get_default();
12160 vty_out(vty
, "%% No BGP process is configured\n");
12161 return CMD_WARNING
;
12165 /* Check IP address argument. */
12166 ret
= str2prefix(ip_str
, &match
);
12168 vty_out(vty
, "%% address is malformed\n");
12169 return CMD_WARNING
;
12172 match
.family
= afi2family(afi
);
12174 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12175 || (safi
== SAFI_EVPN
)) {
12176 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12177 rn
= bgp_route_next(rn
)) {
12178 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12180 table
= bgp_node_get_bgp_table_info(rn
);
12183 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12187 || rm
->p
.prefixlen
== match
.prefixlen
) {
12188 pi
= bgp_node_get_bgp_path_info(rm
);
12190 if (pi
->extra
&& pi
->extra
->damp_info
) {
12191 pi_temp
= pi
->next
;
12192 bgp_damp_info_free(
12193 pi
->extra
->damp_info
,
12201 bgp_unlock_node(rm
);
12204 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12207 || rn
->p
.prefixlen
== match
.prefixlen
) {
12208 pi
= bgp_node_get_bgp_path_info(rn
);
12210 if (pi
->extra
&& pi
->extra
->damp_info
) {
12211 pi_temp
= pi
->next
;
12212 bgp_damp_info_free(
12213 pi
->extra
->damp_info
,
12221 bgp_unlock_node(rn
);
12225 return CMD_SUCCESS
;
12228 DEFUN (clear_ip_bgp_dampening
,
12229 clear_ip_bgp_dampening_cmd
,
12230 "clear ip bgp dampening",
12234 "Clear route flap dampening information\n")
12236 bgp_damp_info_clean();
12237 return CMD_SUCCESS
;
12240 DEFUN (clear_ip_bgp_dampening_prefix
,
12241 clear_ip_bgp_dampening_prefix_cmd
,
12242 "clear ip bgp dampening A.B.C.D/M",
12246 "Clear route flap dampening information\n"
12249 int idx_ipv4_prefixlen
= 4;
12250 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12251 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12254 DEFUN (clear_ip_bgp_dampening_address
,
12255 clear_ip_bgp_dampening_address_cmd
,
12256 "clear ip bgp dampening A.B.C.D",
12260 "Clear route flap dampening information\n"
12261 "Network to clear damping information\n")
12264 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12265 SAFI_UNICAST
, NULL
, 0);
12268 DEFUN (clear_ip_bgp_dampening_address_mask
,
12269 clear_ip_bgp_dampening_address_mask_cmd
,
12270 "clear ip bgp dampening A.B.C.D A.B.C.D",
12274 "Clear route flap dampening information\n"
12275 "Network to clear damping information\n"
12279 int idx_ipv4_2
= 5;
12281 char prefix_str
[BUFSIZ
];
12283 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12286 vty_out(vty
, "%% Inconsistent address and mask\n");
12287 return CMD_WARNING
;
12290 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12294 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12296 struct vty
*vty
= arg
;
12297 struct peer
*peer
= bucket
->data
;
12298 char buf
[SU_ADDRSTRLEN
];
12300 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12301 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12304 DEFUN (show_bgp_peerhash
,
12305 show_bgp_peerhash_cmd
,
12306 "show bgp peerhash",
12309 "Display information about the BGP peerhash\n")
12311 struct list
*instances
= bm
->bgp
;
12312 struct listnode
*node
;
12315 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12316 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12317 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12321 return CMD_SUCCESS
;
12324 /* also used for encap safi */
12325 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12326 afi_t afi
, safi_t safi
)
12328 struct bgp_node
*prn
;
12329 struct bgp_node
*rn
;
12330 struct bgp_table
*table
;
12332 struct prefix_rd
*prd
;
12333 struct bgp_static
*bgp_static
;
12334 mpls_label_t label
;
12335 char buf
[SU_ADDRSTRLEN
];
12336 char rdbuf
[RD_ADDRSTRLEN
];
12338 /* Network configuration. */
12339 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12340 prn
= bgp_route_next(prn
)) {
12341 table
= bgp_node_get_bgp_table_info(prn
);
12345 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12346 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12347 if (bgp_static
== NULL
)
12351 prd
= (struct prefix_rd
*)&prn
->p
;
12353 /* "network" configuration display. */
12354 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12355 label
= decode_label(&bgp_static
->label
);
12357 vty_out(vty
, " network %s/%d rd %s",
12358 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12360 p
->prefixlen
, rdbuf
);
12361 if (safi
== SAFI_MPLS_VPN
)
12362 vty_out(vty
, " label %u", label
);
12364 if (bgp_static
->rmap
.name
)
12365 vty_out(vty
, " route-map %s",
12366 bgp_static
->rmap
.name
);
12368 if (bgp_static
->backdoor
)
12369 vty_out(vty
, " backdoor");
12371 vty_out(vty
, "\n");
12376 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12377 afi_t afi
, safi_t safi
)
12379 struct bgp_node
*prn
;
12380 struct bgp_node
*rn
;
12381 struct bgp_table
*table
;
12383 struct prefix_rd
*prd
;
12384 struct bgp_static
*bgp_static
;
12385 char buf
[PREFIX_STRLEN
* 2];
12386 char buf2
[SU_ADDRSTRLEN
];
12387 char rdbuf
[RD_ADDRSTRLEN
];
12389 /* Network configuration. */
12390 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12391 prn
= bgp_route_next(prn
)) {
12392 table
= bgp_node_get_bgp_table_info(prn
);
12396 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12397 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12398 if (bgp_static
== NULL
)
12401 char *macrouter
= NULL
;
12404 if (bgp_static
->router_mac
)
12405 macrouter
= prefix_mac2str(
12406 bgp_static
->router_mac
, NULL
, 0);
12407 if (bgp_static
->eth_s_id
)
12408 esi
= esi2str(bgp_static
->eth_s_id
);
12410 prd
= (struct prefix_rd
*)&prn
->p
;
12412 /* "network" configuration display. */
12413 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12414 if (p
->u
.prefix_evpn
.route_type
== 5) {
12415 char local_buf
[PREFIX_STRLEN
];
12416 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12417 struct prefix_evpn
*)p
)
12421 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12422 local_buf
, PREFIX_STRLEN
);
12423 sprintf(buf
, "%s/%u", local_buf
,
12424 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12426 prefix2str(p
, buf
, sizeof(buf
));
12429 if (bgp_static
->gatewayIp
.family
== AF_INET
12430 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12431 inet_ntop(bgp_static
->gatewayIp
.family
,
12432 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12435 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12437 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12438 decode_label(&bgp_static
->label
), esi
, buf2
,
12441 XFREE(MTYPE_TMP
, macrouter
);
12442 XFREE(MTYPE_TMP
, esi
);
12447 /* Configuration of static route announcement and aggregate
12449 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12452 struct bgp_node
*rn
;
12454 struct bgp_static
*bgp_static
;
12455 struct bgp_aggregate
*bgp_aggregate
;
12456 char buf
[SU_ADDRSTRLEN
];
12458 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12459 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12463 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12464 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12468 /* Network configuration. */
12469 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12470 rn
= bgp_route_next(rn
)) {
12471 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12472 if (bgp_static
== NULL
)
12477 vty_out(vty
, " network %s/%d",
12478 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12481 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12482 vty_out(vty
, " label-index %u",
12483 bgp_static
->label_index
);
12485 if (bgp_static
->rmap
.name
)
12486 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12488 if (bgp_static
->backdoor
)
12489 vty_out(vty
, " backdoor");
12491 vty_out(vty
, "\n");
12494 /* Aggregate-address configuration. */
12495 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12496 rn
= bgp_route_next(rn
)) {
12497 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12498 if (bgp_aggregate
== NULL
)
12503 vty_out(vty
, " aggregate-address %s/%d",
12504 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12507 if (bgp_aggregate
->as_set
)
12508 vty_out(vty
, " as-set");
12510 if (bgp_aggregate
->summary_only
)
12511 vty_out(vty
, " summary-only");
12513 if (bgp_aggregate
->rmap
.name
)
12514 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12516 vty_out(vty
, "\n");
12520 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12523 struct bgp_node
*rn
;
12524 struct bgp_distance
*bdistance
;
12526 /* Distance configuration. */
12527 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12528 && bgp
->distance_local
[afi
][safi
]
12529 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12530 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12531 || bgp
->distance_local
[afi
][safi
]
12532 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12533 vty_out(vty
, " distance bgp %d %d %d\n",
12534 bgp
->distance_ebgp
[afi
][safi
],
12535 bgp
->distance_ibgp
[afi
][safi
],
12536 bgp
->distance_local
[afi
][safi
]);
12539 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12540 rn
= bgp_route_next(rn
)) {
12541 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12542 if (bdistance
!= NULL
) {
12543 char buf
[PREFIX_STRLEN
];
12545 vty_out(vty
, " distance %d %s %s\n",
12546 bdistance
->distance
,
12547 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12548 bdistance
->access_list
? bdistance
->access_list
12554 /* Allocate routing table structure and install commands. */
12555 void bgp_route_init(void)
12560 /* Init BGP distance table. */
12561 FOREACH_AFI_SAFI (afi
, safi
)
12562 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12564 /* IPv4 BGP commands. */
12565 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12566 install_element(BGP_NODE
, &bgp_network_cmd
);
12567 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12569 install_element(BGP_NODE
, &aggregate_address_cmd
);
12570 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12571 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12572 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12574 /* IPv4 unicast configuration. */
12575 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12576 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12577 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12579 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12580 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12581 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12582 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12584 /* IPv4 multicast configuration. */
12585 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12586 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12587 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12588 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12589 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12590 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12591 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12593 /* IPv4 labeled-unicast configuration. */
12594 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12595 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12596 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12597 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12598 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12600 install_element(VIEW_NODE
,
12601 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12602 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12603 install_element(VIEW_NODE
,
12604 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12605 #ifdef KEEP_OLD_VPN_COMMANDS
12606 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12607 #endif /* KEEP_OLD_VPN_COMMANDS */
12608 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12609 install_element(VIEW_NODE
,
12610 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
12612 /* BGP dampening clear commands */
12613 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12614 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12616 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12617 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12620 install_element(ENABLE_NODE
,
12621 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12622 #ifdef KEEP_OLD_VPN_COMMANDS
12623 install_element(ENABLE_NODE
,
12624 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12625 #endif /* KEEP_OLD_VPN_COMMANDS */
12627 /* New config IPv6 BGP commands. */
12628 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12629 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12630 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12632 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12633 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12635 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12637 install_element(BGP_NODE
, &bgp_distance_cmd
);
12638 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12639 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12640 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12641 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12642 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12643 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12644 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12645 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12646 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12647 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12648 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12649 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12650 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12651 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12652 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12653 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12654 install_element(BGP_IPV4M_NODE
,
12655 &no_bgp_distance_source_access_list_cmd
);
12656 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12657 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12658 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12659 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12660 install_element(BGP_IPV6_NODE
,
12661 &ipv6_bgp_distance_source_access_list_cmd
);
12662 install_element(BGP_IPV6_NODE
,
12663 &no_ipv6_bgp_distance_source_access_list_cmd
);
12664 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12665 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12666 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12667 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12668 install_element(BGP_IPV6M_NODE
,
12669 &ipv6_bgp_distance_source_access_list_cmd
);
12670 install_element(BGP_IPV6M_NODE
,
12671 &no_ipv6_bgp_distance_source_access_list_cmd
);
12673 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12674 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12675 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12676 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12678 /* IPv4 Multicast Mode */
12679 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12680 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12682 /* Large Communities */
12683 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12684 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12686 /* show bgp ipv4 flowspec detailed */
12687 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12689 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12692 void bgp_route_finish(void)
12697 FOREACH_AFI_SAFI (afi
, safi
) {
12698 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12699 bgp_distance_table
[afi
][safi
] = NULL
;