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
34 #include "sockunion.h"
37 #include "workqueue.h"
41 #include "lib_errors.h"
43 #include "bgpd/bgpd.h"
44 #include "bgpd/bgp_table.h"
45 #include "bgpd/bgp_route.h"
46 #include "bgpd/bgp_attr.h"
47 #include "bgpd/bgp_debug.h"
48 #include "bgpd/bgp_errors.h"
49 #include "bgpd/bgp_aspath.h"
50 #include "bgpd/bgp_regex.h"
51 #include "bgpd/bgp_community.h"
52 #include "bgpd/bgp_ecommunity.h"
53 #include "bgpd/bgp_lcommunity.h"
54 #include "bgpd/bgp_clist.h"
55 #include "bgpd/bgp_packet.h"
56 #include "bgpd/bgp_filter.h"
57 #include "bgpd/bgp_fsm.h"
58 #include "bgpd/bgp_mplsvpn.h"
59 #include "bgpd/bgp_nexthop.h"
60 #include "bgpd/bgp_damp.h"
61 #include "bgpd/bgp_advertise.h"
62 #include "bgpd/bgp_zebra.h"
63 #include "bgpd/bgp_vty.h"
64 #include "bgpd/bgp_mpath.h"
65 #include "bgpd/bgp_nht.h"
66 #include "bgpd/bgp_updgrp.h"
67 #include "bgpd/bgp_label.h"
68 #include "bgpd/bgp_addpath.h"
71 #include "bgpd/rfapi/rfapi_backend.h"
72 #include "bgpd/rfapi/vnc_import_bgp.h"
73 #include "bgpd/rfapi/vnc_export_bgp.h"
75 #include "bgpd/bgp_encap_types.h"
76 #include "bgpd/bgp_encap_tlv.h"
77 #include "bgpd/bgp_evpn.h"
78 #include "bgpd/bgp_evpn_vty.h"
79 #include "bgpd/bgp_flowspec.h"
80 #include "bgpd/bgp_flowspec_util.h"
81 #include "bgpd/bgp_pbr.h"
83 #ifndef VTYSH_EXTRACT_PL
84 #include "bgpd/bgp_route_clippy.c"
87 /* Extern from bgp_dump.c */
88 extern const char *bgp_origin_str
[];
89 extern const char *bgp_origin_long_str
[];
92 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
93 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
94 static const struct message bgp_pmsi_tnltype_str
[] = {
95 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
96 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
97 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
98 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
99 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
100 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
101 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
102 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
106 #define VRFID_NONE_STR "-"
108 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
109 safi_t safi
, struct prefix
*p
,
110 struct prefix_rd
*prd
)
113 struct bgp_node
*prn
= NULL
;
119 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
120 || (safi
== SAFI_EVPN
)) {
121 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
123 if (!bgp_node_has_bgp_path_info_data(prn
))
124 bgp_node_set_bgp_table_info(
125 prn
, bgp_table_init(table
->bgp
, afi
, safi
));
127 bgp_unlock_node(prn
);
128 table
= bgp_node_get_bgp_table_info(prn
);
131 rn
= bgp_node_get(table
, p
);
133 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
134 || (safi
== SAFI_EVPN
))
140 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
141 safi_t safi
, struct prefix
*p
,
142 struct prefix_rd
*prd
)
145 struct bgp_node
*prn
= NULL
;
150 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
151 || (safi
== SAFI_EVPN
)) {
152 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
156 if (!bgp_node_has_bgp_path_info_data(prn
)) {
157 bgp_unlock_node(prn
);
161 table
= bgp_node_get_bgp_table_info(prn
);
164 rn
= bgp_node_lookup(table
, p
);
169 /* Allocate bgp_path_info_extra */
170 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
172 struct bgp_path_info_extra
*new;
173 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
174 sizeof(struct bgp_path_info_extra
));
175 new->label
[0] = MPLS_INVALID_LABEL
;
180 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
182 struct bgp_path_info_extra
*e
;
184 if (!extra
|| !*extra
)
189 bgp_damp_info_free(e
->damp_info
, 0);
193 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
196 /* FIXME: since multiple e may have the same e->parent
197 * and e->parent->net is holding a refcount for each
198 * of them, we need to do some fudging here.
200 * WARNING: if bpi->net->lock drops to 0, bpi may be
201 * freed as well (because bpi->net was holding the
202 * last reference to bpi) => write after free!
206 bpi
= bgp_path_info_lock(bpi
);
207 refcount
= bpi
->net
->lock
- 1;
208 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
211 bgp_path_info_unlock(bpi
);
213 bgp_path_info_unlock(e
->parent
);
218 bgp_unlock(e
->bgp_orig
);
220 if ((*extra
)->bgp_fs_pbr
)
221 list_delete(&((*extra
)->bgp_fs_pbr
));
222 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
227 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
228 * allocated if required.
230 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
233 pi
->extra
= bgp_path_info_extra_new();
237 /* Allocate new bgp info structure. */
238 struct bgp_path_info
*bgp_path_info_new(void)
240 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
243 /* Free bgp route information. */
244 static void bgp_path_info_free(struct bgp_path_info
*path
)
247 bgp_attr_unintern(&path
->attr
);
249 bgp_unlink_nexthop(path
);
250 bgp_path_info_extra_free(&path
->extra
);
251 bgp_path_info_mpath_free(&path
->mpath
);
252 bgp_addpath_free_info_data(&path
->tx_addpath
,
253 path
->net
? &path
->net
->tx_addpath
: NULL
);
255 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
257 XFREE(MTYPE_BGP_ROUTE
, path
);
260 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
266 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
268 assert(path
&& path
->lock
> 0);
271 if (path
->lock
== 0) {
273 zlog_debug ("%s: unlocked and freeing", __func__
);
274 zlog_backtrace (LOG_DEBUG
);
276 bgp_path_info_free(path
);
283 zlog_debug ("%s: unlocked to 1", __func__
);
284 zlog_backtrace (LOG_DEBUG
);
291 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
293 struct bgp_path_info
*top
;
295 top
= bgp_node_get_bgp_path_info(rn
);
301 bgp_node_set_bgp_path_info(rn
, pi
);
303 bgp_path_info_lock(pi
);
305 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
308 /* Do the actual removal of info from RIB, for use by bgp_process
309 completion callback *only* */
310 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
313 pi
->next
->prev
= pi
->prev
;
315 pi
->prev
->next
= pi
->next
;
317 bgp_node_set_bgp_path_info(rn
, pi
->next
);
319 bgp_path_info_mpath_dequeue(pi
);
320 bgp_path_info_unlock(pi
);
324 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
326 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
327 /* set of previous already took care of pcount */
328 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
331 /* undo the effects of a previous call to bgp_path_info_delete; typically
332 called when a route is deleted and then quickly re-added before the
333 deletion has been processed */
334 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
336 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
337 /* unset of previous already took care of pcount */
338 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
341 /* Adjust pcount as required */
342 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
344 struct bgp_table
*table
;
346 assert(rn
&& bgp_node_table(rn
));
347 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
349 table
= bgp_node_table(rn
);
351 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
354 if (!BGP_PATH_COUNTABLE(pi
)
355 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
357 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
359 /* slight hack, but more robust against errors. */
360 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
361 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
363 flog_err(EC_LIB_DEVELOPMENT
,
364 "Asked to decrement 0 prefix count for peer");
365 } else if (BGP_PATH_COUNTABLE(pi
)
366 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
367 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
368 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
372 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
373 struct bgp_path_info
*pi2
)
375 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
378 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
379 * This is here primarily to keep prefix-count in check.
381 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
384 SET_FLAG(pi
->flags
, flag
);
386 /* early bath if we know it's not a flag that changes countability state
388 if (!CHECK_FLAG(flag
,
389 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
392 bgp_pcount_adjust(rn
, pi
);
395 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
398 UNSET_FLAG(pi
->flags
, flag
);
400 /* early bath if we know it's not a flag that changes countability state
402 if (!CHECK_FLAG(flag
,
403 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
406 bgp_pcount_adjust(rn
, pi
);
409 /* Get MED value. If MED value is missing and "bgp bestpath
410 missing-as-worst" is specified, treat it as the worst value. */
411 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
413 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
416 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
423 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
425 if (pi
->addpath_rx_id
)
426 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
429 sprintf(buf
, "path %s", pi
->peer
->host
);
432 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
434 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
435 struct bgp_path_info
*exist
, int *paths_eq
,
436 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
437 char *pfx_buf
, afi_t afi
, safi_t safi
)
439 struct attr
*newattr
, *existattr
;
440 bgp_peer_sort_t new_sort
;
441 bgp_peer_sort_t exist_sort
;
447 uint32_t exist_weight
;
448 uint32_t newm
, existm
;
449 struct in_addr new_id
;
450 struct in_addr exist_id
;
453 int internal_as_route
;
456 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
457 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
459 uint32_t exist_mm_seq
;
467 zlog_debug("%s: new is NULL", pfx_buf
);
472 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
476 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
482 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
483 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
484 pfx_buf
, new_buf
, new->flags
, exist_buf
,
489 existattr
= exist
->attr
;
491 /* For EVPN routes, we cannot just go by local vs remote, we have to
492 * look at the MAC mobility sequence number, if present.
494 if (safi
== SAFI_EVPN
) {
495 /* This is an error condition described in RFC 7432 Section
497 * states that in this scenario "the PE MUST alert the operator"
499 * does not state what other action to take. In order to provide
501 * consistency in this scenario we are going to prefer the path
505 if (newattr
->sticky
!= existattr
->sticky
) {
507 prefix2str(&new->net
->p
, pfx_buf
,
509 * PREFIX2STR_BUFFER
);
510 bgp_path_info_path_with_addpath_rx_str(new,
512 bgp_path_info_path_with_addpath_rx_str(
516 if (newattr
->sticky
&& !existattr
->sticky
) {
519 "%s: %s wins over %s due to sticky MAC flag",
520 pfx_buf
, new_buf
, exist_buf
);
524 if (!newattr
->sticky
&& existattr
->sticky
) {
527 "%s: %s loses to %s due to sticky MAC flag",
528 pfx_buf
, new_buf
, exist_buf
);
533 new_mm_seq
= mac_mobility_seqnum(newattr
);
534 exist_mm_seq
= mac_mobility_seqnum(existattr
);
536 if (new_mm_seq
> exist_mm_seq
) {
539 "%s: %s wins over %s due to MM seq %u > %u",
540 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
545 if (new_mm_seq
< exist_mm_seq
) {
548 "%s: %s loses to %s due to MM seq %u < %u",
549 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
555 * if sequence numbers are the same path with the lowest IP
558 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
562 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
563 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
564 inet_ntoa(new->attr
->nexthop
));
570 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
571 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
572 inet_ntoa(new->attr
->nexthop
));
577 /* 1. Weight check. */
578 new_weight
= newattr
->weight
;
579 exist_weight
= existattr
->weight
;
581 if (new_weight
> exist_weight
) {
583 zlog_debug("%s: %s wins over %s due to weight %d > %d",
584 pfx_buf
, new_buf
, exist_buf
, new_weight
,
589 if (new_weight
< exist_weight
) {
591 zlog_debug("%s: %s loses to %s due to weight %d < %d",
592 pfx_buf
, new_buf
, exist_buf
, new_weight
,
597 /* 2. Local preference check. */
598 new_pref
= exist_pref
= bgp
->default_local_pref
;
600 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
601 new_pref
= newattr
->local_pref
;
602 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
603 exist_pref
= existattr
->local_pref
;
605 if (new_pref
> exist_pref
) {
608 "%s: %s wins over %s due to localpref %d > %d",
609 pfx_buf
, new_buf
, exist_buf
, new_pref
,
614 if (new_pref
< exist_pref
) {
617 "%s: %s loses to %s due to localpref %d < %d",
618 pfx_buf
, new_buf
, exist_buf
, new_pref
,
623 /* 3. Local route check. We prefer:
625 * - BGP_ROUTE_AGGREGATE
626 * - BGP_ROUTE_REDISTRIBUTE
628 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
629 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
632 "%s: %s wins over %s due to preferred BGP_ROUTE type",
633 pfx_buf
, new_buf
, exist_buf
);
637 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
638 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
641 "%s: %s loses to %s due to preferred BGP_ROUTE type",
642 pfx_buf
, new_buf
, exist_buf
);
646 /* 4. AS path length check. */
647 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
648 int exist_hops
= aspath_count_hops(existattr
->aspath
);
649 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
651 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
654 aspath_hops
= aspath_count_hops(newattr
->aspath
);
655 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
657 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
660 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
661 pfx_buf
, new_buf
, exist_buf
,
663 (exist_hops
+ exist_confeds
));
667 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
670 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
671 pfx_buf
, new_buf
, exist_buf
,
673 (exist_hops
+ exist_confeds
));
677 int newhops
= aspath_count_hops(newattr
->aspath
);
679 if (newhops
< exist_hops
) {
682 "%s: %s wins over %s due to aspath hopcount %d < %d",
683 pfx_buf
, new_buf
, exist_buf
,
684 newhops
, exist_hops
);
688 if (newhops
> exist_hops
) {
691 "%s: %s loses to %s due to aspath hopcount %d > %d",
692 pfx_buf
, new_buf
, exist_buf
,
693 newhops
, exist_hops
);
699 /* 5. Origin check. */
700 if (newattr
->origin
< existattr
->origin
) {
702 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
703 pfx_buf
, new_buf
, exist_buf
,
704 bgp_origin_long_str
[newattr
->origin
],
705 bgp_origin_long_str
[existattr
->origin
]);
709 if (newattr
->origin
> existattr
->origin
) {
711 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
712 pfx_buf
, new_buf
, exist_buf
,
713 bgp_origin_long_str
[newattr
->origin
],
714 bgp_origin_long_str
[existattr
->origin
]);
719 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
720 && aspath_count_hops(existattr
->aspath
) == 0);
721 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
722 && aspath_count_confeds(existattr
->aspath
) > 0
723 && aspath_count_hops(newattr
->aspath
) == 0
724 && aspath_count_hops(existattr
->aspath
) == 0);
726 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
727 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
728 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
729 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
730 || internal_as_route
) {
731 new_med
= bgp_med_value(new->attr
, bgp
);
732 exist_med
= bgp_med_value(exist
->attr
, bgp
);
734 if (new_med
< exist_med
) {
737 "%s: %s wins over %s due to MED %d < %d",
738 pfx_buf
, new_buf
, exist_buf
, new_med
,
743 if (new_med
> exist_med
) {
746 "%s: %s loses to %s due to MED %d > %d",
747 pfx_buf
, new_buf
, exist_buf
, new_med
,
753 /* 7. Peer type check. */
754 new_sort
= new->peer
->sort
;
755 exist_sort
= exist
->peer
->sort
;
757 if (new_sort
== BGP_PEER_EBGP
758 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
761 "%s: %s wins over %s due to eBGP peer > iBGP peer",
762 pfx_buf
, new_buf
, exist_buf
);
766 if (exist_sort
== BGP_PEER_EBGP
767 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
770 "%s: %s loses to %s due to iBGP peer < eBGP peer",
771 pfx_buf
, new_buf
, exist_buf
);
775 /* 8. IGP metric check. */
779 newm
= new->extra
->igpmetric
;
781 existm
= exist
->extra
->igpmetric
;
786 "%s: %s wins over %s due to IGP metric %d < %d",
787 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
794 "%s: %s loses to %s due to IGP metric %d > %d",
795 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
799 /* 9. Same IGP metric. Compare the cluster list length as
800 representative of IGP hops metric. Rewrite the metric value
801 pair (newm, existm) with the cluster list length. Prefer the
802 path with smaller cluster list length. */
803 if (newm
== existm
) {
804 if (peer_sort(new->peer
) == BGP_PEER_IBGP
805 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
806 && (mpath_cfg
== NULL
808 mpath_cfg
->ibgp_flags
,
809 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
810 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
811 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
816 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
817 pfx_buf
, new_buf
, exist_buf
,
825 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
826 pfx_buf
, new_buf
, exist_buf
,
833 /* 10. confed-external vs. confed-internal */
834 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
835 if (new_sort
== BGP_PEER_CONFED
836 && exist_sort
== BGP_PEER_IBGP
) {
839 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
840 pfx_buf
, new_buf
, exist_buf
);
844 if (exist_sort
== BGP_PEER_CONFED
845 && new_sort
== BGP_PEER_IBGP
) {
848 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
849 pfx_buf
, new_buf
, exist_buf
);
854 /* 11. Maximum path check. */
855 if (newm
== existm
) {
856 /* If one path has a label but the other does not, do not treat
857 * them as equals for multipath
859 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
861 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
864 "%s: %s and %s cannot be multipath, one has a label while the other does not",
865 pfx_buf
, new_buf
, exist_buf
);
866 } else if (bgp_flag_check(bgp
,
867 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
870 * For the two paths, all comparison steps till IGP
872 * have succeeded - including AS_PATH hop count. Since
874 * bestpath as-path multipath-relax' knob is on, we
876 * an exact match of AS_PATH. Thus, mark the paths are
878 * That will trigger both these paths to get into the
886 "%s: %s and %s are equal via multipath-relax",
887 pfx_buf
, new_buf
, exist_buf
);
888 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
889 if (aspath_cmp(new->attr
->aspath
,
890 exist
->attr
->aspath
)) {
895 "%s: %s and %s are equal via matching aspaths",
896 pfx_buf
, new_buf
, exist_buf
);
898 } else if (new->peer
->as
== exist
->peer
->as
) {
903 "%s: %s and %s are equal via same remote-as",
904 pfx_buf
, new_buf
, exist_buf
);
908 * TODO: If unequal cost ibgp multipath is enabled we can
909 * mark the paths as equal here instead of returning
914 "%s: %s wins over %s after IGP metric comparison",
915 pfx_buf
, new_buf
, exist_buf
);
918 "%s: %s loses to %s after IGP metric comparison",
919 pfx_buf
, new_buf
, exist_buf
);
924 /* 12. If both paths are external, prefer the path that was received
925 first (the oldest one). This step minimizes route-flap, since a
926 newer path won't displace an older one, even if it was the
927 preferred route based on the additional decision criteria below. */
928 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
929 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
930 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
933 "%s: %s wins over %s due to oldest external",
934 pfx_buf
, new_buf
, exist_buf
);
938 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
941 "%s: %s loses to %s due to oldest external",
942 pfx_buf
, new_buf
, exist_buf
);
947 /* 13. Router-ID comparision. */
948 /* If one of the paths is "stale", the corresponding peer router-id will
949 * be 0 and would always win over the other path. If originator id is
950 * used for the comparision, it will decide which path is better.
952 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
953 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
955 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
956 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
957 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
959 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
961 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
964 "%s: %s wins over %s due to Router-ID comparison",
965 pfx_buf
, new_buf
, exist_buf
);
969 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
972 "%s: %s loses to %s due to Router-ID comparison",
973 pfx_buf
, new_buf
, exist_buf
);
977 /* 14. Cluster length comparision. */
978 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
979 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
981 if (new_cluster
< exist_cluster
) {
984 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
985 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
990 if (new_cluster
> exist_cluster
) {
993 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
994 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
999 /* 15. Neighbor address comparision. */
1000 /* Do this only if neither path is "stale" as stale paths do not have
1001 * valid peer information (as the connection may or may not be up).
1003 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1006 "%s: %s wins over %s due to latter path being STALE",
1007 pfx_buf
, new_buf
, exist_buf
);
1011 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1014 "%s: %s loses to %s due to former path being STALE",
1015 pfx_buf
, new_buf
, exist_buf
);
1019 /* locally configured routes to advertise do not have su_remote */
1020 if (new->peer
->su_remote
== NULL
)
1022 if (exist
->peer
->su_remote
== NULL
)
1025 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1030 "%s: %s loses to %s due to Neighor IP comparison",
1031 pfx_buf
, new_buf
, exist_buf
);
1038 "%s: %s wins over %s due to Neighor IP comparison",
1039 pfx_buf
, new_buf
, exist_buf
);
1044 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1045 pfx_buf
, new_buf
, exist_buf
);
1050 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1051 * is preferred, or 0 if they are the same (usually will only occur if
1052 * multipath is enabled
1053 * This version is compatible with */
1054 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1055 struct bgp_path_info
*exist
, char *pfx_buf
,
1056 afi_t afi
, safi_t safi
)
1060 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1074 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1075 struct attr
*attr
, afi_t afi
,
1078 struct bgp_filter
*filter
;
1080 filter
= &peer
->filter
[afi
][safi
];
1082 #define FILTER_EXIST_WARN(F, f, filter) \
1083 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1084 zlog_debug("%s: Could not find configured input %s-list %s!", \
1085 peer->host, #f, F##_IN_NAME(filter));
1087 if (DISTRIBUTE_IN_NAME(filter
)) {
1088 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1090 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1094 if (PREFIX_LIST_IN_NAME(filter
)) {
1095 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1097 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1101 if (FILTER_LIST_IN_NAME(filter
)) {
1102 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1104 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1109 return FILTER_PERMIT
;
1110 #undef FILTER_EXIST_WARN
1113 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1114 struct attr
*attr
, afi_t afi
,
1117 struct bgp_filter
*filter
;
1119 filter
= &peer
->filter
[afi
][safi
];
1121 #define FILTER_EXIST_WARN(F, f, filter) \
1122 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1123 zlog_debug("%s: Could not find configured output %s-list %s!", \
1124 peer->host, #f, F##_OUT_NAME(filter));
1126 if (DISTRIBUTE_OUT_NAME(filter
)) {
1127 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1129 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1133 if (PREFIX_LIST_OUT_NAME(filter
)) {
1134 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1136 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1141 if (FILTER_LIST_OUT_NAME(filter
)) {
1142 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1144 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1149 return FILTER_PERMIT
;
1150 #undef FILTER_EXIST_WARN
1153 /* If community attribute includes no_export then return 1. */
1154 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1156 if (attr
->community
) {
1157 /* NO_ADVERTISE check. */
1158 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1161 /* NO_EXPORT check. */
1162 if (peer
->sort
== BGP_PEER_EBGP
1163 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1166 /* NO_EXPORT_SUBCONFED check. */
1167 if (peer
->sort
== BGP_PEER_EBGP
1168 || peer
->sort
== BGP_PEER_CONFED
)
1169 if (community_include(attr
->community
,
1170 COMMUNITY_NO_EXPORT_SUBCONFED
))
1176 /* Route reflection loop check. */
1177 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1179 struct in_addr cluster_id
;
1181 if (attr
->cluster
) {
1182 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1183 cluster_id
= peer
->bgp
->cluster_id
;
1185 cluster_id
= peer
->bgp
->router_id
;
1187 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1193 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1194 struct attr
*attr
, afi_t afi
, safi_t safi
,
1195 const char *rmap_name
)
1197 struct bgp_filter
*filter
;
1198 struct bgp_path_info rmap_path
;
1199 route_map_result_t ret
;
1200 struct route_map
*rmap
= NULL
;
1202 filter
= &peer
->filter
[afi
][safi
];
1204 /* Apply default weight value. */
1205 if (peer
->weight
[afi
][safi
])
1206 attr
->weight
= peer
->weight
[afi
][safi
];
1209 rmap
= route_map_lookup_by_name(rmap_name
);
1214 if (ROUTE_MAP_IN_NAME(filter
)) {
1215 rmap
= ROUTE_MAP_IN(filter
);
1222 /* Route map apply. */
1224 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1225 /* Duplicate current value to new strucutre for modification. */
1226 rmap_path
.peer
= peer
;
1227 rmap_path
.attr
= attr
;
1229 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1231 /* Apply BGP route map to the attribute. */
1232 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1234 peer
->rmap_type
= 0;
1236 if (ret
== RMAP_DENYMATCH
)
1242 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1243 struct attr
*attr
, afi_t afi
, safi_t safi
,
1244 const char *rmap_name
)
1246 struct bgp_path_info rmap_path
;
1247 route_map_result_t ret
;
1248 struct route_map
*rmap
= NULL
;
1252 * So if we get to this point and have no rmap_name
1253 * we want to just show the output as it currently
1259 /* Apply default weight value. */
1260 if (peer
->weight
[afi
][safi
])
1261 attr
->weight
= peer
->weight
[afi
][safi
];
1263 rmap
= route_map_lookup_by_name(rmap_name
);
1266 * If we have a route map name and we do not find
1267 * the routemap that means we have an implicit
1273 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1274 /* Route map apply. */
1275 /* Duplicate current value to new strucutre for modification. */
1276 rmap_path
.peer
= peer
;
1277 rmap_path
.attr
= attr
;
1279 rmap_type
= peer
->rmap_type
;
1280 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1282 /* Apply BGP route map to the attribute. */
1283 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1285 peer
->rmap_type
= rmap_type
;
1287 if (ret
== RMAP_DENYMATCH
)
1289 * caller has multiple error paths with bgp_attr_flush()
1296 /* If this is an EBGP peer with remove-private-AS */
1297 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1298 struct peer
*peer
, struct attr
*attr
)
1300 if (peer
->sort
== BGP_PEER_EBGP
1301 && (peer_af_flag_check(peer
, afi
, safi
,
1302 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1303 || peer_af_flag_check(peer
, afi
, safi
,
1304 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1305 || peer_af_flag_check(peer
, afi
, safi
,
1306 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1307 || peer_af_flag_check(peer
, afi
, safi
,
1308 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1309 // Take action on the entire aspath
1310 if (peer_af_flag_check(peer
, afi
, safi
,
1311 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1312 || peer_af_flag_check(peer
, afi
, safi
,
1313 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1314 if (peer_af_flag_check(
1316 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1317 attr
->aspath
= aspath_replace_private_asns(
1318 attr
->aspath
, bgp
->as
);
1320 // The entire aspath consists of private ASNs so create
1322 else if (aspath_private_as_check(attr
->aspath
))
1323 attr
->aspath
= aspath_empty_get();
1325 // There are some public and some private ASNs, remove
1328 attr
->aspath
= aspath_remove_private_asns(
1332 // 'all' was not specified so the entire aspath must be private
1334 // for us to do anything
1335 else if (aspath_private_as_check(attr
->aspath
)) {
1336 if (peer_af_flag_check(
1338 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1339 attr
->aspath
= aspath_replace_private_asns(
1340 attr
->aspath
, bgp
->as
);
1342 attr
->aspath
= aspath_empty_get();
1347 /* If this is an EBGP peer with as-override */
1348 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1349 struct peer
*peer
, struct attr
*attr
)
1351 if (peer
->sort
== BGP_PEER_EBGP
1352 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1353 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1354 attr
->aspath
= aspath_replace_specific_asn(
1355 attr
->aspath
, peer
->as
, bgp
->as
);
1359 void bgp_attr_add_gshut_community(struct attr
*attr
)
1361 struct community
*old
;
1362 struct community
*new;
1363 struct community
*merge
;
1364 struct community
*gshut
;
1366 old
= attr
->community
;
1367 gshut
= community_str2com("graceful-shutdown");
1372 merge
= community_merge(community_dup(old
), gshut
);
1374 if (old
->refcnt
== 0)
1375 community_free(&old
);
1377 new = community_uniq_sort(merge
);
1378 community_free(&merge
);
1380 new = community_dup(gshut
);
1383 community_free(&gshut
);
1384 attr
->community
= new;
1385 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1387 /* When we add the graceful-shutdown community we must also
1388 * lower the local-preference */
1389 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1390 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1394 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1396 if (family
== AF_INET
) {
1397 attr
->nexthop
.s_addr
= 0;
1398 attr
->mp_nexthop_global_in
.s_addr
= 0;
1400 if (family
== AF_INET6
)
1401 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1402 if (family
== AF_EVPN
)
1403 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1406 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1407 struct update_subgroup
*subgrp
, struct prefix
*p
,
1410 struct bgp_filter
*filter
;
1413 struct peer
*onlypeer
;
1415 struct attr
*piattr
;
1416 char buf
[PREFIX_STRLEN
];
1422 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1424 if (DISABLE_BGP_ANNOUNCE
)
1427 afi
= SUBGRP_AFI(subgrp
);
1428 safi
= SUBGRP_SAFI(subgrp
);
1429 peer
= SUBGRP_PEER(subgrp
);
1431 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1432 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1435 filter
= &peer
->filter
[afi
][safi
];
1436 bgp
= SUBGRP_INST(subgrp
);
1437 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1441 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1442 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1443 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1446 * direct and direct_ext type routes originate internally even
1447 * though they can have peer pointers that reference other
1450 prefix2str(p
, buf
, PREFIX_STRLEN
);
1451 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1457 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1458 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1459 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1460 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1462 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1467 /* With addpath we may be asked to TX all kinds of paths so make sure
1469 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1470 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1471 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1475 /* If this is not the bestpath then check to see if there is an enabled
1477 * feature that requires us to advertise it */
1478 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1479 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1484 /* Aggregate-address suppress check. */
1485 if (pi
->extra
&& pi
->extra
->suppress
)
1486 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1491 * If we are doing VRF 2 VRF leaking via the import
1492 * statement, we want to prevent the route going
1493 * off box as that the RT and RD created are localy
1494 * significant and globaly useless.
1496 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1497 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1500 /* If it's labeled safi, make sure the route has a valid label. */
1501 if (safi
== SAFI_LABELED_UNICAST
) {
1502 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1503 if (!bgp_is_valid_label(&label
)) {
1504 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1505 zlog_debug("u%" PRIu64
":s%" PRIu64
1506 " %s/%d is filtered - no label (%p)",
1507 subgrp
->update_group
->id
, subgrp
->id
,
1508 inet_ntop(p
->family
, &p
->u
.prefix
,
1509 buf
, SU_ADDRSTRLEN
),
1510 p
->prefixlen
, &label
);
1515 /* Do not send back route to sender. */
1516 if (onlypeer
&& from
== onlypeer
) {
1520 /* Do not send the default route in the BGP table if the neighbor is
1521 * configured for default-originate */
1522 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1523 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1524 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1526 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1530 /* Transparency check. */
1531 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1532 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1537 /* If community is not disabled check the no-export and local. */
1538 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1539 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1541 "subgrpannouncecheck: community filter check fail");
1545 /* If the attribute has originator-id and it is same as remote
1547 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1548 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1549 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1551 "%s [Update:SEND] %s originator-id is same as "
1554 prefix2str(p
, buf
, sizeof(buf
)));
1558 /* ORF prefix-list filter check */
1559 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1560 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1561 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1562 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1563 if (peer
->orf_plist
[afi
][safi
]) {
1564 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1566 if (bgp_debug_update(NULL
, p
,
1567 subgrp
->update_group
, 0))
1569 "%s [Update:SEND] %s is filtered via ORF",
1577 /* Output filter check. */
1578 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1579 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1580 zlog_debug("%s [Update:SEND] %s is filtered",
1581 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1585 #ifdef BGP_SEND_ASPATH_CHECK
1586 /* AS path loop check. */
1587 if (onlypeer
&& aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1588 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1590 "%s [Update:SEND] suppress announcement to peer AS %u "
1591 "that is part of AS path.",
1592 onlypeer
->host
, onlypeer
->as
);
1595 #endif /* BGP_SEND_ASPATH_CHECK */
1597 /* If we're a CONFED we need to loop check the CONFED ID too */
1598 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1599 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1600 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1602 "%s [Update:SEND] suppress announcement to peer AS %u"
1604 peer
->host
, bgp
->confed_id
);
1609 /* Route-Reflect check. */
1610 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1615 /* IBGP reflection check. */
1616 if (reflect
&& !samepeer_safe
) {
1617 /* A route from a Client peer. */
1618 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1619 PEER_FLAG_REFLECTOR_CLIENT
)) {
1620 /* Reflect to all the Non-Client peers and also to the
1621 Client peers other than the originator. Originator
1623 is already done. So there is noting to do. */
1624 /* no bgp client-to-client reflection check. */
1625 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1626 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1627 PEER_FLAG_REFLECTOR_CLIENT
))
1630 /* A route from a Non-client peer. Reflect to all other
1632 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1633 PEER_FLAG_REFLECTOR_CLIENT
))
1638 /* For modify attribute, copy it to temporary structure. */
1639 bgp_attr_dup(attr
, piattr
);
1641 /* If local-preference is not set. */
1642 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1643 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1644 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1645 attr
->local_pref
= bgp
->default_local_pref
;
1648 /* If originator-id is not set and the route is to be reflected,
1649 set the originator id */
1651 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1652 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1653 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1656 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1658 if (peer
->sort
== BGP_PEER_EBGP
1659 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1660 if (from
!= bgp
->peer_self
&& !transparent
1661 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1662 PEER_FLAG_MED_UNCHANGED
))
1664 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1667 /* Since the nexthop attribute can vary per peer, it is not explicitly
1669 * in announce check, only certain flags and length (or number of
1671 * -- for IPv6/MP_REACH) are set here in order to guide the update
1673 * code in setting the nexthop(s) on a per peer basis in
1675 * Typically, the source nexthop in the attribute is preserved but in
1677 * scenarios where we know it will always be overwritten, we reset the
1678 * nexthop to "0" in an attempt to achieve better Update packing. An
1679 * example of this is when a prefix from each of 2 IBGP peers needs to
1681 * announced to an EBGP peer (and they have the same attributes barring
1685 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1687 #define NEXTHOP_IS_V6 \
1688 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1689 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1690 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1691 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1693 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1695 * the peer (group) is configured to receive link-local nexthop
1697 * and it is available in the prefix OR we're not reflecting the route
1699 * the peer (group) to whom we're going to announce is on a shared
1701 * and this is either a self-originated route or the peer is EBGP.
1703 if (NEXTHOP_IS_V6
) {
1704 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1705 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1706 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1707 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1708 || (!reflect
&& peer
->shared_network
1709 && (from
== bgp
->peer_self
1710 || peer
->sort
== BGP_PEER_EBGP
))) {
1711 attr
->mp_nexthop_len
=
1712 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1715 /* Clear off link-local nexthop in source, whenever it is not
1717 * ensure more prefixes share the same attribute for
1720 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1721 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1722 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1725 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1726 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1728 /* Route map & unsuppress-map apply. */
1729 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1730 struct bgp_path_info rmap_path
;
1731 struct bgp_path_info_extra dummy_rmap_path_extra
;
1732 struct attr dummy_attr
;
1734 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1735 rmap_path
.peer
= peer
;
1736 rmap_path
.attr
= attr
;
1739 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1740 sizeof(struct bgp_path_info_extra
));
1741 rmap_path
.extra
= &dummy_rmap_path_extra
;
1744 /* don't confuse inbound and outbound setting */
1745 RESET_FLAG(attr
->rmap_change_flags
);
1748 * The route reflector is not allowed to modify the attributes
1749 * of the reflected IBGP routes unless explicitly allowed.
1751 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1752 && !bgp_flag_check(bgp
,
1753 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1754 bgp_attr_dup(&dummy_attr
, attr
);
1755 rmap_path
.attr
= &dummy_attr
;
1758 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1760 if (pi
->extra
&& pi
->extra
->suppress
)
1761 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1762 RMAP_BGP
, &rmap_path
);
1764 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1765 RMAP_BGP
, &rmap_path
);
1767 peer
->rmap_type
= 0;
1769 if (ret
== RMAP_DENYMATCH
) {
1770 bgp_attr_flush(attr
);
1775 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1776 if (peer
->sort
== BGP_PEER_IBGP
1777 || peer
->sort
== BGP_PEER_CONFED
) {
1778 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1779 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1781 bgp_attr_add_gshut_community(attr
);
1785 /* After route-map has been applied, we check to see if the nexthop to
1786 * be carried in the attribute (that is used for the announcement) can
1787 * be cleared off or not. We do this in all cases where we would be
1788 * setting the nexthop to "ourselves". For IPv6, we only need to
1790 * the global nexthop here; the link-local nexthop would have been
1792 * already, and if not, it is required by the update formation code.
1793 * Also see earlier comments in this function.
1796 * If route-map has performed some operation on the nexthop or the peer
1797 * configuration says to pass it unchanged, we cannot reset the nexthop
1798 * here, so only attempt to do it if these aren't true. Note that the
1799 * route-map handler itself might have cleared the nexthop, if for
1801 * it is configured as 'peer-address'.
1803 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1804 piattr
->rmap_change_flags
)
1806 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1807 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1808 /* We can reset the nexthop, if setting (or forcing) it to
1810 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1811 PEER_FLAG_NEXTHOP_SELF
)
1812 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1813 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1815 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1816 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1817 subgroup_announce_reset_nhop(
1818 (peer_cap_enhe(peer
, afi
, safi
)
1822 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1823 /* Can also reset the nexthop if announcing to EBGP, but
1825 * no peer in the subgroup is on a shared subnet.
1826 * Note: 3rd party nexthop currently implemented for
1829 if (!bgp_subgrp_multiaccess_check_v4(piattr
->nexthop
,
1831 subgroup_announce_reset_nhop(
1832 (peer_cap_enhe(peer
, afi
, safi
)
1836 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1838 * This flag is used for leaked vpn-vrf routes
1840 int family
= p
->family
;
1842 if (peer_cap_enhe(peer
, afi
, safi
))
1845 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1847 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1848 __func__
, family2str(family
));
1849 subgroup_announce_reset_nhop(family
, attr
);
1852 /* If IPv6/MP and nexthop does not have any override and happens
1854 * be a link-local address, reset it so that we don't pass along
1856 * source's link-local IPv6 address to recipients who may not be
1858 * the same interface.
1860 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1861 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1862 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1869 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1870 struct bgp_maxpaths_cfg
*mpath_cfg
,
1871 struct bgp_path_info_pair
*result
, afi_t afi
,
1874 struct bgp_path_info
*new_select
;
1875 struct bgp_path_info
*old_select
;
1876 struct bgp_path_info
*pi
;
1877 struct bgp_path_info
*pi1
;
1878 struct bgp_path_info
*pi2
;
1879 struct bgp_path_info
*nextpi
= NULL
;
1880 int paths_eq
, do_mpath
, debug
;
1881 struct list mp_list
;
1882 char pfx_buf
[PREFIX2STR_BUFFER
];
1883 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1885 bgp_mp_list_init(&mp_list
);
1887 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1889 debug
= bgp_debug_bestpath(&rn
->p
);
1892 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1894 /* bgp deterministic-med */
1896 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1898 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1899 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1901 bgp_path_info_unset_flag(rn
, pi1
,
1902 BGP_PATH_DMED_SELECTED
);
1904 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1906 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1908 if (BGP_PATH_HOLDDOWN(pi1
))
1910 if (pi1
->peer
&& pi1
->peer
!= bgp
->peer_self
)
1911 if (pi1
->peer
->status
!= Established
)
1916 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
1917 if (CHECK_FLAG(pi2
->flags
,
1918 BGP_PATH_DMED_CHECK
))
1920 if (BGP_PATH_HOLDDOWN(pi2
))
1923 && pi2
->peer
!= bgp
->peer_self
1926 PEER_STATUS_NSF_WAIT
))
1927 if (pi2
->peer
->status
1931 if (!aspath_cmp_left(pi1
->attr
->aspath
,
1933 && !aspath_cmp_left_confed(
1938 if (bgp_path_info_cmp(
1939 bgp
, pi2
, new_select
,
1940 &paths_eq
, mpath_cfg
, debug
,
1941 pfx_buf
, afi
, safi
)) {
1942 bgp_path_info_unset_flag(
1944 BGP_PATH_DMED_SELECTED
);
1948 bgp_path_info_set_flag(
1949 rn
, pi2
, BGP_PATH_DMED_CHECK
);
1952 bgp_path_info_set_flag(rn
, new_select
,
1953 BGP_PATH_DMED_CHECK
);
1954 bgp_path_info_set_flag(rn
, new_select
,
1955 BGP_PATH_DMED_SELECTED
);
1958 bgp_path_info_path_with_addpath_rx_str(
1959 new_select
, path_buf
);
1960 zlog_debug("%s: %s is the bestpath from AS %u",
1962 aspath_get_first_as(
1963 new_select
->attr
->aspath
));
1968 /* Check old selected route and new selected route. */
1971 for (pi
= bgp_node_get_bgp_path_info(rn
);
1972 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
1973 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
1976 if (BGP_PATH_HOLDDOWN(pi
)) {
1977 /* reap REMOVED routes, if needs be
1978 * selected route must stay for a while longer though
1980 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
1981 && (pi
!= old_select
))
1982 bgp_path_info_reap(rn
, pi
);
1985 zlog_debug("%s: pi %p in holddown", __func__
,
1991 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
1992 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1993 if (pi
->peer
->status
!= Established
) {
1997 "%s: pi %p non self peer %s not estab state",
1998 __func__
, pi
, pi
->peer
->host
);
2003 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2004 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2005 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2007 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2011 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2013 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2014 debug
, pfx_buf
, afi
, safi
)) {
2019 /* Now that we know which path is the bestpath see if any of the other
2021 * qualify as multipaths
2025 bgp_path_info_path_with_addpath_rx_str(new_select
,
2028 sprintf(path_buf
, "NONE");
2030 "%s: After path selection, newbest is %s oldbest was %s",
2032 old_select
? old_select
->peer
->host
: "NONE");
2035 if (do_mpath
&& new_select
) {
2036 for (pi
= bgp_node_get_bgp_path_info(rn
);
2037 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2040 bgp_path_info_path_with_addpath_rx_str(
2043 if (pi
== new_select
) {
2046 "%s: %s is the bestpath, add to the multipath list",
2048 bgp_mp_list_add(&mp_list
, pi
);
2052 if (BGP_PATH_HOLDDOWN(pi
))
2055 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2056 && !CHECK_FLAG(pi
->peer
->sflags
,
2057 PEER_STATUS_NSF_WAIT
))
2058 if (pi
->peer
->status
!= Established
)
2061 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2064 "%s: %s has the same nexthop as the bestpath, skip it",
2069 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2070 mpath_cfg
, debug
, pfx_buf
, afi
, safi
);
2075 "%s: %s is equivalent to the bestpath, add to the multipath list",
2077 bgp_mp_list_add(&mp_list
, pi
);
2082 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2084 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2085 bgp_mp_list_clear(&mp_list
);
2087 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2089 result
->old
= old_select
;
2090 result
->new = new_select
;
2096 * A new route/change in bestpath of an existing route. Evaluate the path
2097 * for advertisement to the subgroup.
2099 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2100 struct bgp_path_info
*selected
,
2101 struct bgp_node
*rn
,
2102 uint32_t addpath_tx_id
)
2105 struct peer
*onlypeer
;
2111 afi
= SUBGRP_AFI(subgrp
);
2112 safi
= SUBGRP_SAFI(subgrp
);
2113 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2116 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2117 char buf_prefix
[PREFIX_STRLEN
];
2118 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2119 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2123 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2124 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2125 PEER_STATUS_ORF_WAIT_REFRESH
))
2128 memset(&attr
, 0, sizeof(struct attr
));
2129 /* It's initialized in bgp_announce_check() */
2131 /* Announcement to the subgroup. If the route is filtered withdraw it.
2134 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2135 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2137 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2141 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2143 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2150 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2151 * This is called at the end of route processing.
2153 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2155 struct bgp_path_info
*pi
;
2157 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2158 if (BGP_PATH_HOLDDOWN(pi
))
2160 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2161 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2166 * Has the route changed from the RIB's perspective? This is invoked only
2167 * if the route selection returns the same best route as earlier - to
2168 * determine if we need to update zebra or not.
2170 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2171 struct bgp_path_info
*selected
)
2173 struct bgp_path_info
*mpinfo
;
2175 /* If this is multipath, check all selected paths for any nexthop
2176 * change or attribute change. Some attribute changes (e.g., community)
2177 * aren't of relevance to the RIB, but we'll update zebra to ensure
2178 * we handle the case of BGP nexthop change. This is the behavior
2179 * when the best path has an attribute change anyway.
2181 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2182 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2186 * If this is multipath, check all selected paths for any nexthop change
2188 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2189 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2190 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2191 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2195 /* Nothing has changed from the RIB's perspective. */
2199 struct bgp_process_queue
{
2201 STAILQ_HEAD(, bgp_node
) pqueue
;
2202 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2204 unsigned int queued
;
2208 * old_select = The old best path
2209 * new_select = the new best path
2211 * if (!old_select && new_select)
2212 * We are sending new information on.
2214 * if (old_select && new_select) {
2215 * if (new_select != old_select)
2216 * We have a new best path send a change
2218 * We've received a update with new attributes that needs
2222 * if (old_select && !new_select)
2223 * We have no eligible route that we can announce or the rn
2226 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2227 afi_t afi
, safi_t safi
)
2229 struct bgp_path_info
*new_select
;
2230 struct bgp_path_info
*old_select
;
2231 struct bgp_path_info_pair old_and_new
;
2232 char pfx_buf
[PREFIX2STR_BUFFER
];
2235 /* Is it end of initial update? (after startup) */
2237 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2238 sizeof(bgp
->update_delay_zebra_resume_time
));
2240 bgp
->main_zebra_update_hold
= 0;
2241 FOREACH_AFI_SAFI (afi
, safi
) {
2242 if (bgp_fibupd_safi(safi
))
2243 bgp_zebra_announce_table(bgp
, afi
, safi
);
2245 bgp
->main_peers_update_hold
= 0;
2247 bgp_start_routeadv(bgp
);
2251 struct prefix
*p
= &rn
->p
;
2253 debug
= bgp_debug_bestpath(&rn
->p
);
2255 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2256 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2257 afi2str(afi
), safi2str(safi
));
2260 /* Best path selection. */
2261 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2263 old_select
= old_and_new
.old
;
2264 new_select
= old_and_new
.new;
2266 /* Do we need to allocate or free labels?
2267 * Right now, since we only deal with per-prefix labels, it is not
2268 * necessary to do this upon changes to best path except if the label
2271 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2274 || bgp_label_index_differs(new_select
, old_select
)
2275 || new_select
->sub_type
!= old_select
->sub_type
) {
2276 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2277 && new_select
->attr
->flag
2279 BGP_ATTR_PREFIX_SID
)
2280 && new_select
->attr
->label_index
2281 != BGP_INVALID_LABEL_INDEX
) {
2284 BGP_NODE_REGISTERED_FOR_LABEL
))
2285 bgp_unregister_for_label(rn
);
2286 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2288 bgp_set_valid_label(&rn
->local_label
);
2290 bgp_register_for_label(rn
, new_select
);
2292 } else if (CHECK_FLAG(rn
->flags
,
2293 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2294 bgp_unregister_for_label(rn
);
2296 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2297 bgp_unregister_for_label(rn
);
2301 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2303 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2304 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2305 old_select
, new_select
);
2308 /* If best route remains the same and this is not due to user-initiated
2309 * clear, see exactly what needs to be done.
2311 if (old_select
&& old_select
== new_select
2312 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2313 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2314 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2315 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2317 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2318 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2320 if (bgp_fibupd_safi(safi
)
2321 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2323 if (new_select
->type
== ZEBRA_ROUTE_BGP
2324 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2325 || new_select
->sub_type
2326 == BGP_ROUTE_IMPORTED
))
2328 bgp_zebra_announce(rn
, p
, old_select
,
2332 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2333 bgp_zebra_clear_route_change_flags(rn
);
2335 /* If there is a change of interest to peers, reannounce the
2337 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2338 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2339 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2341 /* unicast routes must also be annouced to
2342 * labeled-unicast update-groups */
2343 if (safi
== SAFI_UNICAST
)
2344 group_announce_route(bgp
, afi
,
2345 SAFI_LABELED_UNICAST
, rn
,
2348 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2349 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2352 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2356 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2358 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2360 /* bestpath has changed; bump version */
2361 if (old_select
|| new_select
) {
2362 bgp_bump_version(rn
);
2364 if (!bgp
->t_rmap_def_originate_eval
) {
2368 update_group_refresh_default_originate_route_map
,
2369 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2370 &bgp
->t_rmap_def_originate_eval
);
2375 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2378 zlog_debug("%s: setting SELECTED flag", __func__
);
2379 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2380 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2381 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2385 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2386 if (old_select
!= new_select
) {
2388 vnc_import_bgp_exterior_del_route(bgp
, p
,
2390 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2393 vnc_import_bgp_exterior_add_route(bgp
, p
,
2395 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2401 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2403 /* unicast routes must also be annouced to labeled-unicast update-groups
2405 if (safi
== SAFI_UNICAST
)
2406 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2410 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2411 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2412 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2413 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2414 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2415 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2417 /* if this is an evpn imported type-5 prefix,
2418 * we need to withdraw the route first to clear
2419 * the nh neigh and the RMAC entry.
2422 is_route_parent_evpn(old_select
))
2423 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2425 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2427 /* Withdraw the route from the kernel. */
2428 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2429 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2430 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2431 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2433 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2437 /* advertise/withdraw type-5 routes */
2438 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2439 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2440 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2442 /* apply the route-map */
2443 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2446 ret
= route_map_apply(
2447 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2448 &rn
->p
, RMAP_BGP
, new_select
);
2449 if (ret
== RMAP_MATCH
)
2450 bgp_evpn_advertise_type5_route(
2451 bgp
, &rn
->p
, new_select
->attr
,
2454 bgp_evpn_advertise_type5_route(bgp
,
2460 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2461 (!old_select
->extra
|| !old_select
->extra
->parent
))
2462 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2465 /* Clear any route change flags. */
2466 bgp_zebra_clear_route_change_flags(rn
);
2468 /* Reap old select bgp_path_info, if it has been removed */
2469 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2470 bgp_path_info_reap(rn
, old_select
);
2472 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2476 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2478 struct bgp_process_queue
*pqnode
= data
;
2479 struct bgp
*bgp
= pqnode
->bgp
;
2480 struct bgp_table
*table
;
2481 struct bgp_node
*rn
;
2484 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2485 bgp_process_main_one(bgp
, NULL
, 0, 0);
2486 /* should always have dedicated wq call */
2487 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2491 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2492 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2493 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2494 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2495 table
= bgp_node_table(rn
);
2496 /* note, new RNs may be added as part of processing */
2497 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2499 bgp_unlock_node(rn
);
2500 bgp_table_unlock(table
);
2506 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2508 struct bgp_process_queue
*pqnode
= data
;
2510 bgp_unlock(pqnode
->bgp
);
2512 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2515 void bgp_process_queue_init(void)
2517 if (!bm
->process_main_queue
)
2518 bm
->process_main_queue
=
2519 work_queue_new(bm
->master
, "process_main_queue");
2521 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2522 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2523 bm
->process_main_queue
->spec
.max_retries
= 0;
2524 bm
->process_main_queue
->spec
.hold
= 50;
2525 /* Use a higher yield value of 50ms for main queue processing */
2526 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2529 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2531 struct bgp_process_queue
*pqnode
;
2533 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2534 sizeof(struct bgp_process_queue
));
2536 /* unlocked in bgp_processq_del */
2537 pqnode
->bgp
= bgp_lock(bgp
);
2538 STAILQ_INIT(&pqnode
->pqueue
);
2543 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2545 #define ARBITRARY_PROCESS_QLEN 10000
2546 struct work_queue
*wq
= bm
->process_main_queue
;
2547 struct bgp_process_queue
*pqnode
;
2548 int pqnode_reuse
= 0;
2550 /* already scheduled for processing? */
2551 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2557 /* Add route nodes to an existing work queue item until reaching the
2558 limit only if is from the same BGP view and it's not an EOIU marker
2560 if (work_queue_item_count(wq
)) {
2561 struct work_queue_item
*item
= work_queue_last_item(wq
);
2562 pqnode
= item
->data
;
2564 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2565 || pqnode
->bgp
!= bgp
2566 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2567 pqnode
= bgp_processq_alloc(bgp
);
2571 pqnode
= bgp_processq_alloc(bgp
);
2572 /* all unlocked in bgp_process_wq */
2573 bgp_table_lock(bgp_node_table(rn
));
2575 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2578 /* can't be enqueued twice */
2579 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2580 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2584 work_queue_add(wq
, pqnode
);
2589 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2591 struct bgp_process_queue
*pqnode
;
2593 if (bm
->process_main_queue
== NULL
)
2596 pqnode
= bgp_processq_alloc(bgp
);
2598 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2599 work_queue_add(bm
->process_main_queue
, pqnode
);
2602 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2606 peer
= THREAD_ARG(thread
);
2607 peer
->t_pmax_restart
= NULL
;
2609 if (bgp_debug_neighbor_events(peer
))
2611 "%s Maximum-prefix restart timer expired, restore peering",
2614 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2615 zlog_debug("%s: %s peer_clear failed",
2616 __PRETTY_FUNCTION__
, peer
->host
);
2621 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2625 iana_safi_t pkt_safi
;
2627 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2630 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2631 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2632 PEER_STATUS_PREFIX_LIMIT
)
2637 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2639 afi_safi_print(afi
, safi
), peer
->host
,
2640 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2641 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2643 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2644 PEER_FLAG_MAX_PREFIX_WARNING
))
2647 /* Convert AFI, SAFI to values for packet. */
2648 pkt_afi
= afi_int2iana(afi
);
2649 pkt_safi
= safi_int2iana(safi
);
2653 ndata
[0] = (pkt_afi
>> 8);
2655 ndata
[2] = pkt_safi
;
2656 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2657 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2658 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2659 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2661 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2662 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2663 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2667 /* Dynamic peers will just close their connection. */
2668 if (peer_dynamic_neighbor(peer
))
2671 /* restart timer start */
2672 if (peer
->pmax_restart
[afi
][safi
]) {
2673 peer
->v_pmax_restart
=
2674 peer
->pmax_restart
[afi
][safi
] * 60;
2676 if (bgp_debug_neighbor_events(peer
))
2678 "%s Maximum-prefix restart timer started for %d secs",
2679 peer
->host
, peer
->v_pmax_restart
);
2681 BGP_TIMER_ON(peer
->t_pmax_restart
,
2682 bgp_maximum_prefix_restart_timer
,
2683 peer
->v_pmax_restart
);
2688 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2689 PEER_STATUS_PREFIX_LIMIT
);
2691 if (peer
->pcount
[afi
][safi
]
2692 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2693 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2694 PEER_STATUS_PREFIX_THRESHOLD
)
2699 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2700 afi_safi_print(afi
, safi
), peer
->host
,
2701 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2702 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2703 PEER_STATUS_PREFIX_THRESHOLD
);
2705 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2706 PEER_STATUS_PREFIX_THRESHOLD
);
2710 /* Unconditionally remove the route from the RIB, without taking
2711 * damping into consideration (eg, because the session went down)
2713 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2714 struct peer
*peer
, afi_t afi
, safi_t safi
)
2716 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2718 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2719 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2721 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2724 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2725 struct peer
*peer
, afi_t afi
, safi_t safi
,
2726 struct prefix_rd
*prd
)
2728 /* apply dampening, if result is suppressed, we'll be retaining
2729 * the bgp_path_info in the RIB for historical reference.
2731 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2732 && peer
->sort
== BGP_PEER_EBGP
)
2733 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2734 == BGP_DAMP_SUPPRESSED
) {
2735 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2741 if (safi
== SAFI_MPLS_VPN
) {
2742 struct bgp_node
*prn
= NULL
;
2743 struct bgp_table
*table
= NULL
;
2745 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2746 (struct prefix
*)prd
);
2747 if (bgp_node_has_bgp_path_info_data(prn
)) {
2748 table
= bgp_node_get_bgp_table_info(prn
);
2750 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2751 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2753 bgp_unlock_node(prn
);
2755 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2756 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2758 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2759 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2765 /* If this is an EVPN route, process for un-import. */
2766 if (safi
== SAFI_EVPN
)
2767 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2769 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2772 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2773 struct peer
*peer
, struct attr
*attr
,
2774 struct bgp_node
*rn
)
2776 struct bgp_path_info
*new;
2778 /* Make new BGP info. */
2779 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2781 new->instance
= instance
;
2782 new->sub_type
= sub_type
;
2785 new->uptime
= bgp_clock();
2790 static void overlay_index_update(struct attr
*attr
,
2791 struct eth_segment_id
*eth_s_id
,
2792 union gw_addr
*gw_ip
)
2797 if (eth_s_id
== NULL
) {
2798 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2799 sizeof(struct eth_segment_id
));
2801 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2802 sizeof(struct eth_segment_id
));
2804 if (gw_ip
== NULL
) {
2805 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2807 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2808 sizeof(union gw_addr
));
2812 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2813 struct eth_segment_id
*eth_s_id
,
2814 union gw_addr
*gw_ip
)
2816 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2817 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2819 struct eth_segment_id esi
;
2823 if (afi
!= AFI_L2VPN
)
2826 memset(&temp
, 0, sizeof(temp
));
2827 path_eth_s_id
= &temp
.esi
;
2828 path_gw_ip
= &temp
.ip
;
2830 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2833 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2834 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2837 if (gw_ip
== NULL
) {
2838 memset(&temp
, 0, sizeof(temp
));
2839 path_gw_ip_remote
= &temp
.ip
;
2841 path_gw_ip_remote
= gw_ip
;
2843 if (eth_s_id
== NULL
) {
2844 memset(&temp
, 0, sizeof(temp
));
2845 path_eth_s_id_remote
= &temp
.esi
;
2847 path_eth_s_id_remote
= eth_s_id
;
2849 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2852 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2853 sizeof(struct eth_segment_id
));
2856 /* Check if received nexthop is valid or not. */
2857 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2862 /* Only validated for unicast and multicast currently. */
2863 /* Also valid for EVPN where the nexthop is an IP address. */
2864 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2867 /* If NEXT_HOP is present, validate it. */
2868 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2869 if (attr
->nexthop
.s_addr
== 0
2870 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2871 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2875 /* If MP_NEXTHOP is present, validate it. */
2876 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2877 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2878 * it is not an IPv6 link-local address.
2880 if (attr
->mp_nexthop_len
) {
2881 switch (attr
->mp_nexthop_len
) {
2882 case BGP_ATTR_NHLEN_IPV4
:
2883 case BGP_ATTR_NHLEN_VPNV4
:
2884 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2885 || IPV4_CLASS_DE(ntohl(
2886 attr
->mp_nexthop_global_in
.s_addr
))
2887 || bgp_nexthop_self(bgp
,
2888 attr
->mp_nexthop_global_in
));
2891 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2892 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2893 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2894 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2895 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2896 || IN6_IS_ADDR_MULTICAST(
2897 &attr
->mp_nexthop_global
));
2909 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2910 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2911 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2912 uint32_t num_labels
, int soft_reconfig
,
2913 struct bgp_route_evpn
*evpn
)
2916 int aspath_loop_count
= 0;
2917 struct bgp_node
*rn
;
2919 struct attr new_attr
;
2920 struct attr
*attr_new
;
2921 struct bgp_path_info
*pi
;
2922 struct bgp_path_info
*new;
2923 struct bgp_path_info_extra
*extra
;
2925 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2927 int do_loop_check
= 1;
2928 int has_valid_label
= 0;
2930 int vnc_implicit_withdraw
= 0;
2934 memset(&new_attr
, 0, sizeof(struct attr
));
2935 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2936 new_attr
.label
= MPLS_INVALID_LABEL
;
2939 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2940 /* TODO: Check to see if we can get rid of "is_valid_label" */
2941 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2942 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2944 has_valid_label
= bgp_is_valid_label(label
);
2946 /* When peer's soft reconfiguration enabled. Record input packet in
2949 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2950 && peer
!= bgp
->peer_self
)
2951 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2953 /* Check previously received route. */
2954 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
2955 if (pi
->peer
== peer
&& pi
->type
== type
2956 && pi
->sub_type
== sub_type
2957 && pi
->addpath_rx_id
== addpath_id
)
2960 /* AS path local-as loop check. */
2961 if (peer
->change_local_as
) {
2962 if (peer
->allowas_in
[afi
][safi
])
2963 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2964 else if (!CHECK_FLAG(peer
->flags
,
2965 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2966 aspath_loop_count
= 1;
2968 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2969 > aspath_loop_count
) {
2970 reason
= "as-path contains our own AS;";
2975 /* If the peer is configured for "allowas-in origin" and the last ASN in
2977 * as-path is our ASN then we do not need to call aspath_loop_check
2979 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2980 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2983 /* AS path loop check. */
2984 if (do_loop_check
) {
2985 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2986 > peer
->allowas_in
[afi
][safi
]
2987 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2988 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2989 > peer
->allowas_in
[afi
][safi
])) {
2990 reason
= "as-path contains our own AS;";
2995 /* Route reflector originator ID check. */
2996 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2997 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2998 reason
= "originator is us;";
3002 /* Route reflector cluster ID check. */
3003 if (bgp_cluster_filter(peer
, attr
)) {
3004 reason
= "reflected from the same cluster;";
3008 /* Apply incoming filter. */
3009 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3014 bgp_attr_dup(&new_attr
, attr
);
3016 /* Apply incoming route-map.
3017 * NB: new_attr may now contain newly allocated values from route-map
3019 * commands, so we need bgp_attr_flush in the error paths, until we
3021 * the attr (which takes over the memory references) */
3022 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3024 reason
= "route-map;";
3025 bgp_attr_flush(&new_attr
);
3029 if (peer
->sort
== BGP_PEER_EBGP
) {
3031 /* If we receive the graceful-shutdown community from an eBGP
3032 * peer we must lower local-preference */
3033 if (new_attr
.community
3034 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3035 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3036 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3038 /* If graceful-shutdown is configured then add the GSHUT
3039 * community to all paths received from eBGP peers */
3040 } else if (bgp_flag_check(peer
->bgp
,
3041 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3042 bgp_attr_add_gshut_community(&new_attr
);
3046 /* next hop check. */
3047 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3048 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3049 reason
= "martian or self next-hop;";
3050 bgp_attr_flush(&new_attr
);
3054 attr_new
= bgp_attr_intern(&new_attr
);
3056 /* If the update is implicit withdraw. */
3058 pi
->uptime
= bgp_clock();
3059 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3061 /* Same attribute comes in. */
3062 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3063 && attrhash_cmp(pi
->attr
, attr_new
)
3064 && (!has_valid_label
3065 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3066 num_labels
* sizeof(mpls_label_t
))
3068 && (overlay_index_equal(
3069 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3070 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3071 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3072 BGP_CONFIG_DAMPENING
)
3073 && peer
->sort
== BGP_PEER_EBGP
3074 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3075 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3076 bgp_debug_rdpfxpath2str(
3077 afi
, safi
, prd
, p
, label
,
3078 num_labels
, addpath_id
? 1 : 0,
3079 addpath_id
, pfx_buf
,
3081 zlog_debug("%s rcvd %s", peer
->host
,
3085 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3086 != BGP_DAMP_SUPPRESSED
) {
3087 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3089 bgp_process(bgp
, rn
, afi
, safi
);
3091 } else /* Duplicate - odd */
3093 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3094 if (!peer
->rcvd_attr_printed
) {
3096 "%s rcvd UPDATE w/ attr: %s",
3098 peer
->rcvd_attr_str
);
3099 peer
->rcvd_attr_printed
= 1;
3102 bgp_debug_rdpfxpath2str(
3103 afi
, safi
, prd
, p
, label
,
3104 num_labels
, addpath_id
? 1 : 0,
3105 addpath_id
, pfx_buf
,
3108 "%s rcvd %s...duplicate ignored",
3109 peer
->host
, pfx_buf
);
3112 /* graceful restart STALE flag unset. */
3113 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3114 bgp_path_info_unset_flag(
3115 rn
, pi
, BGP_PATH_STALE
);
3116 bgp_process(bgp
, rn
, afi
, safi
);
3120 bgp_unlock_node(rn
);
3121 bgp_attr_unintern(&attr_new
);
3126 /* Withdraw/Announce before we fully processed the withdraw */
3127 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3128 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3129 bgp_debug_rdpfxpath2str(
3130 afi
, safi
, prd
, p
, label
, num_labels
,
3131 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3134 "%s rcvd %s, flapped quicker than processing",
3135 peer
->host
, pfx_buf
);
3138 bgp_path_info_restore(rn
, pi
);
3141 /* Received Logging. */
3142 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3143 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3144 num_labels
, addpath_id
? 1 : 0,
3145 addpath_id
, pfx_buf
,
3147 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3150 /* graceful restart STALE flag unset. */
3151 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3152 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3154 /* The attribute is changed. */
3155 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3157 /* implicit withdraw, decrement aggregate and pcount here.
3158 * only if update is accepted, they'll increment below.
3160 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3162 /* Update bgp route dampening information. */
3163 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3164 && peer
->sort
== BGP_PEER_EBGP
) {
3165 /* This is implicit withdraw so we should update
3168 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3169 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3172 if (safi
== SAFI_MPLS_VPN
) {
3173 struct bgp_node
*prn
= NULL
;
3174 struct bgp_table
*table
= NULL
;
3176 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3177 (struct prefix
*)prd
);
3178 if (bgp_node_has_bgp_path_info_data(prn
)) {
3179 table
= bgp_node_get_bgp_table_info(prn
);
3181 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3182 bgp
, prd
, table
, p
, pi
);
3184 bgp_unlock_node(prn
);
3186 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3187 && (safi
== SAFI_UNICAST
)) {
3188 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3190 * Implicit withdraw case.
3192 ++vnc_implicit_withdraw
;
3193 vnc_import_bgp_del_route(bgp
, p
, pi
);
3194 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3199 /* Special handling for EVPN update of an existing route. If the
3200 * extended community attribute has changed, we need to
3202 * the route using its existing extended community. It will be
3203 * subsequently processed for import with the new extended
3206 if (safi
== SAFI_EVPN
&& !same_attr
) {
3208 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3210 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3213 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3214 attr_new
->ecommunity
);
3216 if (bgp_debug_update(peer
, p
, NULL
, 1))
3218 "Change in EXT-COMM, existing %s new %s",
3220 pi
->attr
->ecommunity
),
3222 attr_new
->ecommunity
));
3223 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3229 /* Update to new attribute. */
3230 bgp_attr_unintern(&pi
->attr
);
3231 pi
->attr
= attr_new
;
3233 /* Update MPLS label */
3234 if (has_valid_label
) {
3235 extra
= bgp_path_info_extra_get(pi
);
3236 memcpy(&extra
->label
, label
,
3237 num_labels
* sizeof(mpls_label_t
));
3238 extra
->num_labels
= num_labels
;
3239 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3240 bgp_set_valid_label(&extra
->label
[0]);
3244 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3245 && (safi
== SAFI_UNICAST
)) {
3246 if (vnc_implicit_withdraw
) {
3248 * Add back the route with its new attributes
3250 * The route is still selected, until the route
3252 * queued by bgp_process actually runs. We have
3254 * update to the VNC side immediately to avoid
3256 * configuration changes (e.g., route-map
3258 * trigger re-importation of the entire RIB.
3260 vnc_import_bgp_add_route(bgp
, p
, pi
);
3261 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3265 /* Update Overlay Index */
3266 if (afi
== AFI_L2VPN
) {
3267 overlay_index_update(
3268 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3269 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3272 /* Update bgp route dampening information. */
3273 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3274 && peer
->sort
== BGP_PEER_EBGP
) {
3275 /* Now we do normal update dampening. */
3276 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3277 if (ret
== BGP_DAMP_SUPPRESSED
) {
3278 bgp_unlock_node(rn
);
3283 /* Nexthop reachability check - for unicast and
3284 * labeled-unicast.. */
3285 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3286 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3287 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3288 && !CHECK_FLAG(peer
->flags
,
3289 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3291 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3296 struct bgp
*bgp_nexthop
= bgp
;
3298 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3299 bgp_nexthop
= pi
->extra
->bgp_orig
;
3301 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3303 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3304 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3306 if (BGP_DEBUG(nht
, NHT
)) {
3307 char buf1
[INET6_ADDRSTRLEN
];
3309 (const void *)&attr_new
3311 buf1
, INET6_ADDRSTRLEN
);
3312 zlog_debug("%s(%s): NH unresolved",
3313 __FUNCTION__
, buf1
);
3315 bgp_path_info_unset_flag(rn
, pi
,
3319 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3322 if (safi
== SAFI_MPLS_VPN
) {
3323 struct bgp_node
*prn
= NULL
;
3324 struct bgp_table
*table
= NULL
;
3326 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3327 (struct prefix
*)prd
);
3328 if (bgp_node_has_bgp_path_info_data(prn
)) {
3329 table
= bgp_node_get_bgp_table_info(prn
);
3331 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3332 bgp
, prd
, table
, p
, pi
);
3334 bgp_unlock_node(prn
);
3338 /* If this is an EVPN route and some attribute has changed,
3340 * route for import. If the extended community has changed, we
3342 * have done the un-import earlier and the import would result
3344 * route getting injected into appropriate L2 VNIs. If it is
3346 * some other attribute change, the import will result in
3348 * the attributes for the route in the VNI(s).
3350 if (safi
== SAFI_EVPN
&& !same_attr
)
3351 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3353 /* Process change. */
3354 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3356 bgp_process(bgp
, rn
, afi
, safi
);
3357 bgp_unlock_node(rn
);
3359 if (SAFI_UNICAST
== safi
3360 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3361 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3363 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3365 if ((SAFI_MPLS_VPN
== safi
)
3366 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3368 vpn_leak_to_vrf_update(bgp
, pi
);
3372 if (SAFI_MPLS_VPN
== safi
) {
3373 mpls_label_t label_decoded
= decode_label(label
);
3375 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3376 type
, sub_type
, &label_decoded
);
3378 if (SAFI_ENCAP
== safi
) {
3379 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3380 type
, sub_type
, NULL
);
3385 } // End of implicit withdraw
3387 /* Received Logging. */
3388 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3389 if (!peer
->rcvd_attr_printed
) {
3390 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3391 peer
->rcvd_attr_str
);
3392 peer
->rcvd_attr_printed
= 1;
3395 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3396 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3398 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3401 /* Make new BGP info. */
3402 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3404 /* Update MPLS label */
3405 if (has_valid_label
) {
3406 extra
= bgp_path_info_extra_get(new);
3407 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3408 extra
->num_labels
= num_labels
;
3409 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3410 bgp_set_valid_label(&extra
->label
[0]);
3413 /* Update Overlay Index */
3414 if (afi
== AFI_L2VPN
) {
3415 overlay_index_update(new->attr
,
3416 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3417 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3419 /* Nexthop reachability check. */
3420 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3421 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3422 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3423 && !CHECK_FLAG(peer
->flags
,
3424 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3425 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3430 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3431 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3432 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3434 if (BGP_DEBUG(nht
, NHT
)) {
3435 char buf1
[INET6_ADDRSTRLEN
];
3437 (const void *)&attr_new
->nexthop
,
3438 buf1
, INET6_ADDRSTRLEN
);
3439 zlog_debug("%s(%s): NH unresolved",
3440 __FUNCTION__
, buf1
);
3442 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3445 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3448 new->addpath_rx_id
= addpath_id
;
3450 /* Increment prefix */
3451 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3453 /* Register new BGP information. */
3454 bgp_path_info_add(rn
, new);
3456 /* route_node_get lock */
3457 bgp_unlock_node(rn
);
3460 if (safi
== SAFI_MPLS_VPN
) {
3461 struct bgp_node
*prn
= NULL
;
3462 struct bgp_table
*table
= NULL
;
3464 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3465 if (bgp_node_has_bgp_path_info_data(prn
)) {
3466 table
= bgp_node_get_bgp_table_info(prn
);
3468 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3469 bgp
, prd
, table
, p
, new);
3471 bgp_unlock_node(prn
);
3475 /* If maximum prefix count is configured and current prefix
3477 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3480 /* If this is an EVPN route, process for import. */
3481 if (safi
== SAFI_EVPN
)
3482 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3484 /* Process change. */
3485 bgp_process(bgp
, rn
, afi
, safi
);
3487 if (SAFI_UNICAST
== safi
3488 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3489 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3490 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3492 if ((SAFI_MPLS_VPN
== safi
)
3493 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3495 vpn_leak_to_vrf_update(bgp
, new);
3498 if (SAFI_MPLS_VPN
== safi
) {
3499 mpls_label_t label_decoded
= decode_label(label
);
3501 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3502 sub_type
, &label_decoded
);
3504 if (SAFI_ENCAP
== safi
) {
3505 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3512 /* This BGP update is filtered. Log the reason then update BGP
3515 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3516 if (!peer
->rcvd_attr_printed
) {
3517 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3518 peer
->rcvd_attr_str
);
3519 peer
->rcvd_attr_printed
= 1;
3522 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3523 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3525 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3526 peer
->host
, pfx_buf
, reason
);
3530 /* If this is an EVPN route, un-import it as it is now filtered.
3532 if (safi
== SAFI_EVPN
)
3533 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3535 if (SAFI_UNICAST
== safi
3536 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3537 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3539 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3541 if ((SAFI_MPLS_VPN
== safi
)
3542 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3544 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3547 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3550 bgp_unlock_node(rn
);
3554 * Filtered update is treated as an implicit withdrawal (see
3556 * a few lines above)
3558 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3559 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3567 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3568 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3569 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3570 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3573 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3574 struct bgp_node
*rn
;
3575 struct bgp_path_info
*pi
;
3578 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3579 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3587 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3589 /* If peer is soft reconfiguration enabled. Record input packet for
3590 * further calculation.
3592 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3593 * routes that are filtered. This tanks out Quagga RS pretty badly due
3595 * the iteration over all RS clients.
3596 * Since we need to remove the entry from adj_in anyway, do that first
3598 * if there was no entry, we don't need to do anything more.
3600 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3601 && peer
!= bgp
->peer_self
)
3602 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3603 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3604 bgp_debug_rdpfxpath2str(
3605 afi
, safi
, prd
, p
, label
, num_labels
,
3606 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3609 "%s withdrawing route %s not in adj-in",
3610 peer
->host
, pfx_buf
);
3612 bgp_unlock_node(rn
);
3616 /* Lookup withdrawn route. */
3617 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3618 if (pi
->peer
== peer
&& pi
->type
== type
3619 && pi
->sub_type
== sub_type
3620 && pi
->addpath_rx_id
== addpath_id
)
3624 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3625 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3626 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3628 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3632 /* Withdraw specified route from routing table. */
3633 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3634 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3635 if (SAFI_UNICAST
== safi
3636 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3637 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3638 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3640 if ((SAFI_MPLS_VPN
== safi
)
3641 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3643 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3645 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3646 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3647 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3649 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3652 /* Unlock bgp_node_get() lock. */
3653 bgp_unlock_node(rn
);
3658 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3661 struct update_subgroup
*subgrp
;
3662 subgrp
= peer_subgroup(peer
, afi
, safi
);
3663 subgroup_default_originate(subgrp
, withdraw
);
3668 * bgp_stop_announce_route_timer
3670 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3672 if (!paf
->t_announce_route
)
3675 THREAD_TIMER_OFF(paf
->t_announce_route
);
3679 * bgp_announce_route_timer_expired
3681 * Callback that is invoked when the route announcement timer for a
3684 static int bgp_announce_route_timer_expired(struct thread
*t
)
3686 struct peer_af
*paf
;
3689 paf
= THREAD_ARG(t
);
3692 if (peer
->status
!= Established
)
3695 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3698 peer_af_announce_route(paf
, 1);
3703 * bgp_announce_route
3705 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3707 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3709 struct peer_af
*paf
;
3710 struct update_subgroup
*subgrp
;
3712 paf
= peer_af_find(peer
, afi
, safi
);
3715 subgrp
= PAF_SUBGRP(paf
);
3718 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3719 * or a refresh has already been triggered.
3721 if (!subgrp
|| paf
->t_announce_route
)
3725 * Start a timer to stagger/delay the announce. This serves
3726 * two purposes - announcement can potentially be combined for
3727 * multiple peers and the announcement doesn't happen in the
3730 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3731 (subgrp
->peer_count
== 1)
3732 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3733 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3734 &paf
->t_announce_route
);
3738 * Announce routes from all AF tables to a peer.
3740 * This should ONLY be called when there is a need to refresh the
3741 * routes to the peer based on a policy change for this peer alone
3742 * or a route refresh request received from the peer.
3743 * The operation will result in splitting the peer from its existing
3744 * subgroups and putting it in new subgroups.
3746 void bgp_announce_route_all(struct peer
*peer
)
3751 FOREACH_AFI_SAFI (afi
, safi
)
3752 bgp_announce_route(peer
, afi
, safi
);
3755 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3756 struct bgp_table
*table
,
3757 struct prefix_rd
*prd
)
3760 struct bgp_node
*rn
;
3761 struct bgp_adj_in
*ain
;
3764 table
= peer
->bgp
->rib
[afi
][safi
];
3766 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3767 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3768 if (ain
->peer
!= peer
)
3771 struct bgp_path_info
*pi
=
3772 bgp_node_get_bgp_path_info(rn
);
3773 uint32_t num_labels
= 0;
3774 mpls_label_t
*label_pnt
= NULL
;
3776 if (pi
&& pi
->extra
)
3777 num_labels
= pi
->extra
->num_labels
;
3779 label_pnt
= &pi
->extra
->label
[0];
3781 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3782 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3783 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3784 num_labels
, 1, NULL
);
3787 bgp_unlock_node(rn
);
3793 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3795 struct bgp_node
*rn
;
3796 struct bgp_table
*table
;
3798 if (peer
->status
!= Established
)
3801 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3802 && (safi
!= SAFI_EVPN
))
3803 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3805 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3806 rn
= bgp_route_next(rn
)) {
3807 table
= bgp_node_get_bgp_table_info(rn
);
3808 if (table
!= NULL
) {
3809 struct prefix_rd prd
;
3811 prd
.family
= AF_UNSPEC
;
3813 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3815 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3822 struct bgp_clear_node_queue
{
3823 struct bgp_node
*rn
;
3826 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3828 struct bgp_clear_node_queue
*cnq
= data
;
3829 struct bgp_node
*rn
= cnq
->rn
;
3830 struct peer
*peer
= wq
->spec
.data
;
3831 struct bgp_path_info
*pi
;
3833 afi_t afi
= bgp_node_table(rn
)->afi
;
3834 safi_t safi
= bgp_node_table(rn
)->safi
;
3839 /* It is possible that we have multiple paths for a prefix from a peer
3840 * if that peer is using AddPath.
3842 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3843 if (pi
->peer
!= peer
)
3846 /* graceful restart STALE flag set. */
3847 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3848 && peer
->nsf
[afi
][safi
]
3849 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3850 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3851 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3853 /* If this is an EVPN route, process for
3855 if (safi
== SAFI_EVPN
)
3856 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3858 /* Handle withdraw for VRF route-leaking and L3VPN */
3859 if (SAFI_UNICAST
== safi
3860 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3861 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3862 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3865 if (SAFI_MPLS_VPN
== safi
&&
3866 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3867 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3870 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3876 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3878 struct bgp_clear_node_queue
*cnq
= data
;
3879 struct bgp_node
*rn
= cnq
->rn
;
3880 struct bgp_table
*table
= bgp_node_table(rn
);
3882 bgp_unlock_node(rn
);
3883 bgp_table_unlock(table
);
3884 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3887 static void bgp_clear_node_complete(struct work_queue
*wq
)
3889 struct peer
*peer
= wq
->spec
.data
;
3891 /* Tickle FSM to start moving again */
3892 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3894 peer_unlock(peer
); /* bgp_clear_route */
3897 static void bgp_clear_node_queue_init(struct peer
*peer
)
3899 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3901 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3902 #undef CLEAR_QUEUE_NAME_LEN
3904 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3905 peer
->clear_node_queue
->spec
.hold
= 10;
3906 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3907 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3908 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3909 peer
->clear_node_queue
->spec
.max_retries
= 0;
3911 /* we only 'lock' this peer reference when the queue is actually active
3913 peer
->clear_node_queue
->spec
.data
= peer
;
3916 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3917 struct bgp_table
*table
)
3919 struct bgp_node
*rn
;
3920 int force
= bm
->process_main_queue
? 0 : 1;
3923 table
= peer
->bgp
->rib
[afi
][safi
];
3925 /* If still no table => afi/safi isn't configured at all or smth. */
3929 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3930 struct bgp_path_info
*pi
, *next
;
3931 struct bgp_adj_in
*ain
;
3932 struct bgp_adj_in
*ain_next
;
3934 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3935 * queued for every clearing peer, regardless of whether it is
3936 * relevant to the peer at hand.
3938 * Overview: There are 3 different indices which need to be
3939 * scrubbed, potentially, when a peer is removed:
3941 * 1 peer's routes visible via the RIB (ie accepted routes)
3942 * 2 peer's routes visible by the (optional) peer's adj-in index
3943 * 3 other routes visible by the peer's adj-out index
3945 * 3 there is no hurry in scrubbing, once the struct peer is
3946 * removed from bgp->peer, we could just GC such deleted peer's
3947 * adj-outs at our leisure.
3949 * 1 and 2 must be 'scrubbed' in some way, at least made
3950 * invisible via RIB index before peer session is allowed to be
3951 * brought back up. So one needs to know when such a 'search' is
3956 * - there'd be a single global queue or a single RIB walker
3957 * - rather than tracking which route_nodes still need to be
3958 * examined on a peer basis, we'd track which peers still
3961 * Given that our per-peer prefix-counts now should be reliable,
3962 * this may actually be achievable. It doesn't seem to be a huge
3963 * problem at this time,
3965 * It is possible that we have multiple paths for a prefix from
3967 * if that peer is using AddPath.
3971 ain_next
= ain
->next
;
3973 if (ain
->peer
== peer
) {
3974 bgp_adj_in_remove(rn
, ain
);
3975 bgp_unlock_node(rn
);
3981 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
3983 if (pi
->peer
!= peer
)
3987 bgp_path_info_reap(rn
, pi
);
3989 struct bgp_clear_node_queue
*cnq
;
3991 /* both unlocked in bgp_clear_node_queue_del */
3992 bgp_table_lock(bgp_node_table(rn
));
3995 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3996 sizeof(struct bgp_clear_node_queue
));
3998 work_queue_add(peer
->clear_node_queue
, cnq
);
4006 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4008 struct bgp_node
*rn
;
4009 struct bgp_table
*table
;
4011 if (peer
->clear_node_queue
== NULL
)
4012 bgp_clear_node_queue_init(peer
);
4014 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4015 * Idle until it receives a Clearing_Completed event. This protects
4016 * against peers which flap faster than we can we clear, which could
4019 * a) race with routes from the new session being installed before
4020 * clear_route_node visits the node (to delete the route of that
4022 * b) resource exhaustion, clear_route_node likely leads to an entry
4023 * on the process_main queue. Fast-flapping could cause that queue
4027 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4028 * the unlock will happen upon work-queue completion; other wise, the
4029 * unlock happens at the end of this function.
4031 if (!peer
->clear_node_queue
->thread
)
4034 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4035 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4037 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4038 rn
= bgp_route_next(rn
)) {
4039 table
= bgp_node_get_bgp_table_info(rn
);
4043 bgp_clear_route_table(peer
, afi
, safi
, table
);
4046 /* unlock if no nodes got added to the clear-node-queue. */
4047 if (!peer
->clear_node_queue
->thread
)
4051 void bgp_clear_route_all(struct peer
*peer
)
4056 FOREACH_AFI_SAFI (afi
, safi
)
4057 bgp_clear_route(peer
, afi
, safi
);
4060 rfapiProcessPeerDown(peer
);
4064 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4066 struct bgp_table
*table
;
4067 struct bgp_node
*rn
;
4068 struct bgp_adj_in
*ain
;
4069 struct bgp_adj_in
*ain_next
;
4071 table
= peer
->bgp
->rib
[afi
][safi
];
4073 /* It is possible that we have multiple paths for a prefix from a peer
4074 * if that peer is using AddPath.
4076 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4080 ain_next
= ain
->next
;
4082 if (ain
->peer
== peer
) {
4083 bgp_adj_in_remove(rn
, ain
);
4084 bgp_unlock_node(rn
);
4092 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4094 struct bgp_node
*rn
;
4095 struct bgp_path_info
*pi
;
4096 struct bgp_table
*table
;
4098 if (safi
== SAFI_MPLS_VPN
) {
4099 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4100 rn
= bgp_route_next(rn
)) {
4101 struct bgp_node
*rm
;
4103 /* look for neighbor in tables */
4104 table
= bgp_node_get_bgp_table_info(rn
);
4108 for (rm
= bgp_table_top(table
); rm
;
4109 rm
= bgp_route_next(rm
))
4110 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4112 if (pi
->peer
!= peer
)
4114 if (!CHECK_FLAG(pi
->flags
,
4118 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4123 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4124 rn
= bgp_route_next(rn
))
4125 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4127 if (pi
->peer
!= peer
)
4129 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4131 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4137 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4140 struct bgp_node
*rn
;
4141 struct bgp_path_info
*pi
;
4142 struct bgp_path_info
*next
;
4144 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4145 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4147 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4148 && pi
->type
== ZEBRA_ROUTE_BGP
4149 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4150 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4151 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4153 if (bgp_fibupd_safi(safi
))
4154 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4156 bgp_path_info_reap(rn
, pi
);
4161 /* Delete all kernel routes. */
4162 void bgp_cleanup_routes(struct bgp
*bgp
)
4165 struct bgp_node
*rn
;
4166 struct bgp_table
*table
;
4168 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4169 if (afi
== AFI_L2VPN
)
4171 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4174 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4176 if (afi
!= AFI_L2VPN
) {
4178 safi
= SAFI_MPLS_VPN
;
4179 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4180 rn
= bgp_route_next(rn
)) {
4181 table
= bgp_node_get_bgp_table_info(rn
);
4182 if (table
!= NULL
) {
4183 bgp_cleanup_table(bgp
, table
, safi
);
4184 bgp_table_finish(&table
);
4185 bgp_node_set_bgp_table_info(rn
, NULL
);
4186 bgp_unlock_node(rn
);
4190 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4191 rn
= bgp_route_next(rn
)) {
4192 table
= bgp_node_get_bgp_table_info(rn
);
4193 if (table
!= NULL
) {
4194 bgp_cleanup_table(bgp
, table
, safi
);
4195 bgp_table_finish(&table
);
4196 bgp_node_set_bgp_table_info(rn
, NULL
);
4197 bgp_unlock_node(rn
);
4202 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4203 rn
= bgp_route_next(rn
)) {
4204 table
= bgp_node_get_bgp_table_info(rn
);
4205 if (table
!= NULL
) {
4206 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4207 bgp_table_finish(&table
);
4208 bgp_node_set_bgp_table_info(rn
, NULL
);
4209 bgp_unlock_node(rn
);
4214 void bgp_reset(void)
4217 bgp_zclient_reset();
4218 access_list_reset();
4219 prefix_list_reset();
4222 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4224 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4225 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4226 PEER_CAP_ADDPATH_AF_TX_RCV
));
4229 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4231 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4232 struct bgp_nlri
*packet
)
4241 int addpath_encoded
;
4242 uint32_t addpath_id
;
4245 lim
= pnt
+ packet
->length
;
4247 safi
= packet
->safi
;
4249 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4251 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4252 syntactic validity. If the field is syntactically incorrect,
4253 then the Error Subcode is set to Invalid Network Field. */
4254 for (; pnt
< lim
; pnt
+= psize
) {
4255 /* Clear prefix structure. */
4256 memset(&p
, 0, sizeof(struct prefix
));
4258 if (addpath_encoded
) {
4260 /* When packet overflow occurs return immediately. */
4261 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4264 addpath_id
= ntohl(*((uint32_t *)pnt
));
4265 pnt
+= BGP_ADDPATH_ID_LEN
;
4268 /* Fetch prefix length. */
4269 p
.prefixlen
= *pnt
++;
4270 /* afi/safi validity already verified by caller,
4271 * bgp_update_receive */
4272 p
.family
= afi2family(afi
);
4274 /* Prefix length check. */
4275 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4278 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4279 peer
->host
, p
.prefixlen
, packet
->afi
);
4283 /* Packet size overflow check. */
4284 psize
= PSIZE(p
.prefixlen
);
4286 /* When packet overflow occur return immediately. */
4287 if (pnt
+ psize
> lim
) {
4290 "%s [Error] Update packet error (prefix length %d overflows packet)",
4291 peer
->host
, p
.prefixlen
);
4295 /* Defensive coding, double-check the psize fits in a struct
4297 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4300 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4301 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4305 /* Fetch prefix from NLRI packet. */
4306 memcpy(p
.u
.val
, pnt
, psize
);
4308 /* Check address. */
4309 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4310 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4311 /* From RFC4271 Section 6.3:
4313 * If a prefix in the NLRI field is semantically
4315 * (e.g., an unexpected multicast IP address),
4317 * be logged locally, and the prefix SHOULD be
4322 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4323 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4328 /* Check address. */
4329 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4330 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4335 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4337 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4342 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4347 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4349 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4356 /* Normal process. */
4358 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4359 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4360 NULL
, NULL
, 0, 0, NULL
);
4362 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4363 safi
, ZEBRA_ROUTE_BGP
,
4364 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4367 /* Address family configuration mismatch or maximum-prefix count
4373 /* Packet length consistency check. */
4377 "%s [Error] Update packet error (prefix length mismatch with total length)",
4385 static struct bgp_static
*bgp_static_new(void)
4387 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4390 static void bgp_static_free(struct bgp_static
*bgp_static
)
4392 if (bgp_static
->rmap
.name
)
4393 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4394 if (bgp_static
->eth_s_id
)
4395 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4396 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4399 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4400 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4402 struct bgp_node
*rn
;
4403 struct bgp_path_info
*pi
;
4404 struct bgp_path_info
*new;
4405 struct bgp_path_info rmap_path
;
4407 struct attr
*attr_new
;
4410 int vnc_implicit_withdraw
= 0;
4417 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4419 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4421 attr
.nexthop
= bgp_static
->igpnexthop
;
4422 attr
.med
= bgp_static
->igpmetric
;
4423 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4425 if (bgp_static
->atomic
)
4426 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4428 /* Store label index, if required. */
4429 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4430 attr
.label_index
= bgp_static
->label_index
;
4431 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4434 /* Apply route-map. */
4435 if (bgp_static
->rmap
.name
) {
4436 struct attr attr_tmp
= attr
;
4438 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4439 rmap_path
.peer
= bgp
->peer_self
;
4440 rmap_path
.attr
= &attr_tmp
;
4442 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4444 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4447 bgp
->peer_self
->rmap_type
= 0;
4449 if (ret
== RMAP_DENYMATCH
) {
4450 /* Free uninterned attribute. */
4451 bgp_attr_flush(&attr_tmp
);
4453 /* Unintern original. */
4454 aspath_unintern(&attr
.aspath
);
4455 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4459 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4460 bgp_attr_add_gshut_community(&attr_tmp
);
4462 attr_new
= bgp_attr_intern(&attr_tmp
);
4465 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4466 bgp_attr_add_gshut_community(&attr
);
4468 attr_new
= bgp_attr_intern(&attr
);
4471 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4472 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4473 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4477 if (attrhash_cmp(pi
->attr
, attr_new
)
4478 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4479 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4480 bgp_unlock_node(rn
);
4481 bgp_attr_unintern(&attr_new
);
4482 aspath_unintern(&attr
.aspath
);
4485 /* The attribute is changed. */
4486 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4488 /* Rewrite BGP route information. */
4489 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4490 bgp_path_info_restore(rn
, pi
);
4492 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4494 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4495 && (safi
== SAFI_UNICAST
)) {
4496 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4498 * Implicit withdraw case.
4499 * We have to do this before pi is
4502 ++vnc_implicit_withdraw
;
4503 vnc_import_bgp_del_route(bgp
, p
, pi
);
4504 vnc_import_bgp_exterior_del_route(
4509 bgp_attr_unintern(&pi
->attr
);
4510 pi
->attr
= attr_new
;
4511 pi
->uptime
= bgp_clock();
4513 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4514 && (safi
== SAFI_UNICAST
)) {
4515 if (vnc_implicit_withdraw
) {
4516 vnc_import_bgp_add_route(bgp
, p
, pi
);
4517 vnc_import_bgp_exterior_add_route(
4523 /* Nexthop reachability check. */
4524 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4525 && (safi
== SAFI_UNICAST
4526 || safi
== SAFI_LABELED_UNICAST
)) {
4528 struct bgp
*bgp_nexthop
= bgp
;
4530 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4531 bgp_nexthop
= pi
->extra
->bgp_orig
;
4533 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4535 bgp_path_info_set_flag(rn
, pi
,
4538 if (BGP_DEBUG(nht
, NHT
)) {
4539 char buf1
[INET6_ADDRSTRLEN
];
4540 inet_ntop(p
->family
,
4544 "%s(%s): Route not in table, not advertising",
4545 __FUNCTION__
, buf1
);
4547 bgp_path_info_unset_flag(
4548 rn
, pi
, BGP_PATH_VALID
);
4551 /* Delete the NHT structure if any, if we're
4553 * enabling/disabling import check. We
4554 * deregister the route
4555 * from NHT to avoid overloading NHT and the
4556 * process interaction
4558 bgp_unlink_nexthop(pi
);
4559 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4561 /* Process change. */
4562 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4563 bgp_process(bgp
, rn
, afi
, safi
);
4565 if (SAFI_UNICAST
== safi
4566 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4568 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4569 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4573 bgp_unlock_node(rn
);
4574 aspath_unintern(&attr
.aspath
);
4579 /* Make new BGP info. */
4580 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4582 /* Nexthop reachability check. */
4583 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4584 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4585 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4586 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4588 if (BGP_DEBUG(nht
, NHT
)) {
4589 char buf1
[INET6_ADDRSTRLEN
];
4590 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4593 "%s(%s): Route not in table, not advertising",
4594 __FUNCTION__
, buf1
);
4596 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4599 /* Delete the NHT structure if any, if we're toggling between
4600 * enabling/disabling import check. We deregister the route
4601 * from NHT to avoid overloading NHT and the process interaction
4603 bgp_unlink_nexthop(new);
4605 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4608 /* Aggregate address increment. */
4609 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4611 /* Register new BGP information. */
4612 bgp_path_info_add(rn
, new);
4614 /* route_node_get lock */
4615 bgp_unlock_node(rn
);
4617 /* Process change. */
4618 bgp_process(bgp
, rn
, afi
, safi
);
4620 if (SAFI_UNICAST
== safi
4621 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4622 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4623 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4626 /* Unintern original. */
4627 aspath_unintern(&attr
.aspath
);
4630 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4633 struct bgp_node
*rn
;
4634 struct bgp_path_info
*pi
;
4636 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4638 /* Check selected route and self inserted route. */
4639 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4640 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4641 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4644 /* Withdraw static BGP route from routing table. */
4646 if (SAFI_UNICAST
== safi
4647 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4648 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4649 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4651 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4652 bgp_unlink_nexthop(pi
);
4653 bgp_path_info_delete(rn
, pi
);
4654 bgp_process(bgp
, rn
, afi
, safi
);
4657 /* Unlock bgp_node_lookup. */
4658 bgp_unlock_node(rn
);
4662 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4664 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4665 afi_t afi
, safi_t safi
,
4666 struct prefix_rd
*prd
)
4668 struct bgp_node
*rn
;
4669 struct bgp_path_info
*pi
;
4671 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4673 /* Check selected route and self inserted route. */
4674 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4675 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4676 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4679 /* Withdraw static BGP route from routing table. */
4682 rfapiProcessWithdraw(
4683 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4684 1); /* Kill, since it is an administrative change */
4686 if (SAFI_MPLS_VPN
== safi
4687 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4688 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4690 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4691 bgp_path_info_delete(rn
, pi
);
4692 bgp_process(bgp
, rn
, afi
, safi
);
4695 /* Unlock bgp_node_lookup. */
4696 bgp_unlock_node(rn
);
4699 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4700 struct bgp_static
*bgp_static
, afi_t afi
,
4703 struct bgp_node
*rn
;
4704 struct bgp_path_info
*new;
4705 struct attr
*attr_new
;
4706 struct attr attr
= {0};
4707 struct bgp_path_info
*pi
;
4709 mpls_label_t label
= 0;
4711 uint32_t num_labels
= 0;
4716 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4718 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4721 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4723 attr
.nexthop
= bgp_static
->igpnexthop
;
4724 attr
.med
= bgp_static
->igpmetric
;
4725 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4727 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4728 || (safi
== SAFI_ENCAP
)) {
4729 if (afi
== AFI_IP
) {
4730 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4731 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4734 if (afi
== AFI_L2VPN
) {
4735 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4737 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4738 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4739 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4740 sizeof(struct in6_addr
));
4741 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4742 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4743 struct bgp_encap_type_vxlan bet
;
4744 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4745 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4746 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4748 if (bgp_static
->router_mac
) {
4749 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4752 /* Apply route-map. */
4753 if (bgp_static
->rmap
.name
) {
4754 struct attr attr_tmp
= attr
;
4755 struct bgp_path_info rmap_path
;
4758 rmap_path
.peer
= bgp
->peer_self
;
4759 rmap_path
.attr
= &attr_tmp
;
4761 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4763 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4766 bgp
->peer_self
->rmap_type
= 0;
4768 if (ret
== RMAP_DENYMATCH
) {
4769 /* Free uninterned attribute. */
4770 bgp_attr_flush(&attr_tmp
);
4772 /* Unintern original. */
4773 aspath_unintern(&attr
.aspath
);
4774 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4779 attr_new
= bgp_attr_intern(&attr_tmp
);
4781 attr_new
= bgp_attr_intern(&attr
);
4784 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4785 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4786 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4790 memset(&add
, 0, sizeof(union gw_addr
));
4791 if (attrhash_cmp(pi
->attr
, attr_new
)
4792 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4793 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4794 bgp_unlock_node(rn
);
4795 bgp_attr_unintern(&attr_new
);
4796 aspath_unintern(&attr
.aspath
);
4799 /* The attribute is changed. */
4800 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4802 /* Rewrite BGP route information. */
4803 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4804 bgp_path_info_restore(rn
, pi
);
4806 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4807 bgp_attr_unintern(&pi
->attr
);
4808 pi
->attr
= attr_new
;
4809 pi
->uptime
= bgp_clock();
4812 label
= decode_label(&pi
->extra
->label
[0]);
4815 /* Process change. */
4816 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4817 bgp_process(bgp
, rn
, afi
, safi
);
4819 if (SAFI_MPLS_VPN
== safi
4820 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4821 vpn_leak_to_vrf_update(bgp
, pi
);
4824 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4825 pi
->attr
, afi
, safi
, pi
->type
,
4826 pi
->sub_type
, &label
);
4828 bgp_unlock_node(rn
);
4829 aspath_unintern(&attr
.aspath
);
4835 /* Make new BGP info. */
4836 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4838 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4839 new->extra
= bgp_path_info_extra_new();
4841 new->extra
->label
[0] = bgp_static
->label
;
4842 new->extra
->num_labels
= num_labels
;
4845 label
= decode_label(&bgp_static
->label
);
4848 /* Aggregate address increment. */
4849 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4851 /* Register new BGP information. */
4852 bgp_path_info_add(rn
, new);
4853 /* route_node_get lock */
4854 bgp_unlock_node(rn
);
4856 /* Process change. */
4857 bgp_process(bgp
, rn
, afi
, safi
);
4859 if (SAFI_MPLS_VPN
== safi
4860 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4861 vpn_leak_to_vrf_update(bgp
, new);
4864 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4865 safi
, new->type
, new->sub_type
, &label
);
4868 /* Unintern original. */
4869 aspath_unintern(&attr
.aspath
);
4872 /* Configure static BGP network. When user don't run zebra, static
4873 route should be installed as valid. */
4874 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4875 const char *ip_str
, afi_t afi
, safi_t safi
,
4876 const char *rmap
, int backdoor
, uint32_t label_index
)
4878 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4881 struct bgp_static
*bgp_static
;
4882 struct bgp_node
*rn
;
4883 uint8_t need_update
= 0;
4885 /* Convert IP prefix string to struct prefix. */
4886 ret
= str2prefix(ip_str
, &p
);
4888 vty_out(vty
, "%% Malformed prefix\n");
4889 return CMD_WARNING_CONFIG_FAILED
;
4891 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4892 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4893 return CMD_WARNING_CONFIG_FAILED
;
4900 /* Set BGP static route configuration. */
4901 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4904 vty_out(vty
, "%% Can't find static route specified\n");
4905 return CMD_WARNING_CONFIG_FAILED
;
4908 bgp_static
= bgp_node_get_bgp_static_info(rn
);
4910 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4911 && (label_index
!= bgp_static
->label_index
)) {
4913 "%% label-index doesn't match static route\n");
4914 return CMD_WARNING_CONFIG_FAILED
;
4917 if ((rmap
&& bgp_static
->rmap
.name
)
4918 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4920 "%% route-map name doesn't match static route\n");
4921 return CMD_WARNING_CONFIG_FAILED
;
4924 /* Update BGP RIB. */
4925 if (!bgp_static
->backdoor
)
4926 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4928 /* Clear configuration. */
4929 bgp_static_free(bgp_static
);
4930 bgp_node_set_bgp_static_info(rn
, NULL
);
4931 bgp_unlock_node(rn
);
4932 bgp_unlock_node(rn
);
4935 /* Set BGP static route configuration. */
4936 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4938 bgp_static
= bgp_node_get_bgp_static_info(rn
);
4940 /* Configuration change. */
4941 /* Label index cannot be changed. */
4942 if (bgp_static
->label_index
!= label_index
) {
4943 vty_out(vty
, "%% cannot change label-index\n");
4944 return CMD_WARNING_CONFIG_FAILED
;
4947 /* Check previous routes are installed into BGP. */
4948 if (bgp_static
->valid
4949 && bgp_static
->backdoor
!= backdoor
)
4952 bgp_static
->backdoor
= backdoor
;
4955 if (bgp_static
->rmap
.name
)
4956 XFREE(MTYPE_ROUTE_MAP_NAME
,
4957 bgp_static
->rmap
.name
);
4958 bgp_static
->rmap
.name
=
4959 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4960 bgp_static
->rmap
.map
=
4961 route_map_lookup_by_name(rmap
);
4963 if (bgp_static
->rmap
.name
)
4964 XFREE(MTYPE_ROUTE_MAP_NAME
,
4965 bgp_static
->rmap
.name
);
4966 bgp_static
->rmap
.name
= NULL
;
4967 bgp_static
->rmap
.map
= NULL
;
4968 bgp_static
->valid
= 0;
4970 bgp_unlock_node(rn
);
4972 /* New configuration. */
4973 bgp_static
= bgp_static_new();
4974 bgp_static
->backdoor
= backdoor
;
4975 bgp_static
->valid
= 0;
4976 bgp_static
->igpmetric
= 0;
4977 bgp_static
->igpnexthop
.s_addr
= 0;
4978 bgp_static
->label_index
= label_index
;
4981 if (bgp_static
->rmap
.name
)
4982 XFREE(MTYPE_ROUTE_MAP_NAME
,
4983 bgp_static
->rmap
.name
);
4984 bgp_static
->rmap
.name
=
4985 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4986 bgp_static
->rmap
.map
=
4987 route_map_lookup_by_name(rmap
);
4989 bgp_node_set_bgp_static_info(rn
, bgp_static
);
4992 bgp_static
->valid
= 1;
4994 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4996 if (!bgp_static
->backdoor
)
4997 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5003 void bgp_static_add(struct bgp
*bgp
)
5007 struct bgp_node
*rn
;
5008 struct bgp_node
*rm
;
5009 struct bgp_table
*table
;
5010 struct bgp_static
*bgp_static
;
5012 FOREACH_AFI_SAFI (afi
, safi
)
5013 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5014 rn
= bgp_route_next(rn
)) {
5015 if (!bgp_node_has_bgp_path_info_data(rn
))
5018 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5019 || (safi
== SAFI_EVPN
)) {
5020 table
= bgp_node_get_bgp_table_info(rn
);
5022 for (rm
= bgp_table_top(table
); rm
;
5023 rm
= bgp_route_next(rm
)) {
5025 bgp_node_get_bgp_static_info(
5027 bgp_static_update_safi(bgp
, &rm
->p
,
5034 bgp_node_get_bgp_static_info(rn
), afi
,
5040 /* Called from bgp_delete(). Delete all static routes from the BGP
5042 void bgp_static_delete(struct bgp
*bgp
)
5046 struct bgp_node
*rn
;
5047 struct bgp_node
*rm
;
5048 struct bgp_table
*table
;
5049 struct bgp_static
*bgp_static
;
5051 FOREACH_AFI_SAFI (afi
, safi
)
5052 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5053 rn
= bgp_route_next(rn
)) {
5054 if (!bgp_node_has_bgp_path_info_data(rn
))
5057 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5058 || (safi
== SAFI_EVPN
)) {
5059 table
= bgp_node_get_bgp_table_info(rn
);
5061 for (rm
= bgp_table_top(table
); rm
;
5062 rm
= bgp_route_next(rm
)) {
5064 bgp_node_get_bgp_static_info(
5066 bgp_static_withdraw_safi(
5067 bgp
, &rm
->p
, AFI_IP
, safi
,
5068 (struct prefix_rd
*)&rn
->p
);
5069 bgp_static_free(bgp_static
);
5070 bgp_node_set_bgp_static_info(rn
, NULL
);
5071 bgp_unlock_node(rn
);
5074 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5075 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5076 bgp_static_free(bgp_static
);
5077 bgp_node_set_bgp_static_info(rn
, NULL
);
5078 bgp_unlock_node(rn
);
5083 void bgp_static_redo_import_check(struct bgp
*bgp
)
5087 struct bgp_node
*rn
;
5088 struct bgp_node
*rm
;
5089 struct bgp_table
*table
;
5090 struct bgp_static
*bgp_static
;
5092 /* Use this flag to force reprocessing of the route */
5093 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5094 FOREACH_AFI_SAFI (afi
, safi
) {
5095 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5096 rn
= bgp_route_next(rn
)) {
5097 if (!bgp_node_has_bgp_path_info_data(rn
))
5100 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5101 || (safi
== SAFI_EVPN
)) {
5102 table
= bgp_node_get_bgp_table_info(rn
);
5104 for (rm
= bgp_table_top(table
); rm
;
5105 rm
= bgp_route_next(rm
)) {
5107 bgp_node_get_bgp_static_info(
5109 bgp_static_update_safi(bgp
, &rm
->p
,
5114 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5115 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5120 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5123 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5126 struct bgp_table
*table
;
5127 struct bgp_node
*rn
;
5128 struct bgp_path_info
*pi
;
5130 table
= bgp
->rib
[afi
][safi
];
5131 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5132 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5133 if (pi
->peer
== bgp
->peer_self
5134 && ((pi
->type
== ZEBRA_ROUTE_BGP
5135 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5136 || (pi
->type
!= ZEBRA_ROUTE_BGP
5138 == BGP_ROUTE_REDISTRIBUTE
))) {
5139 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5141 bgp_unlink_nexthop(pi
);
5142 bgp_path_info_delete(rn
, pi
);
5143 bgp_process(bgp
, rn
, afi
, safi
);
5150 * Purge all networks and redistributed routes from routing table.
5151 * Invoked upon the instance going down.
5153 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5158 FOREACH_AFI_SAFI (afi
, safi
)
5159 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5164 * Currently this is used to set static routes for VPN and ENCAP.
5165 * I think it can probably be factored with bgp_static_set.
5167 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5168 const char *ip_str
, const char *rd_str
,
5169 const char *label_str
, const char *rmap_str
,
5170 int evpn_type
, const char *esi
, const char *gwip
,
5171 const char *ethtag
, const char *routermac
)
5173 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5176 struct prefix_rd prd
;
5177 struct bgp_node
*prn
;
5178 struct bgp_node
*rn
;
5179 struct bgp_table
*table
;
5180 struct bgp_static
*bgp_static
;
5181 mpls_label_t label
= MPLS_INVALID_LABEL
;
5182 struct prefix gw_ip
;
5184 /* validate ip prefix */
5185 ret
= str2prefix(ip_str
, &p
);
5187 vty_out(vty
, "%% Malformed prefix\n");
5188 return CMD_WARNING_CONFIG_FAILED
;
5191 if ((afi
== AFI_L2VPN
)
5192 && (bgp_build_evpn_prefix(evpn_type
,
5193 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5194 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5195 return CMD_WARNING_CONFIG_FAILED
;
5198 ret
= str2prefix_rd(rd_str
, &prd
);
5200 vty_out(vty
, "%% Malformed rd\n");
5201 return CMD_WARNING_CONFIG_FAILED
;
5205 unsigned long label_val
;
5206 label_val
= strtoul(label_str
, NULL
, 10);
5207 encode_label(label_val
, &label
);
5210 if (safi
== SAFI_EVPN
) {
5211 if (esi
&& str2esi(esi
, NULL
) == 0) {
5212 vty_out(vty
, "%% Malformed ESI\n");
5213 return CMD_WARNING_CONFIG_FAILED
;
5215 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5216 vty_out(vty
, "%% Malformed Router MAC\n");
5217 return CMD_WARNING_CONFIG_FAILED
;
5220 memset(&gw_ip
, 0, sizeof(struct prefix
));
5221 ret
= str2prefix(gwip
, &gw_ip
);
5223 vty_out(vty
, "%% Malformed GatewayIp\n");
5224 return CMD_WARNING_CONFIG_FAILED
;
5226 if ((gw_ip
.family
== AF_INET
5227 && is_evpn_prefix_ipaddr_v6(
5228 (struct prefix_evpn
*)&p
))
5229 || (gw_ip
.family
== AF_INET6
5230 && is_evpn_prefix_ipaddr_v4(
5231 (struct prefix_evpn
*)&p
))) {
5233 "%% GatewayIp family differs with IP prefix\n");
5234 return CMD_WARNING_CONFIG_FAILED
;
5238 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5239 if (!bgp_node_has_bgp_path_info_data(prn
))
5240 bgp_node_set_bgp_table_info(prn
,
5241 bgp_table_init(bgp
, afi
, safi
));
5243 bgp_unlock_node(prn
);
5244 table
= bgp_node_get_bgp_table_info(prn
);
5246 rn
= bgp_node_get(table
, &p
);
5248 if (bgp_node_has_bgp_path_info_data(rn
)) {
5249 vty_out(vty
, "%% Same network configuration exists\n");
5250 bgp_unlock_node(rn
);
5252 /* New configuration. */
5253 bgp_static
= bgp_static_new();
5254 bgp_static
->backdoor
= 0;
5255 bgp_static
->valid
= 0;
5256 bgp_static
->igpmetric
= 0;
5257 bgp_static
->igpnexthop
.s_addr
= 0;
5258 bgp_static
->label
= label
;
5259 bgp_static
->prd
= prd
;
5262 if (bgp_static
->rmap
.name
)
5263 XFREE(MTYPE_ROUTE_MAP_NAME
,
5264 bgp_static
->rmap
.name
);
5265 bgp_static
->rmap
.name
=
5266 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5267 bgp_static
->rmap
.map
=
5268 route_map_lookup_by_name(rmap_str
);
5271 if (safi
== SAFI_EVPN
) {
5273 bgp_static
->eth_s_id
=
5275 sizeof(struct eth_segment_id
));
5276 str2esi(esi
, bgp_static
->eth_s_id
);
5279 bgp_static
->router_mac
=
5280 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5281 (void)prefix_str2mac(routermac
,
5282 bgp_static
->router_mac
);
5285 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5287 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5289 bgp_static
->valid
= 1;
5290 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5296 /* Configure static BGP network. */
5297 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5298 const char *ip_str
, const char *rd_str
,
5299 const char *label_str
, int evpn_type
, const char *esi
,
5300 const char *gwip
, const char *ethtag
)
5302 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5305 struct prefix_rd prd
;
5306 struct bgp_node
*prn
;
5307 struct bgp_node
*rn
;
5308 struct bgp_table
*table
;
5309 struct bgp_static
*bgp_static
;
5310 mpls_label_t label
= MPLS_INVALID_LABEL
;
5312 /* Convert IP prefix string to struct prefix. */
5313 ret
= str2prefix(ip_str
, &p
);
5315 vty_out(vty
, "%% Malformed prefix\n");
5316 return CMD_WARNING_CONFIG_FAILED
;
5319 if ((afi
== AFI_L2VPN
)
5320 && (bgp_build_evpn_prefix(evpn_type
,
5321 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5322 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5323 return CMD_WARNING_CONFIG_FAILED
;
5325 ret
= str2prefix_rd(rd_str
, &prd
);
5327 vty_out(vty
, "%% Malformed rd\n");
5328 return CMD_WARNING_CONFIG_FAILED
;
5332 unsigned long label_val
;
5333 label_val
= strtoul(label_str
, NULL
, 10);
5334 encode_label(label_val
, &label
);
5337 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5338 if (!bgp_node_has_bgp_path_info_data(prn
))
5339 bgp_node_set_bgp_table_info(prn
,
5340 bgp_table_init(bgp
, afi
, safi
));
5342 bgp_unlock_node(prn
);
5343 table
= bgp_node_get_bgp_table_info(prn
);
5345 rn
= bgp_node_lookup(table
, &p
);
5348 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5350 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5351 bgp_static_free(bgp_static
);
5352 bgp_node_set_bgp_static_info(rn
, NULL
);
5353 bgp_unlock_node(rn
);
5354 bgp_unlock_node(rn
);
5356 vty_out(vty
, "%% Can't find the route\n");
5361 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5362 const char *rmap_name
)
5364 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5365 struct bgp_rmap
*rmap
;
5367 rmap
= &bgp
->table_map
[afi
][safi
];
5370 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5371 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5372 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5375 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5380 if (bgp_fibupd_safi(safi
))
5381 bgp_zebra_announce_table(bgp
, afi
, safi
);
5386 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5387 const char *rmap_name
)
5389 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5390 struct bgp_rmap
*rmap
;
5392 rmap
= &bgp
->table_map
[afi
][safi
];
5394 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5398 if (bgp_fibupd_safi(safi
))
5399 bgp_zebra_announce_table(bgp
, afi
, safi
);
5404 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5407 if (bgp
->table_map
[afi
][safi
].name
) {
5408 vty_out(vty
, " table-map %s\n",
5409 bgp
->table_map
[afi
][safi
].name
);
5413 DEFUN (bgp_table_map
,
5416 "BGP table to RIB route download filter\n"
5417 "Name of the route map\n")
5420 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5421 argv
[idx_word
]->arg
);
5423 DEFUN (no_bgp_table_map
,
5424 no_bgp_table_map_cmd
,
5425 "no table-map WORD",
5427 "BGP table to RIB route download filter\n"
5428 "Name of the route map\n")
5431 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5432 argv
[idx_word
]->arg
);
5438 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5439 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5440 backdoor$backdoor}]",
5442 "Specify a network to announce via BGP\n"
5447 "Route-map to modify the attributes\n"
5448 "Name of the route map\n"
5449 "Label index to associate with the prefix\n"
5450 "Label index value\n"
5451 "Specify a BGP backdoor route\n")
5453 char addr_prefix_str
[BUFSIZ
];
5458 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5461 vty_out(vty
, "%% Inconsistent address and mask\n");
5462 return CMD_WARNING_CONFIG_FAILED
;
5466 return bgp_static_set(
5467 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5468 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5469 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5472 DEFPY(ipv6_bgp_network
,
5473 ipv6_bgp_network_cmd
,
5474 "[no] network X:X::X:X/M$prefix \
5475 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5477 "Specify a network to announce via BGP\n"
5479 "Route-map to modify the attributes\n"
5480 "Name of the route map\n"
5481 "Label index to associate with the prefix\n"
5482 "Label index value\n")
5484 return bgp_static_set(
5485 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5486 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5489 /* Aggreagete address:
5491 advertise-map Set condition to advertise attribute
5492 as-set Generate AS set path information
5493 attribute-map Set attributes of aggregate
5494 route-map Set parameters of aggregate
5495 summary-only Filter more specific routes from updates
5496 suppress-map Conditionally filter more specific routes from updates
5499 struct bgp_aggregate
{
5500 /* Summary-only flag. */
5501 uint8_t summary_only
;
5503 /* AS set generation. */
5506 /* Route-map for aggregated route. */
5507 struct route_map
*map
;
5509 /* Suppress-count. */
5510 unsigned long count
;
5512 /* SAFI configuration. */
5516 static struct bgp_aggregate
*bgp_aggregate_new(void)
5518 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5521 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5523 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5526 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5527 struct aspath
*aspath
,
5528 struct community
*comm
,
5529 struct ecommunity
*ecomm
,
5530 struct lcommunity
*lcomm
)
5532 static struct aspath
*ae
= NULL
;
5535 ae
= aspath_empty();
5540 if (origin
!= pi
->attr
->origin
)
5543 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5546 if (!community_cmp(pi
->attr
->community
, comm
))
5549 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5552 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5555 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5561 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5562 struct prefix
*p
, uint8_t origin
,
5563 struct aspath
*aspath
,
5564 struct community
*community
,
5565 struct ecommunity
*ecommunity
,
5566 struct lcommunity
*lcommunity
,
5567 uint8_t atomic_aggregate
,
5568 struct bgp_aggregate
*aggregate
)
5570 struct bgp_node
*rn
;
5571 struct bgp_table
*table
;
5572 struct bgp_path_info
*pi
, *orig
, *new;
5574 table
= bgp
->rib
[afi
][safi
];
5576 rn
= bgp_node_get(table
, p
);
5578 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5579 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5580 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5583 if (aggregate
->count
> 0) {
5585 * If the aggregate information has not changed
5586 * no need to re-install it again.
5588 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5589 ecommunity
, lcommunity
)) {
5590 bgp_unlock_node(rn
);
5593 aspath_free(aspath
);
5595 community_free(&community
);
5597 ecommunity_free(&ecommunity
);
5599 lcommunity_free(&lcommunity
);
5605 * Mark the old as unusable
5608 bgp_path_info_delete(rn
, pi
);
5610 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5612 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5613 community
, ecommunity
,
5618 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5620 bgp_path_info_add(rn
, new);
5621 bgp_process(bgp
, rn
, afi
, safi
);
5623 for (pi
= orig
; pi
; pi
= pi
->next
)
5624 if (pi
->peer
== bgp
->peer_self
5625 && pi
->type
== ZEBRA_ROUTE_BGP
5626 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5629 /* Withdraw static BGP route from routing table. */
5631 bgp_path_info_delete(rn
, pi
);
5632 bgp_process(bgp
, rn
, afi
, safi
);
5636 bgp_unlock_node(rn
);
5639 /* Update an aggregate as routes are added/removed from the BGP table */
5640 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5641 struct bgp_path_info
*pinew
, afi_t afi
,
5642 safi_t safi
, struct bgp_path_info
*del
,
5643 struct bgp_aggregate
*aggregate
)
5645 struct bgp_table
*table
;
5646 struct bgp_node
*top
;
5647 struct bgp_node
*rn
;
5649 struct aspath
*aspath
= NULL
;
5650 struct aspath
*asmerge
= NULL
;
5651 struct community
*community
= NULL
;
5652 struct community
*commerge
= NULL
;
5653 struct ecommunity
*ecommunity
= NULL
;
5654 struct ecommunity
*ecommerge
= NULL
;
5655 struct lcommunity
*lcommunity
= NULL
;
5656 struct lcommunity
*lcommerge
= NULL
;
5657 struct bgp_path_info
*pi
;
5658 unsigned long match
= 0;
5659 uint8_t atomic_aggregate
= 0;
5661 /* ORIGIN attribute: If at least one route among routes that are
5662 aggregated has ORIGIN with the value INCOMPLETE, then the
5663 aggregated route must have the ORIGIN attribute with the value
5664 INCOMPLETE. Otherwise, if at least one route among routes that
5665 are aggregated has ORIGIN with the value EGP, then the aggregated
5666 route must have the origin attribute with the value EGP. In all
5667 other case the value of the ORIGIN attribute of the aggregated
5668 route is INTERNAL. */
5669 origin
= BGP_ORIGIN_IGP
;
5671 table
= bgp
->rib
[afi
][safi
];
5673 top
= bgp_node_get(table
, p
);
5674 for (rn
= bgp_node_get(table
, p
); rn
;
5675 rn
= bgp_route_next_until(rn
, top
)) {
5676 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5681 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5682 if (BGP_PATH_HOLDDOWN(pi
))
5685 if (del
&& pi
== del
)
5689 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5690 atomic_aggregate
= 1;
5692 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5696 * summary-only aggregate route suppress
5697 * aggregated route announcements.
5699 if (aggregate
->summary_only
) {
5700 (bgp_path_info_extra_get(pi
))->suppress
++;
5701 bgp_path_info_set_flag(rn
, pi
,
5702 BGP_PATH_ATTR_CHANGED
);
5709 * If at least one route among routes that are
5710 * aggregated has ORIGIN with the value INCOMPLETE,
5711 * then the aggregated route MUST have the ORIGIN
5712 * attribute with the value INCOMPLETE. Otherwise, if
5713 * at least one route among routes that are aggregated
5714 * has ORIGIN with the value EGP, then the aggregated
5715 * route MUST have the ORIGIN attribute with the value
5718 if (origin
< pi
->attr
->origin
)
5719 origin
= pi
->attr
->origin
;
5721 if (!aggregate
->as_set
)
5725 * as-set aggregate route generate origin, as path,
5726 * and community aggregation.
5729 asmerge
= aspath_aggregate(aspath
,
5731 aspath_free(aspath
);
5734 aspath
= aspath_dup(pi
->attr
->aspath
);
5736 if (pi
->attr
->community
) {
5738 commerge
= community_merge(
5739 community
, pi
->attr
->community
);
5741 community_uniq_sort(commerge
);
5742 community_free(&commerge
);
5744 community
= community_dup(
5745 pi
->attr
->community
);
5748 if (pi
->attr
->ecommunity
) {
5750 ecommerge
= ecommunity_merge(
5752 pi
->attr
->ecommunity
);
5754 ecommunity_uniq_sort(ecommerge
);
5755 ecommunity_free(&ecommerge
);
5757 ecommunity
= ecommunity_dup(
5758 pi
->attr
->ecommunity
);
5761 if (pi
->attr
->lcommunity
) {
5763 lcommerge
= lcommunity_merge(
5765 pi
->attr
->lcommunity
);
5767 lcommunity_uniq_sort(lcommerge
);
5768 lcommunity_free(&lcommerge
);
5770 lcommunity
= lcommunity_dup(
5771 pi
->attr
->lcommunity
);
5775 bgp_process(bgp
, rn
, afi
, safi
);
5777 bgp_unlock_node(top
);
5782 if (aggregate
->summary_only
)
5783 (bgp_path_info_extra_get(pinew
))->suppress
++;
5785 if (origin
< pinew
->attr
->origin
)
5786 origin
= pinew
->attr
->origin
;
5788 if (aggregate
->as_set
) {
5790 asmerge
= aspath_aggregate(aspath
,
5791 pinew
->attr
->aspath
);
5792 aspath_free(aspath
);
5795 aspath
= aspath_dup(pinew
->attr
->aspath
);
5797 if (pinew
->attr
->community
) {
5799 commerge
= community_merge(
5801 pinew
->attr
->community
);
5803 community_uniq_sort(commerge
);
5804 community_free(&commerge
);
5806 community
= community_dup(
5807 pinew
->attr
->community
);
5810 if (pinew
->attr
->ecommunity
) {
5812 ecommerge
= ecommunity_merge(
5814 pinew
->attr
->ecommunity
);
5816 ecommunity_uniq_sort(ecommerge
);
5817 ecommunity_free(&ecommerge
);
5819 ecommunity
= ecommunity_dup(
5820 pinew
->attr
->ecommunity
);
5823 if (pinew
->attr
->lcommunity
) {
5825 lcommerge
= lcommunity_merge(
5827 pinew
->attr
->lcommunity
);
5829 lcommunity_uniq_sort(lcommerge
);
5830 lcommunity_free(&lcommerge
);
5832 lcommunity
= lcommunity_dup(
5833 pinew
->attr
->lcommunity
);
5838 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5839 ecommunity
, lcommunity
, atomic_aggregate
,
5842 if (aggregate
->count
== 0) {
5844 aspath_free(aspath
);
5846 community_free(&community
);
5848 ecommunity_free(&ecommunity
);
5850 lcommunity_free(&lcommunity
);
5854 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5855 safi_t safi
, struct bgp_aggregate
*aggregate
)
5857 struct bgp_table
*table
;
5858 struct bgp_node
*top
;
5859 struct bgp_node
*rn
;
5860 struct bgp_path_info
*pi
;
5861 unsigned long match
;
5863 table
= bgp
->rib
[afi
][safi
];
5865 /* If routes exists below this node, generate aggregate routes. */
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
)
5873 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5874 if (BGP_PATH_HOLDDOWN(pi
))
5877 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5880 if (aggregate
->summary_only
&& pi
->extra
) {
5881 pi
->extra
->suppress
--;
5883 if (pi
->extra
->suppress
== 0) {
5884 bgp_path_info_set_flag(
5885 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5892 /* If this node was suppressed, process the change. */
5894 bgp_process(bgp
, rn
, afi
, safi
);
5896 bgp_unlock_node(top
);
5899 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5900 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
5902 struct bgp_node
*child
;
5903 struct bgp_node
*rn
;
5904 struct bgp_aggregate
*aggregate
;
5905 struct bgp_table
*table
;
5907 table
= bgp
->aggregate
[afi
][safi
];
5909 /* No aggregates configured. */
5910 if (bgp_table_top_nolock(table
) == NULL
)
5913 if (p
->prefixlen
== 0)
5916 if (BGP_PATH_HOLDDOWN(pi
))
5919 child
= bgp_node_get(table
, p
);
5921 /* Aggregate address configuration check. */
5922 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5923 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
5924 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5925 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5926 bgp_aggregate_route(bgp
, &rn
->p
, pi
, afi
, safi
, NULL
,
5930 bgp_unlock_node(child
);
5933 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5934 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
5936 struct bgp_node
*child
;
5937 struct bgp_node
*rn
;
5938 struct bgp_aggregate
*aggregate
;
5939 struct bgp_table
*table
;
5941 table
= bgp
->aggregate
[afi
][safi
];
5943 /* No aggregates configured. */
5944 if (bgp_table_top_nolock(table
) == NULL
)
5947 if (p
->prefixlen
== 0)
5950 child
= bgp_node_get(table
, p
);
5952 /* Aggregate address configuration check. */
5953 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5954 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
5955 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5956 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5957 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5961 bgp_unlock_node(child
);
5964 /* Aggregate route attribute. */
5965 #define AGGREGATE_SUMMARY_ONLY 1
5966 #define AGGREGATE_AS_SET 1
5968 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5969 afi_t afi
, safi_t safi
)
5971 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5974 struct bgp_node
*rn
;
5975 struct bgp_aggregate
*aggregate
;
5977 /* Convert string to prefix structure. */
5978 ret
= str2prefix(prefix_str
, &p
);
5980 vty_out(vty
, "Malformed prefix\n");
5981 return CMD_WARNING_CONFIG_FAILED
;
5985 /* Old configuration check. */
5986 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5989 "%% There is no aggregate-address configuration.\n");
5990 return CMD_WARNING_CONFIG_FAILED
;
5993 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
5994 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5995 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
5996 NULL
, NULL
, 0, aggregate
);
5998 /* Unlock aggregate address configuration. */
5999 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6000 bgp_aggregate_free(aggregate
);
6001 bgp_unlock_node(rn
);
6002 bgp_unlock_node(rn
);
6007 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6008 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6010 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6013 struct bgp_node
*rn
;
6014 struct bgp_aggregate
*aggregate
;
6016 /* Convert string to prefix structure. */
6017 ret
= str2prefix(prefix_str
, &p
);
6019 vty_out(vty
, "Malformed prefix\n");
6020 return CMD_WARNING_CONFIG_FAILED
;
6024 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6025 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6026 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6028 return CMD_WARNING_CONFIG_FAILED
;
6031 /* Old configuration check. */
6032 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6034 if (bgp_node_has_bgp_path_info_data(rn
)) {
6035 vty_out(vty
, "There is already same aggregate network.\n");
6036 /* try to remove the old entry */
6037 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6039 vty_out(vty
, "Error deleting aggregate.\n");
6040 bgp_unlock_node(rn
);
6041 return CMD_WARNING_CONFIG_FAILED
;
6045 /* Make aggregate address structure. */
6046 aggregate
= bgp_aggregate_new();
6047 aggregate
->summary_only
= summary_only
;
6048 aggregate
->as_set
= as_set
;
6049 aggregate
->safi
= safi
;
6050 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6052 /* Aggregate address insert into BGP routing table. */
6053 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
6058 DEFUN (aggregate_address
,
6059 aggregate_address_cmd
,
6060 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6061 "Configure BGP aggregate entries\n"
6062 "Aggregate prefix\n"
6063 "Generate AS set path information\n"
6064 "Filter more specific routes from updates\n"
6065 "Filter more specific routes from updates\n"
6066 "Generate AS set path information\n")
6069 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6070 char *prefix
= argv
[idx
]->arg
;
6072 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6074 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6075 ? AGGREGATE_SUMMARY_ONLY
6078 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6079 summary_only
, as_set
);
6082 DEFUN (aggregate_address_mask
,
6083 aggregate_address_mask_cmd
,
6084 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6085 "Configure BGP aggregate entries\n"
6086 "Aggregate address\n"
6088 "Generate AS set path information\n"
6089 "Filter more specific routes from updates\n"
6090 "Filter more specific routes from updates\n"
6091 "Generate AS set path information\n")
6094 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6095 char *prefix
= argv
[idx
]->arg
;
6096 char *mask
= argv
[idx
+ 1]->arg
;
6098 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6100 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6101 ? AGGREGATE_SUMMARY_ONLY
6104 char prefix_str
[BUFSIZ
];
6105 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6108 vty_out(vty
, "%% Inconsistent address and mask\n");
6109 return CMD_WARNING_CONFIG_FAILED
;
6112 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6113 summary_only
, as_set
);
6116 DEFUN (no_aggregate_address
,
6117 no_aggregate_address_cmd
,
6118 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6120 "Configure BGP aggregate entries\n"
6121 "Aggregate prefix\n"
6122 "Generate AS set path information\n"
6123 "Filter more specific routes from updates\n"
6124 "Filter more specific routes from updates\n"
6125 "Generate AS set path information\n")
6128 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6129 char *prefix
= argv
[idx
]->arg
;
6130 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6133 DEFUN (no_aggregate_address_mask
,
6134 no_aggregate_address_mask_cmd
,
6135 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6137 "Configure BGP aggregate entries\n"
6138 "Aggregate address\n"
6140 "Generate AS set path information\n"
6141 "Filter more specific routes from updates\n"
6142 "Filter more specific routes from updates\n"
6143 "Generate AS set path information\n")
6146 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6147 char *prefix
= argv
[idx
]->arg
;
6148 char *mask
= argv
[idx
+ 1]->arg
;
6150 char prefix_str
[BUFSIZ
];
6151 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6154 vty_out(vty
, "%% Inconsistent address and mask\n");
6155 return CMD_WARNING_CONFIG_FAILED
;
6158 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6161 DEFUN (ipv6_aggregate_address
,
6162 ipv6_aggregate_address_cmd
,
6163 "aggregate-address X:X::X:X/M [summary-only]",
6164 "Configure BGP aggregate entries\n"
6165 "Aggregate prefix\n"
6166 "Filter more specific routes from updates\n")
6169 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6170 char *prefix
= argv
[idx
]->arg
;
6171 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6172 ? AGGREGATE_SUMMARY_ONLY
6174 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6178 DEFUN (no_ipv6_aggregate_address
,
6179 no_ipv6_aggregate_address_cmd
,
6180 "no aggregate-address X:X::X:X/M [summary-only]",
6182 "Configure BGP aggregate entries\n"
6183 "Aggregate prefix\n"
6184 "Filter more specific routes from updates\n")
6187 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6188 char *prefix
= argv
[idx
]->arg
;
6189 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6192 /* Redistribute route treatment. */
6193 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6194 const union g_addr
*nexthop
, ifindex_t ifindex
,
6195 enum nexthop_types_t nhtype
, uint32_t metric
,
6196 uint8_t type
, unsigned short instance
,
6199 struct bgp_path_info
*new;
6200 struct bgp_path_info
*bpi
;
6201 struct bgp_path_info rmap_path
;
6202 struct bgp_node
*bn
;
6204 struct attr
*new_attr
;
6207 struct bgp_redist
*red
;
6209 /* Make default attribute. */
6210 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6213 case NEXTHOP_TYPE_IFINDEX
:
6215 case NEXTHOP_TYPE_IPV4
:
6216 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6217 attr
.nexthop
= nexthop
->ipv4
;
6219 case NEXTHOP_TYPE_IPV6
:
6220 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6221 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6222 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6224 case NEXTHOP_TYPE_BLACKHOLE
:
6225 switch (p
->family
) {
6227 attr
.nexthop
.s_addr
= INADDR_ANY
;
6230 memset(&attr
.mp_nexthop_global
, 0,
6231 sizeof(attr
.mp_nexthop_global
));
6232 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6237 attr
.nh_ifindex
= ifindex
;
6240 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6243 afi
= family2afi(p
->family
);
6245 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6247 struct attr attr_new
;
6249 /* Copy attribute for modification. */
6250 bgp_attr_dup(&attr_new
, &attr
);
6252 if (red
->redist_metric_flag
)
6253 attr_new
.med
= red
->redist_metric
;
6255 /* Apply route-map. */
6256 if (red
->rmap
.name
) {
6257 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6258 rmap_path
.peer
= bgp
->peer_self
;
6259 rmap_path
.attr
= &attr_new
;
6261 SET_FLAG(bgp
->peer_self
->rmap_type
,
6262 PEER_RMAP_TYPE_REDISTRIBUTE
);
6264 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6267 bgp
->peer_self
->rmap_type
= 0;
6269 if (ret
== RMAP_DENYMATCH
) {
6270 /* Free uninterned attribute. */
6271 bgp_attr_flush(&attr_new
);
6273 /* Unintern original. */
6274 aspath_unintern(&attr
.aspath
);
6275 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6280 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6281 bgp_attr_add_gshut_community(&attr_new
);
6283 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6284 SAFI_UNICAST
, p
, NULL
);
6286 new_attr
= bgp_attr_intern(&attr_new
);
6288 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6290 if (bpi
->peer
== bgp
->peer_self
6291 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6295 /* Ensure the (source route) type is updated. */
6297 if (attrhash_cmp(bpi
->attr
, new_attr
)
6298 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6299 bgp_attr_unintern(&new_attr
);
6300 aspath_unintern(&attr
.aspath
);
6301 bgp_unlock_node(bn
);
6304 /* The attribute is changed. */
6305 bgp_path_info_set_flag(bn
, bpi
,
6306 BGP_PATH_ATTR_CHANGED
);
6308 /* Rewrite BGP route information. */
6309 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6310 bgp_path_info_restore(bn
, bpi
);
6312 bgp_aggregate_decrement(
6313 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6314 bgp_attr_unintern(&bpi
->attr
);
6315 bpi
->attr
= new_attr
;
6316 bpi
->uptime
= bgp_clock();
6318 /* Process change. */
6319 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6321 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6322 bgp_unlock_node(bn
);
6323 aspath_unintern(&attr
.aspath
);
6325 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6327 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6329 vpn_leak_from_vrf_update(
6330 bgp_get_default(), bgp
, bpi
);
6336 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6337 bgp
->peer_self
, new_attr
, bn
);
6338 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6340 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6341 bgp_path_info_add(bn
, new);
6342 bgp_unlock_node(bn
);
6343 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6345 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6346 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6348 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6352 /* Unintern original. */
6353 aspath_unintern(&attr
.aspath
);
6356 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6357 unsigned short instance
)
6360 struct bgp_node
*rn
;
6361 struct bgp_path_info
*pi
;
6362 struct bgp_redist
*red
;
6364 afi
= family2afi(p
->family
);
6366 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6368 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6369 SAFI_UNICAST
, p
, NULL
);
6371 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6372 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6376 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6377 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6379 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6382 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6383 bgp_path_info_delete(rn
, pi
);
6384 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6386 bgp_unlock_node(rn
);
6390 /* Withdraw specified route type's route. */
6391 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6392 unsigned short instance
)
6394 struct bgp_node
*rn
;
6395 struct bgp_path_info
*pi
;
6396 struct bgp_table
*table
;
6398 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6400 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6401 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6402 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6403 && pi
->instance
== instance
)
6407 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6408 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6410 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6413 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6415 bgp_path_info_delete(rn
, pi
);
6416 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6421 /* Static function to display route. */
6422 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6429 if (p
->family
== AF_INET
) {
6433 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6436 json_object_string_add(json
, "prefix",
6437 inet_ntop(p
->family
,
6440 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6441 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6442 json_object_string_add(json
, "network", buf2
);
6444 } else if (p
->family
== AF_ETHERNET
) {
6445 prefix2str(p
, buf
, PREFIX_STRLEN
);
6446 len
= vty_out(vty
, "%s", buf
);
6447 } else if (p
->family
== AF_EVPN
) {
6451 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6454 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6455 } else if (p
->family
== AF_FLOWSPEC
) {
6456 route_vty_out_flowspec(vty
, p
, NULL
,
6458 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6459 NLRI_STRING_FORMAT_MIN
, json
);
6464 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6467 json_object_string_add(json
, "prefix",
6468 inet_ntop(p
->family
,
6471 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6472 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6473 json_object_string_add(json
, "network", buf2
);
6480 vty_out(vty
, "\n%*s", 20, " ");
6482 vty_out(vty
, "%*s", len
, " ");
6486 enum bgp_display_type
{
6490 /* Print the short form route status for a bgp_path_info */
6491 static void route_vty_short_status_out(struct vty
*vty
,
6492 struct bgp_path_info
*path
,
6493 json_object
*json_path
)
6497 /* Route status display. */
6498 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6499 json_object_boolean_true_add(json_path
, "removed");
6501 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6502 json_object_boolean_true_add(json_path
, "stale");
6504 if (path
->extra
&& path
->extra
->suppress
)
6505 json_object_boolean_true_add(json_path
, "suppressed");
6507 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6508 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6509 json_object_boolean_true_add(json_path
, "valid");
6512 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6513 json_object_boolean_true_add(json_path
, "history");
6515 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6516 json_object_boolean_true_add(json_path
, "damped");
6518 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6519 json_object_boolean_true_add(json_path
, "bestpath");
6521 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6522 json_object_boolean_true_add(json_path
, "multipath");
6524 /* Internal route. */
6525 if ((path
->peer
->as
)
6526 && (path
->peer
->as
== path
->peer
->local_as
))
6527 json_object_string_add(json_path
, "pathFrom",
6530 json_object_string_add(json_path
, "pathFrom",
6536 /* Route status display. */
6537 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6539 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6541 else if (path
->extra
&& path
->extra
->suppress
)
6543 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6544 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6550 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6552 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6554 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6556 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6561 /* Internal route. */
6562 if (path
->peer
&& (path
->peer
->as
)
6563 && (path
->peer
->as
== path
->peer
->local_as
))
6569 /* called from terminal list command */
6570 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6571 struct bgp_path_info
*path
, int display
, safi_t safi
,
6572 json_object
*json_paths
)
6575 json_object
*json_path
= NULL
;
6576 json_object
*json_nexthops
= NULL
;
6577 json_object
*json_nexthop_global
= NULL
;
6578 json_object
*json_nexthop_ll
= NULL
;
6579 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6581 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6582 bool nexthop_othervrf
= false;
6583 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6584 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6587 json_path
= json_object_new_object();
6589 /* short status lead text */
6590 route_vty_short_status_out(vty
, path
, json_path
);
6593 /* print prefix and mask */
6595 route_vty_out_route(p
, vty
, json_path
);
6597 vty_out(vty
, "%*s", 17, " ");
6599 route_vty_out_route(p
, vty
, json_path
);
6602 /* Print attribute */
6606 json_object_array_add(json_paths
, json_path
);
6614 * If vrf id of nexthop is different from that of prefix,
6615 * set up printable string to append
6617 if (path
->extra
&& path
->extra
->bgp_orig
) {
6618 const char *self
= "";
6623 nexthop_othervrf
= true;
6624 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6626 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6627 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6628 "@%s%s", VRFID_NONE_STR
, self
);
6630 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6631 path
->extra
->bgp_orig
->vrf_id
, self
);
6633 if (path
->extra
->bgp_orig
->inst_type
6634 != BGP_INSTANCE_TYPE_DEFAULT
)
6636 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6638 const char *self
= "";
6643 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6647 * For ENCAP and EVPN routes, nexthop address family is not
6648 * neccessarily the same as the prefix address family.
6649 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6650 * EVPN routes are also exchanged with a MP nexthop. Currently,
6652 * is only IPv4, the value will be present in either
6654 * attr->mp_nexthop_global_in
6656 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6659 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6663 sprintf(nexthop
, "%s",
6664 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6668 sprintf(nexthop
, "%s",
6669 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6673 sprintf(nexthop
, "?");
6678 json_nexthop_global
= json_object_new_object();
6680 json_object_string_add(json_nexthop_global
, "afi",
6681 (af
== AF_INET
) ? "ip" : "ipv6");
6682 json_object_string_add(json_nexthop_global
,
6683 (af
== AF_INET
) ? "ip" : "ipv6",
6685 json_object_boolean_true_add(json_nexthop_global
,
6688 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6689 } else if (safi
== SAFI_EVPN
) {
6691 json_nexthop_global
= json_object_new_object();
6693 json_object_string_add(json_nexthop_global
, "ip",
6694 inet_ntoa(attr
->nexthop
));
6695 json_object_string_add(json_nexthop_global
, "afi",
6697 json_object_boolean_true_add(json_nexthop_global
,
6700 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6702 } else if (safi
== SAFI_FLOWSPEC
) {
6703 if (attr
->nexthop
.s_addr
!= 0) {
6705 json_nexthop_global
= json_object_new_object();
6706 json_object_string_add(
6707 json_nexthop_global
, "ip",
6708 inet_ntoa(attr
->nexthop
));
6709 json_object_string_add(json_nexthop_global
,
6711 json_object_boolean_true_add(
6712 json_nexthop_global
,
6715 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6718 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6720 json_nexthop_global
= json_object_new_object();
6722 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6723 json_object_string_add(
6724 json_nexthop_global
, "ip",
6725 inet_ntoa(attr
->mp_nexthop_global_in
));
6727 json_object_string_add(
6728 json_nexthop_global
, "ip",
6729 inet_ntoa(attr
->nexthop
));
6731 json_object_string_add(json_nexthop_global
, "afi",
6733 json_object_boolean_true_add(json_nexthop_global
,
6738 snprintf(buf
, sizeof(buf
), "%s%s",
6739 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6740 vty_out(vty
, "%-16s", buf
);
6745 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6750 json_nexthop_global
= json_object_new_object();
6751 json_object_string_add(
6752 json_nexthop_global
, "ip",
6753 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6755 json_object_string_add(json_nexthop_global
, "afi",
6757 json_object_string_add(json_nexthop_global
, "scope",
6760 /* We display both LL & GL if both have been
6762 if ((attr
->mp_nexthop_len
== 32)
6763 || (path
->peer
->conf_if
)) {
6764 json_nexthop_ll
= json_object_new_object();
6765 json_object_string_add(
6766 json_nexthop_ll
, "ip",
6768 &attr
->mp_nexthop_local
, buf
,
6770 json_object_string_add(json_nexthop_ll
, "afi",
6772 json_object_string_add(json_nexthop_ll
, "scope",
6775 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6776 &attr
->mp_nexthop_local
)
6778 && !attr
->mp_nexthop_prefer_global
)
6779 json_object_boolean_true_add(
6780 json_nexthop_ll
, "used");
6782 json_object_boolean_true_add(
6783 json_nexthop_global
, "used");
6785 json_object_boolean_true_add(
6786 json_nexthop_global
, "used");
6788 /* Display LL if LL/Global both in table unless
6789 * prefer-global is set */
6790 if (((attr
->mp_nexthop_len
== 32)
6791 && !attr
->mp_nexthop_prefer_global
)
6792 || (path
->peer
->conf_if
)) {
6793 if (path
->peer
->conf_if
) {
6794 len
= vty_out(vty
, "%s",
6795 path
->peer
->conf_if
);
6796 len
= 16 - len
; /* len of IPv6
6802 vty_out(vty
, "\n%*s", 36, " ");
6804 vty_out(vty
, "%*s", len
, " ");
6810 &attr
->mp_nexthop_local
,
6816 vty_out(vty
, "\n%*s", 36, " ");
6818 vty_out(vty
, "%*s", len
, " ");
6824 &attr
->mp_nexthop_global
, buf
,
6830 vty_out(vty
, "\n%*s", 36, " ");
6832 vty_out(vty
, "%*s", len
, " ");
6838 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6842 * Adding "metric" field to match with corresponding
6843 * CLI. "med" will be deprecated in future.
6845 json_object_int_add(json_path
, "med", attr
->med
);
6846 json_object_int_add(json_path
, "metric", attr
->med
);
6848 vty_out(vty
, "%10u", attr
->med
);
6849 else if (!json_paths
)
6853 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6857 * Adding "locPrf" field to match with corresponding
6858 * CLI. "localPref" will be deprecated in future.
6860 json_object_int_add(json_path
, "localpref",
6862 json_object_int_add(json_path
, "locPrf",
6865 vty_out(vty
, "%7u", attr
->local_pref
);
6866 else if (!json_paths
)
6870 json_object_int_add(json_path
, "weight", attr
->weight
);
6872 vty_out(vty
, "%7u ", attr
->weight
);
6876 json_object_string_add(
6877 json_path
, "peerId",
6878 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6886 * Adding "path" field to match with corresponding
6887 * CLI. "aspath" will be deprecated in future.
6889 json_object_string_add(json_path
, "aspath",
6891 json_object_string_add(json_path
, "path",
6894 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6899 json_object_string_add(json_path
, "origin",
6900 bgp_origin_long_str
[attr
->origin
]);
6902 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6906 json_object_boolean_true_add(json_path
,
6907 "announceNexthopSelf");
6908 if (nexthop_othervrf
) {
6909 json_object_string_add(json_path
, "nhVrfName",
6912 json_object_int_add(json_path
, "nhVrfId",
6913 ((nexthop_vrfid
== VRF_UNKNOWN
)
6915 : (int)nexthop_vrfid
));
6920 if (json_nexthop_global
|| json_nexthop_ll
) {
6921 json_nexthops
= json_object_new_array();
6923 if (json_nexthop_global
)
6924 json_object_array_add(json_nexthops
,
6925 json_nexthop_global
);
6927 if (json_nexthop_ll
)
6928 json_object_array_add(json_nexthops
,
6931 json_object_object_add(json_path
, "nexthops",
6935 json_object_array_add(json_paths
, json_path
);
6939 /* prints an additional line, indented, with VNC info, if
6941 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6942 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
6947 /* called from terminal list command */
6948 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6949 safi_t safi
, bool use_json
, json_object
*json_ar
)
6951 json_object
*json_status
= NULL
;
6952 json_object
*json_net
= NULL
;
6955 /* Route status display. */
6957 json_status
= json_object_new_object();
6958 json_net
= json_object_new_object();
6965 /* print prefix and mask */
6967 json_object_string_add(
6968 json_net
, "addrPrefix",
6969 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6970 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
6971 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6972 json_object_string_add(json_net
, "network", buf2
);
6974 route_vty_out_route(p
, vty
, NULL
);
6976 /* Print attribute */
6979 if (p
->family
== AF_INET
6980 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6981 || safi
== SAFI_EVPN
6982 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6983 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6984 || safi
== SAFI_EVPN
)
6985 json_object_string_add(
6986 json_net
, "nextHop",
6988 attr
->mp_nexthop_global_in
));
6990 json_object_string_add(
6991 json_net
, "nextHop",
6992 inet_ntoa(attr
->nexthop
));
6993 } else if (p
->family
== AF_INET6
6994 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6997 json_object_string_add(
6998 json_net
, "nextHopGlobal",
7000 &attr
->mp_nexthop_global
, buf
,
7005 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7006 json_object_int_add(json_net
, "metric",
7009 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7012 * Adding "locPrf" field to match with
7013 * corresponding CLI. "localPref" will be
7014 * deprecated in future.
7016 json_object_int_add(json_net
, "localPref",
7018 json_object_int_add(json_net
, "locPrf",
7022 json_object_int_add(json_net
, "weight", attr
->weight
);
7028 * Adding "path" field to match with
7029 * corresponding CLI. "localPref" will be
7030 * deprecated in future.
7032 json_object_string_add(json_net
, "asPath",
7034 json_object_string_add(json_net
, "path",
7039 json_object_string_add(json_net
, "bgpOriginCode",
7040 bgp_origin_str
[attr
->origin
]);
7042 if (p
->family
== AF_INET
7043 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7044 || safi
== SAFI_EVPN
7045 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7046 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7047 || safi
== SAFI_EVPN
)
7048 vty_out(vty
, "%-16s",
7050 attr
->mp_nexthop_global_in
));
7052 vty_out(vty
, "%-16s",
7053 inet_ntoa(attr
->nexthop
));
7054 } else if (p
->family
== AF_INET6
7055 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7062 &attr
->mp_nexthop_global
, buf
,
7066 vty_out(vty
, "\n%*s", 36, " ");
7068 vty_out(vty
, "%*s", len
, " ");
7071 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7072 vty_out(vty
, "%10u", attr
->med
);
7076 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7077 vty_out(vty
, "%7u", attr
->local_pref
);
7081 vty_out(vty
, "%7u ", attr
->weight
);
7085 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7088 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7092 json_object_boolean_true_add(json_status
, "*");
7093 json_object_boolean_true_add(json_status
, ">");
7094 json_object_object_add(json_net
, "appliedStatusSymbols",
7096 char buf_cut
[BUFSIZ
];
7097 json_object_object_add(
7099 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7105 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7106 struct bgp_path_info
*path
, int display
, safi_t safi
,
7109 json_object
*json_out
= NULL
;
7111 mpls_label_t label
= MPLS_INVALID_LABEL
;
7117 json_out
= json_object_new_object();
7119 /* short status lead text */
7120 route_vty_short_status_out(vty
, path
, json_out
);
7122 /* print prefix and mask */
7125 route_vty_out_route(p
, vty
, NULL
);
7127 vty_out(vty
, "%*s", 17, " ");
7130 /* Print attribute */
7133 if (((p
->family
== AF_INET
)
7134 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7135 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7136 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7137 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7138 || safi
== SAFI_EVPN
) {
7140 json_object_string_add(
7141 json_out
, "mpNexthopGlobalIn",
7143 attr
->mp_nexthop_global_in
));
7145 vty_out(vty
, "%-16s",
7147 attr
->mp_nexthop_global_in
));
7150 json_object_string_add(
7151 json_out
, "nexthop",
7152 inet_ntoa(attr
->nexthop
));
7154 vty_out(vty
, "%-16s",
7155 inet_ntoa(attr
->nexthop
));
7157 } else if (((p
->family
== AF_INET6
)
7158 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7159 || (safi
== SAFI_EVPN
7160 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7161 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7165 if (attr
->mp_nexthop_len
7166 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7168 json_object_string_add(
7169 json_out
, "mpNexthopGlobalIn",
7172 &attr
->mp_nexthop_global
,
7173 buf_a
, sizeof(buf_a
)));
7178 &attr
->mp_nexthop_global
,
7179 buf_a
, sizeof(buf_a
)));
7180 } else if (attr
->mp_nexthop_len
7181 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7184 &attr
->mp_nexthop_global
,
7185 buf_a
, sizeof(buf_a
));
7187 &attr
->mp_nexthop_local
,
7188 buf_b
, sizeof(buf_b
));
7189 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7190 json_object_string_add(
7192 "mpNexthopGlobalLocal", buf_c
);
7194 vty_out(vty
, "%s(%s)",
7197 &attr
->mp_nexthop_global
,
7198 buf_a
, sizeof(buf_a
)),
7201 &attr
->mp_nexthop_local
,
7202 buf_b
, sizeof(buf_b
)));
7207 label
= decode_label(&path
->extra
->label
[0]);
7209 if (bgp_is_valid_label(&label
)) {
7211 json_object_int_add(json_out
, "notag", label
);
7212 json_object_array_add(json
, json_out
);
7214 vty_out(vty
, "notag/%d", label
);
7220 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7221 struct bgp_path_info
*path
, int display
,
7222 json_object
*json_paths
)
7226 json_object
*json_path
= NULL
;
7229 json_path
= json_object_new_object();
7234 /* short status lead text */
7235 route_vty_short_status_out(vty
, path
, json_path
);
7237 /* print prefix and mask */
7239 route_vty_out_route(p
, vty
, NULL
);
7241 vty_out(vty
, "%*s", 17, " ");
7243 /* Print attribute */
7247 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7251 vty_out(vty
, "%-16s",
7252 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7256 vty_out(vty
, "%s(%s)",
7257 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7259 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7266 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7268 vty_out(vty
, "%s", str
);
7269 XFREE(MTYPE_TMP
, str
);
7271 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7273 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7274 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7277 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7280 if (attr
->ecommunity
) {
7282 struct ecommunity_val
*routermac
= ecommunity_lookup(
7283 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7284 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7286 mac
= ecom_mac2str((char *)routermac
->val
);
7288 vty_out(vty
, "/%s", (char *)mac
);
7289 XFREE(MTYPE_TMP
, mac
);
7297 /* dampening route */
7298 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7299 struct bgp_path_info
*path
, int display
,
7300 safi_t safi
, bool use_json
, json_object
*json
)
7304 char timebuf
[BGP_UPTIME_LEN
];
7306 /* short status lead text */
7307 route_vty_short_status_out(vty
, path
, json
);
7309 /* print prefix and mask */
7312 route_vty_out_route(p
, vty
, NULL
);
7314 vty_out(vty
, "%*s", 17, " ");
7317 len
= vty_out(vty
, "%s", path
->peer
->host
);
7321 vty_out(vty
, "\n%*s", 34, " ");
7324 json_object_int_add(json
, "peerHost", len
);
7326 vty_out(vty
, "%*s", len
, " ");
7330 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7334 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7335 BGP_UPTIME_LEN
, use_json
,
7338 /* Print attribute */
7344 json_object_string_add(json
, "asPath",
7347 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7352 json_object_string_add(json
, "origin",
7353 bgp_origin_str
[attr
->origin
]);
7355 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7362 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7363 struct bgp_path_info
*path
, int display
,
7364 safi_t safi
, bool use_json
, json_object
*json
)
7367 struct bgp_damp_info
*bdi
;
7368 char timebuf
[BGP_UPTIME_LEN
];
7374 bdi
= path
->extra
->damp_info
;
7376 /* short status lead text */
7377 route_vty_short_status_out(vty
, path
, json
);
7379 /* print prefix and mask */
7382 route_vty_out_route(p
, vty
, NULL
);
7384 vty_out(vty
, "%*s", 17, " ");
7387 len
= vty_out(vty
, "%s", path
->peer
->host
);
7391 vty_out(vty
, "\n%*s", 33, " ");
7394 json_object_int_add(json
, "peerHost", len
);
7396 vty_out(vty
, "%*s", len
, " ");
7399 len
= vty_out(vty
, "%d", bdi
->flap
);
7406 json_object_int_add(json
, "bdiFlap", len
);
7408 vty_out(vty
, "%*s", len
, " ");
7412 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7415 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7416 BGP_UPTIME_LEN
, 0, NULL
));
7418 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7419 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7421 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7422 BGP_UPTIME_LEN
, use_json
, json
);
7425 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7430 vty_out(vty
, "%*s ", 8, " ");
7433 /* Print attribute */
7439 json_object_string_add(json
, "asPath",
7442 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7447 json_object_string_add(json
, "origin",
7448 bgp_origin_str
[attr
->origin
]);
7450 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7456 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7457 int *first
, const char *header
,
7458 json_object
*json_adv_to
)
7460 char buf1
[INET6_ADDRSTRLEN
];
7461 json_object
*json_peer
= NULL
;
7464 /* 'advertised-to' is a dictionary of peers we have advertised
7466 * prefix too. The key is the peer's IP or swpX, the value is
7468 * hostname if we know it and "" if not.
7470 json_peer
= json_object_new_object();
7473 json_object_string_add(json_peer
, "hostname",
7477 json_object_object_add(json_adv_to
, peer
->conf_if
,
7480 json_object_object_add(
7482 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7486 vty_out(vty
, "%s", header
);
7491 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7493 vty_out(vty
, " %s(%s)", peer
->hostname
,
7496 vty_out(vty
, " %s(%s)", peer
->hostname
,
7497 sockunion2str(&peer
->su
, buf1
,
7501 vty_out(vty
, " %s", peer
->conf_if
);
7504 sockunion2str(&peer
->su
, buf1
,
7510 static void route_vty_out_tx_ids(struct vty
*vty
,
7511 struct bgp_addpath_info_data
*d
)
7515 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7516 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7517 d
->addpath_tx_id
[i
],
7518 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7522 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7523 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7524 json_object
*json_paths
)
7526 char buf
[INET6_ADDRSTRLEN
];
7528 char buf2
[EVPN_ROUTE_STRLEN
];
7530 int sockunion_vty_out(struct vty
*, union sockunion
*);
7532 json_object
*json_bestpath
= NULL
;
7533 json_object
*json_cluster_list
= NULL
;
7534 json_object
*json_cluster_list_list
= NULL
;
7535 json_object
*json_ext_community
= NULL
;
7536 json_object
*json_last_update
= NULL
;
7537 json_object
*json_pmsi
= NULL
;
7538 json_object
*json_nexthop_global
= NULL
;
7539 json_object
*json_nexthop_ll
= NULL
;
7540 json_object
*json_nexthops
= NULL
;
7541 json_object
*json_path
= NULL
;
7542 json_object
*json_peer
= NULL
;
7543 json_object
*json_string
= NULL
;
7544 json_object
*json_adv_to
= NULL
;
7546 struct listnode
*node
, *nnode
;
7548 int addpath_capable
;
7550 unsigned int first_as
;
7552 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7556 json_path
= json_object_new_object();
7557 json_peer
= json_object_new_object();
7558 json_nexthop_global
= json_object_new_object();
7561 if (!json_paths
&& safi
== SAFI_EVPN
) {
7564 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7565 vty_out(vty
, " Route %s", buf2
);
7567 if (path
->extra
&& path
->extra
->num_labels
) {
7568 bgp_evpn_label2str(path
->extra
->label
,
7569 path
->extra
->num_labels
, tag_buf
,
7571 vty_out(vty
, " VNI %s", tag_buf
);
7574 if (path
->extra
&& path
->extra
->parent
) {
7575 struct bgp_path_info
*parent_ri
;
7576 struct bgp_node
*rn
, *prn
;
7578 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7579 rn
= parent_ri
->net
;
7580 if (rn
&& rn
->prn
) {
7582 vty_out(vty
, " Imported from %s:%s\n",
7584 (struct prefix_rd
*)&prn
->p
,
7585 buf1
, sizeof(buf1
)),
7594 /* Line1 display AS-path, Aggregator */
7597 if (!attr
->aspath
->json
)
7598 aspath_str_update(attr
->aspath
, true);
7599 json_object_lock(attr
->aspath
->json
);
7600 json_object_object_add(json_path
, "aspath",
7601 attr
->aspath
->json
);
7603 if (attr
->aspath
->segments
)
7604 aspath_print_vty(vty
, " %s",
7607 vty_out(vty
, " Local");
7611 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7613 json_object_boolean_true_add(json_path
,
7616 vty_out(vty
, ", (removed)");
7619 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7621 json_object_boolean_true_add(json_path
,
7624 vty_out(vty
, ", (stale)");
7627 if (CHECK_FLAG(attr
->flag
,
7628 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7630 json_object_int_add(json_path
, "aggregatorAs",
7631 attr
->aggregator_as
);
7632 json_object_string_add(
7633 json_path
, "aggregatorId",
7634 inet_ntoa(attr
->aggregator_addr
));
7636 vty_out(vty
, ", (aggregated by %u %s)",
7637 attr
->aggregator_as
,
7638 inet_ntoa(attr
->aggregator_addr
));
7642 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7643 PEER_FLAG_REFLECTOR_CLIENT
)) {
7645 json_object_boolean_true_add(
7646 json_path
, "rxedFromRrClient");
7648 vty_out(vty
, ", (Received from a RR-client)");
7651 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7652 PEER_FLAG_RSERVER_CLIENT
)) {
7654 json_object_boolean_true_add(
7655 json_path
, "rxedFromRsClient");
7657 vty_out(vty
, ", (Received from a RS-client)");
7660 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7662 json_object_boolean_true_add(
7663 json_path
, "dampeningHistoryEntry");
7665 vty_out(vty
, ", (history entry)");
7666 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
7668 json_object_boolean_true_add(
7669 json_path
, "dampeningSuppressed");
7671 vty_out(vty
, ", (suppressed due to dampening)");
7677 /* Line2 display Next-hop, Neighbor, Router-id */
7678 /* Display the nexthop */
7679 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7680 || p
->family
== AF_EVPN
)
7681 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7682 || safi
== SAFI_EVPN
7683 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7684 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7685 || safi
== SAFI_EVPN
) {
7687 json_object_string_add(
7688 json_nexthop_global
, "ip",
7690 attr
->mp_nexthop_global_in
));
7694 attr
->mp_nexthop_global_in
));
7697 json_object_string_add(
7698 json_nexthop_global
, "ip",
7699 inet_ntoa(attr
->nexthop
));
7702 inet_ntoa(attr
->nexthop
));
7706 json_object_string_add(json_nexthop_global
,
7710 json_object_string_add(
7711 json_nexthop_global
, "ip",
7713 &attr
->mp_nexthop_global
, buf
,
7715 json_object_string_add(json_nexthop_global
,
7717 json_object_string_add(json_nexthop_global
,
7722 &attr
->mp_nexthop_global
, buf
,
7727 /* Display the IGP cost or 'inaccessible' */
7728 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
7730 json_object_boolean_false_add(
7731 json_nexthop_global
, "accessible");
7733 vty_out(vty
, " (inaccessible)");
7735 if (path
->extra
&& path
->extra
->igpmetric
) {
7737 json_object_int_add(
7738 json_nexthop_global
, "metric",
7739 path
->extra
->igpmetric
);
7741 vty_out(vty
, " (metric %u)",
7742 path
->extra
->igpmetric
);
7745 /* IGP cost is 0, display this only for json */
7748 json_object_int_add(json_nexthop_global
,
7753 json_object_boolean_true_add(
7754 json_nexthop_global
, "accessible");
7757 /* Display peer "from" output */
7758 /* This path was originated locally */
7759 if (path
->peer
== bgp
->peer_self
) {
7761 if (safi
== SAFI_EVPN
7762 || (p
->family
== AF_INET
7763 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7765 json_object_string_add(
7766 json_peer
, "peerId", "0.0.0.0");
7768 vty_out(vty
, " from 0.0.0.0 ");
7771 json_object_string_add(json_peer
,
7774 vty_out(vty
, " from :: ");
7778 json_object_string_add(
7779 json_peer
, "routerId",
7780 inet_ntoa(bgp
->router_id
));
7782 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7785 /* We RXed this path from one of our peers */
7789 json_object_string_add(
7790 json_peer
, "peerId",
7791 sockunion2str(&path
->peer
->su
, buf
,
7793 json_object_string_add(
7794 json_peer
, "routerId",
7796 &path
->peer
->remote_id
, buf1
,
7799 if (path
->peer
->hostname
)
7800 json_object_string_add(
7801 json_peer
, "hostname",
7802 path
->peer
->hostname
);
7804 if (path
->peer
->domainname
)
7805 json_object_string_add(
7806 json_peer
, "domainname",
7807 path
->peer
->domainname
);
7809 if (path
->peer
->conf_if
)
7810 json_object_string_add(
7811 json_peer
, "interface",
7812 path
->peer
->conf_if
);
7814 if (path
->peer
->conf_if
) {
7815 if (path
->peer
->hostname
7818 BGP_FLAG_SHOW_HOSTNAME
))
7819 vty_out(vty
, " from %s(%s)",
7820 path
->peer
->hostname
,
7821 path
->peer
->conf_if
);
7823 vty_out(vty
, " from %s",
7824 path
->peer
->conf_if
);
7826 if (path
->peer
->hostname
7829 BGP_FLAG_SHOW_HOSTNAME
))
7830 vty_out(vty
, " from %s(%s)",
7831 path
->peer
->hostname
,
7834 vty_out(vty
, " from %s",
7842 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7843 vty_out(vty
, " (%s)",
7844 inet_ntoa(attr
->originator_id
));
7846 vty_out(vty
, " (%s)",
7849 &path
->peer
->remote_id
,
7850 buf1
, sizeof(buf1
)));
7855 * Note when vrfid of nexthop is different from that of prefix
7857 if (path
->extra
&& path
->extra
->bgp_orig
) {
7858 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7863 if (path
->extra
->bgp_orig
->inst_type
7864 == BGP_INSTANCE_TYPE_DEFAULT
)
7866 vn
= VRF_DEFAULT_NAME
;
7868 vn
= path
->extra
->bgp_orig
->name
;
7870 json_object_string_add(json_path
, "nhVrfName",
7873 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7874 json_object_int_add(json_path
,
7877 json_object_int_add(json_path
,
7878 "nhVrfId", (int)nexthop_vrfid
);
7881 if (nexthop_vrfid
== VRF_UNKNOWN
)
7882 vty_out(vty
, " vrf ?");
7884 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7890 json_object_boolean_true_add(json_path
,
7891 "announceNexthopSelf");
7893 vty_out(vty
, " announce-nh-self");
7900 /* display the link-local nexthop */
7901 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7903 json_nexthop_ll
= json_object_new_object();
7904 json_object_string_add(
7905 json_nexthop_ll
, "ip",
7907 &attr
->mp_nexthop_local
, buf
,
7909 json_object_string_add(json_nexthop_ll
, "afi",
7911 json_object_string_add(json_nexthop_ll
, "scope",
7914 json_object_boolean_true_add(json_nexthop_ll
,
7917 if (!attr
->mp_nexthop_prefer_global
)
7918 json_object_boolean_true_add(
7919 json_nexthop_ll
, "used");
7921 json_object_boolean_true_add(
7922 json_nexthop_global
, "used");
7924 vty_out(vty
, " (%s) %s\n",
7926 &attr
->mp_nexthop_local
, buf
,
7928 attr
->mp_nexthop_prefer_global
7933 /* If we do not have a link-local nexthop then we must flag the
7937 json_object_boolean_true_add(
7938 json_nexthop_global
, "used");
7941 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7942 * Int/Ext/Local, Atomic, best */
7944 json_object_string_add(
7945 json_path
, "origin",
7946 bgp_origin_long_str
[attr
->origin
]);
7948 vty_out(vty
, " Origin %s",
7949 bgp_origin_long_str
[attr
->origin
]);
7951 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7955 * Adding "metric" field to match with
7956 * corresponding CLI. "med" will be
7957 * deprecated in future.
7959 json_object_int_add(json_path
, "med",
7961 json_object_int_add(json_path
, "metric",
7964 vty_out(vty
, ", metric %u", attr
->med
);
7967 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7969 json_object_int_add(json_path
, "localpref",
7972 vty_out(vty
, ", localpref %u",
7976 if (attr
->weight
!= 0) {
7978 json_object_int_add(json_path
, "weight",
7981 vty_out(vty
, ", weight %u", attr
->weight
);
7984 if (attr
->tag
!= 0) {
7986 json_object_int_add(json_path
, "tag",
7989 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7993 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
7995 json_object_boolean_false_add(json_path
,
7998 vty_out(vty
, ", invalid");
7999 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8001 json_object_boolean_true_add(json_path
,
8004 vty_out(vty
, ", valid");
8007 if (path
->peer
!= bgp
->peer_self
) {
8008 if (path
->peer
->as
== path
->peer
->local_as
) {
8009 if (CHECK_FLAG(bgp
->config
,
8010 BGP_CONFIG_CONFEDERATION
)) {
8012 json_object_string_add(
8017 ", confed-internal");
8020 json_object_string_add(
8024 vty_out(vty
, ", internal");
8027 if (bgp_confederation_peers_check(
8028 bgp
, path
->peer
->as
)) {
8030 json_object_string_add(
8035 ", confed-external");
8038 json_object_string_add(
8042 vty_out(vty
, ", external");
8045 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8047 json_object_boolean_true_add(json_path
,
8049 json_object_boolean_true_add(json_path
,
8052 vty_out(vty
, ", aggregated, local");
8054 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8056 json_object_boolean_true_add(json_path
,
8059 vty_out(vty
, ", sourced");
8062 json_object_boolean_true_add(json_path
,
8064 json_object_boolean_true_add(json_path
,
8067 vty_out(vty
, ", sourced, local");
8071 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8073 json_object_boolean_true_add(json_path
,
8076 vty_out(vty
, ", atomic-aggregate");
8079 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8080 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8081 && bgp_path_info_mpath_count(path
))) {
8083 json_object_boolean_true_add(json_path
,
8086 vty_out(vty
, ", multipath");
8089 // Mark the bestpath(s)
8090 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8091 first_as
= aspath_get_first_as(attr
->aspath
);
8096 json_object_new_object();
8097 json_object_int_add(json_bestpath
,
8098 "bestpathFromAs", first_as
);
8101 vty_out(vty
, ", bestpath-from-AS %u",
8105 ", bestpath-from-AS Local");
8109 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8113 json_object_new_object();
8114 json_object_boolean_true_add(json_bestpath
,
8117 vty_out(vty
, ", best");
8121 json_object_object_add(json_path
, "bestpath",
8127 /* Line 4 display Community */
8128 if (attr
->community
) {
8130 if (!attr
->community
->json
)
8131 community_str(attr
->community
, true);
8132 json_object_lock(attr
->community
->json
);
8133 json_object_object_add(json_path
, "community",
8134 attr
->community
->json
);
8136 vty_out(vty
, " Community: %s\n",
8137 attr
->community
->str
);
8141 /* Line 5 display Extended-community */
8142 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8144 json_ext_community
= json_object_new_object();
8145 json_object_string_add(json_ext_community
,
8147 attr
->ecommunity
->str
);
8148 json_object_object_add(json_path
,
8149 "extendedCommunity",
8150 json_ext_community
);
8152 vty_out(vty
, " Extended Community: %s\n",
8153 attr
->ecommunity
->str
);
8157 /* Line 6 display Large community */
8158 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8160 if (!attr
->lcommunity
->json
)
8161 lcommunity_str(attr
->lcommunity
, true);
8162 json_object_lock(attr
->lcommunity
->json
);
8163 json_object_object_add(json_path
,
8165 attr
->lcommunity
->json
);
8167 vty_out(vty
, " Large Community: %s\n",
8168 attr
->lcommunity
->str
);
8172 /* Line 7 display Originator, Cluster-id */
8173 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8174 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8176 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8178 json_object_string_add(
8179 json_path
, "originatorId",
8180 inet_ntoa(attr
->originator_id
));
8182 vty_out(vty
, " Originator: %s",
8183 inet_ntoa(attr
->originator_id
));
8186 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8191 json_object_new_object();
8192 json_cluster_list_list
=
8193 json_object_new_array();
8196 i
< attr
->cluster
->length
/ 4;
8198 json_string
= json_object_new_string(
8202 json_object_array_add(
8203 json_cluster_list_list
,
8207 /* struct cluster_list does not have
8209 * aspath and community do. Add this
8212 json_object_string_add(json_cluster_list,
8213 "string", attr->cluster->str);
8215 json_object_object_add(
8216 json_cluster_list
, "list",
8217 json_cluster_list_list
);
8218 json_object_object_add(
8219 json_path
, "clusterList",
8222 vty_out(vty
, ", Cluster list: ");
8225 i
< attr
->cluster
->length
/ 4;
8239 if (path
->extra
&& path
->extra
->damp_info
)
8240 bgp_damp_info_vty(vty
, path
, json_path
);
8243 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8244 && safi
!= SAFI_EVPN
) {
8245 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8248 json_object_int_add(json_path
, "remoteLabel",
8251 vty_out(vty
, " Remote label: %d\n", label
);
8255 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8257 json_object_int_add(json_path
, "labelIndex",
8260 vty_out(vty
, " Label Index: %d\n",
8264 /* Line 8 display Addpath IDs */
8265 if (path
->addpath_rx_id
8266 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8268 json_object_int_add(json_path
, "addpathRxId",
8269 path
->addpath_rx_id
);
8271 /* Keep backwards compatibility with the old API
8272 * by putting TX All's ID in the old field
8274 json_object_int_add(
8275 json_path
, "addpathTxId",
8276 path
->tx_addpath
.addpath_tx_id
8279 /* ... but create a specific field for each
8282 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8283 json_object_int_add(
8285 bgp_addpath_names(i
)
8291 vty_out(vty
, " AddPath ID: RX %u, ",
8292 path
->addpath_rx_id
);
8294 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8298 /* If we used addpath to TX a non-bestpath we need to display
8299 * "Advertised to" on a path-by-path basis
8301 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8304 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8306 bgp_addpath_encode_tx(peer
, afi
, safi
);
8307 has_adj
= bgp_adj_out_lookup(
8309 bgp_addpath_id_for_peer(
8311 &path
->tx_addpath
));
8313 if ((addpath_capable
&& has_adj
)
8314 || (!addpath_capable
&& has_adj
8315 && CHECK_FLAG(path
->flags
,
8316 BGP_PATH_SELECTED
))) {
8317 if (json_path
&& !json_adv_to
)
8319 json_object_new_object();
8321 route_vty_out_advertised_to(
8330 json_object_object_add(json_path
,
8341 /* Line 9 display Uptime */
8342 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8344 json_last_update
= json_object_new_object();
8345 json_object_int_add(json_last_update
, "epoch", tbuf
);
8346 json_object_string_add(json_last_update
, "string",
8348 json_object_object_add(json_path
, "lastUpdate",
8351 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8353 /* Line 10 display PMSI tunnel attribute, if present */
8354 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8355 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8356 attr
->pmsi_tnl_type
,
8357 PMSI_TNLTYPE_STR_DEFAULT
);
8360 json_pmsi
= json_object_new_object();
8361 json_object_string_add(json_pmsi
,
8363 json_object_object_add(json_path
, "pmsi",
8366 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8372 /* We've constructed the json object for this path, add it to the json
8376 if (json_nexthop_global
|| json_nexthop_ll
) {
8377 json_nexthops
= json_object_new_array();
8379 if (json_nexthop_global
)
8380 json_object_array_add(json_nexthops
,
8381 json_nexthop_global
);
8383 if (json_nexthop_ll
)
8384 json_object_array_add(json_nexthops
,
8387 json_object_object_add(json_path
, "nexthops",
8391 json_object_object_add(json_path
, "peer", json_peer
);
8392 json_object_array_add(json_paths
, json_path
);
8397 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8398 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8399 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8401 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8402 const char *prefix_list_str
, afi_t afi
,
8403 safi_t safi
, enum bgp_show_type type
);
8404 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8405 const char *filter
, afi_t afi
, safi_t safi
,
8406 enum bgp_show_type type
);
8407 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8408 const char *rmap_str
, afi_t afi
, safi_t safi
,
8409 enum bgp_show_type type
);
8410 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8411 const char *com
, int exact
, afi_t afi
,
8413 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8414 const char *prefix
, afi_t afi
, safi_t safi
,
8415 enum bgp_show_type type
);
8416 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8417 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8418 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8419 const char *comstr
, int exact
, afi_t afi
,
8420 safi_t safi
, bool use_json
);
8423 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8424 struct bgp_table
*table
, enum bgp_show_type type
,
8425 void *output_arg
, bool use_json
, char *rd
,
8426 int is_last
, unsigned long *output_cum
,
8427 unsigned long *total_cum
,
8428 unsigned long *json_header_depth
)
8430 struct bgp_path_info
*pi
;
8431 struct bgp_node
*rn
;
8434 unsigned long output_count
= 0;
8435 unsigned long total_count
= 0;
8438 json_object
*json_paths
= NULL
;
8441 if (output_cum
&& *output_cum
!= 0)
8444 if (use_json
&& !*json_header_depth
) {
8446 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8447 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8448 " \"localAS\": %u,\n \"routes\": { ",
8449 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8450 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8453 table
->version
, inet_ntoa(bgp
->router_id
),
8454 bgp
->default_local_pref
, bgp
->as
);
8455 *json_header_depth
= 2;
8457 vty_out(vty
, " \"routeDistinguishers\" : {");
8458 ++*json_header_depth
;
8462 if (use_json
&& rd
) {
8463 vty_out(vty
, " \"%s\" : { ", rd
);
8466 /* Start processing of routes. */
8467 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8468 pi
= bgp_node_get_bgp_path_info(rn
);
8474 json_paths
= json_object_new_array();
8478 for (; pi
; pi
= pi
->next
) {
8480 if (type
== bgp_show_type_flap_statistics
8481 || type
== bgp_show_type_flap_neighbor
8482 || type
== bgp_show_type_dampend_paths
8483 || type
== bgp_show_type_damp_neighbor
) {
8484 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8487 if (type
== bgp_show_type_regexp
) {
8488 regex_t
*regex
= output_arg
;
8490 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8494 if (type
== bgp_show_type_prefix_list
) {
8495 struct prefix_list
*plist
= output_arg
;
8497 if (prefix_list_apply(plist
, &rn
->p
)
8501 if (type
== bgp_show_type_filter_list
) {
8502 struct as_list
*as_list
= output_arg
;
8504 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8505 != AS_FILTER_PERMIT
)
8508 if (type
== bgp_show_type_route_map
) {
8509 struct route_map
*rmap
= output_arg
;
8510 struct bgp_path_info path
;
8511 struct attr dummy_attr
;
8514 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8516 path
.peer
= pi
->peer
;
8517 path
.attr
= &dummy_attr
;
8519 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8521 if (ret
== RMAP_DENYMATCH
)
8524 if (type
== bgp_show_type_neighbor
8525 || type
== bgp_show_type_flap_neighbor
8526 || type
== bgp_show_type_damp_neighbor
) {
8527 union sockunion
*su
= output_arg
;
8529 if (pi
->peer
== NULL
8530 || pi
->peer
->su_remote
== NULL
8531 || !sockunion_same(pi
->peer
->su_remote
, su
))
8534 if (type
== bgp_show_type_cidr_only
) {
8535 uint32_t destination
;
8537 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8538 if (IN_CLASSC(destination
)
8539 && rn
->p
.prefixlen
== 24)
8541 if (IN_CLASSB(destination
)
8542 && rn
->p
.prefixlen
== 16)
8544 if (IN_CLASSA(destination
)
8545 && rn
->p
.prefixlen
== 8)
8548 if (type
== bgp_show_type_prefix_longer
) {
8550 if (!prefix_match(p
, &rn
->p
))
8553 if (type
== bgp_show_type_community_all
) {
8554 if (!pi
->attr
->community
)
8557 if (type
== bgp_show_type_community
) {
8558 struct community
*com
= output_arg
;
8560 if (!pi
->attr
->community
8561 || !community_match(pi
->attr
->community
,
8565 if (type
== bgp_show_type_community_exact
) {
8566 struct community
*com
= output_arg
;
8568 if (!pi
->attr
->community
8569 || !community_cmp(pi
->attr
->community
, com
))
8572 if (type
== bgp_show_type_community_list
) {
8573 struct community_list
*list
= output_arg
;
8575 if (!community_list_match(pi
->attr
->community
,
8579 if (type
== bgp_show_type_community_list_exact
) {
8580 struct community_list
*list
= output_arg
;
8582 if (!community_list_exact_match(
8583 pi
->attr
->community
, list
))
8586 if (type
== bgp_show_type_lcommunity
) {
8587 struct lcommunity
*lcom
= output_arg
;
8589 if (!pi
->attr
->lcommunity
8590 || !lcommunity_match(pi
->attr
->lcommunity
,
8594 if (type
== bgp_show_type_lcommunity_list
) {
8595 struct community_list
*list
= output_arg
;
8597 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8601 if (type
== bgp_show_type_lcommunity_all
) {
8602 if (!pi
->attr
->lcommunity
)
8605 if (type
== bgp_show_type_dampend_paths
8606 || type
== bgp_show_type_damp_neighbor
) {
8607 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8608 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8612 if (!use_json
&& header
) {
8613 vty_out(vty
, "BGP table version is %" PRIu64
8614 ", local router ID is %s, vrf id ",
8616 inet_ntoa(bgp
->router_id
));
8617 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8618 vty_out(vty
, "%s", VRFID_NONE_STR
);
8620 vty_out(vty
, "%u", bgp
->vrf_id
);
8622 vty_out(vty
, "Default local pref %u, ",
8623 bgp
->default_local_pref
);
8624 vty_out(vty
, "local AS %u\n", bgp
->as
);
8625 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8626 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8627 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8628 if (type
== bgp_show_type_dampend_paths
8629 || type
== bgp_show_type_damp_neighbor
)
8630 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8631 else if (type
== bgp_show_type_flap_statistics
8632 || type
== bgp_show_type_flap_neighbor
)
8633 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8635 vty_out(vty
, BGP_SHOW_HEADER
);
8638 if (rd
!= NULL
&& !display
&& !output_count
) {
8641 "Route Distinguisher: %s\n",
8644 if (type
== bgp_show_type_dampend_paths
8645 || type
== bgp_show_type_damp_neighbor
)
8646 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
8647 safi
, use_json
, json_paths
);
8648 else if (type
== bgp_show_type_flap_statistics
8649 || type
== bgp_show_type_flap_neighbor
)
8650 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
8651 safi
, use_json
, json_paths
);
8653 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
8665 if (p
->family
== AF_FLOWSPEC
) {
8666 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
8668 bgp_fs_nlri_get_string((unsigned char *)
8669 p
->u
.prefix_flowspec
.ptr
,
8670 p
->u
.prefix_flowspec
8673 NLRI_STRING_FORMAT_MIN
,
8676 vty_out(vty
, "\"%s/%d\": ",
8678 p
->u
.prefix_flowspec
.prefixlen
);
8680 vty_out(vty
, ",\"%s/%d\": ",
8682 p
->u
.prefix_flowspec
.prefixlen
);
8684 prefix2str(p
, buf2
, sizeof(buf2
));
8686 vty_out(vty
, "\"%s\": ", buf2
);
8688 vty_out(vty
, ",\"%s\": ", buf2
);
8691 json_object_to_json_string(json_paths
));
8692 json_object_free(json_paths
);
8699 output_count
+= *output_cum
;
8700 *output_cum
= output_count
;
8703 total_count
+= *total_cum
;
8704 *total_cum
= total_count
;
8708 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8712 for (i
= 0; i
< *json_header_depth
; ++i
)
8713 vty_out(vty
, " } ");
8717 /* No route is displayed */
8718 if (output_count
== 0) {
8719 if (type
== bgp_show_type_normal
)
8721 "No BGP prefixes displayed, %ld exist\n",
8725 "\nDisplayed %ld routes and %ld total paths\n",
8726 output_count
, total_count
);
8733 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8734 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8735 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8737 struct bgp_node
*rn
, *next
;
8738 unsigned long output_cum
= 0;
8739 unsigned long total_cum
= 0;
8740 unsigned long json_header_depth
= 0;
8741 struct bgp_table
*itable
;
8744 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8746 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8747 next
= bgp_route_next(rn
);
8748 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8751 itable
= bgp_node_get_bgp_table_info(rn
);
8752 if (itable
!= NULL
) {
8753 struct prefix_rd prd
;
8754 char rd
[RD_ADDRSTRLEN
];
8756 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8757 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8758 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
8759 use_json
, rd
, next
== NULL
, &output_cum
,
8760 &total_cum
, &json_header_depth
);
8766 if (output_cum
== 0)
8767 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8771 "\nDisplayed %ld routes and %ld total paths\n",
8772 output_cum
, total_cum
);
8776 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8777 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8779 struct bgp_table
*table
;
8780 unsigned long json_header_depth
= 0;
8783 bgp
= bgp_get_default();
8788 vty_out(vty
, "No BGP process is configured\n");
8790 vty_out(vty
, "{}\n");
8794 table
= bgp
->rib
[afi
][safi
];
8795 /* use MPLS and ENCAP specific shows until they are merged */
8796 if (safi
== SAFI_MPLS_VPN
) {
8797 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8798 output_arg
, use_json
);
8801 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8802 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8803 output_arg
, use_json
,
8806 /* labeled-unicast routes live in the unicast table */
8807 else if (safi
== SAFI_LABELED_UNICAST
)
8808 safi
= SAFI_UNICAST
;
8810 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8811 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8814 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8815 safi_t safi
, bool use_json
)
8817 struct listnode
*node
, *nnode
;
8820 bool route_output
= false;
8823 vty_out(vty
, "{\n");
8825 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8826 route_output
= true;
8829 vty_out(vty
, ",\n");
8833 vty_out(vty
, "\"%s\":",
8834 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8838 vty_out(vty
, "\nInstance %s:\n",
8839 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8843 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8848 vty_out(vty
, "}\n");
8849 else if (!route_output
)
8850 vty_out(vty
, "%% BGP instance not found\n");
8853 /* Header of detailed BGP route information */
8854 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8855 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8856 afi_t afi
, safi_t safi
, json_object
*json
)
8858 struct bgp_path_info
*pi
;
8861 struct listnode
*node
, *nnode
;
8862 char buf1
[RD_ADDRSTRLEN
];
8863 char buf2
[INET6_ADDRSTRLEN
];
8864 char buf3
[EVPN_ROUTE_STRLEN
];
8865 char prefix_str
[BUFSIZ
];
8870 int route_filter_translated_v4
= 0;
8871 int route_filter_v4
= 0;
8872 int route_filter_translated_v6
= 0;
8873 int route_filter_v6
= 0;
8876 int accept_own_nexthop
= 0;
8879 int no_advertise
= 0;
8883 int has_valid_label
= 0;
8884 mpls_label_t label
= 0;
8885 json_object
*json_adv_to
= NULL
;
8888 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8890 if (has_valid_label
)
8891 label
= label_pton(&rn
->local_label
);
8894 if (has_valid_label
)
8895 json_object_int_add(json
, "localLabel", label
);
8897 json_object_string_add(
8899 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8901 if (safi
== SAFI_EVPN
)
8902 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8903 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8906 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8907 buf3
, sizeof(buf3
)));
8909 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8910 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8911 ? prefix_rd2str(prd
, buf1
,
8914 safi
== SAFI_MPLS_VPN
? ":" : "",
8915 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8919 if (has_valid_label
)
8920 vty_out(vty
, "Local label: %d\n", label
);
8921 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8922 vty_out(vty
, "not allocated\n");
8925 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
8927 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
8929 if (pi
->extra
&& pi
->extra
->suppress
)
8932 if (pi
->attr
->community
== NULL
)
8935 no_advertise
+= community_include(
8936 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
8937 no_export
+= community_include(pi
->attr
->community
,
8938 COMMUNITY_NO_EXPORT
);
8939 local_as
+= community_include(pi
->attr
->community
,
8940 COMMUNITY_LOCAL_AS
);
8941 accept_own
+= community_include(pi
->attr
->community
,
8942 COMMUNITY_ACCEPT_OWN
);
8943 route_filter_translated_v4
+= community_include(
8944 pi
->attr
->community
,
8945 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
8946 route_filter_translated_v6
+= community_include(
8947 pi
->attr
->community
,
8948 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
8949 route_filter_v4
+= community_include(
8950 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
8951 route_filter_v6
+= community_include(
8952 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
8953 llgr_stale
+= community_include(pi
->attr
->community
,
8954 COMMUNITY_LLGR_STALE
);
8955 no_llgr
+= community_include(pi
->attr
->community
,
8957 accept_own_nexthop
+=
8958 community_include(pi
->attr
->community
,
8959 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
8960 blackhole
+= community_include(pi
->attr
->community
,
8961 COMMUNITY_BLACKHOLE
);
8962 no_peer
+= community_include(pi
->attr
->community
,
8968 vty_out(vty
, "Paths: (%d available", count
);
8970 vty_out(vty
, ", best #%d", best
);
8971 if (safi
== SAFI_UNICAST
)
8972 vty_out(vty
, ", table %s",
8974 == BGP_INSTANCE_TYPE_DEFAULT
)
8978 vty_out(vty
, ", no best path");
8982 ", accept own local route exported and imported in different VRF");
8983 else if (route_filter_translated_v4
)
8985 ", mark translated RTs for VPNv4 route filtering");
8986 else if (route_filter_v4
)
8988 ", attach RT as-is for VPNv4 route filtering");
8989 else if (route_filter_translated_v6
)
8991 ", mark translated RTs for VPNv6 route filtering");
8992 else if (route_filter_v6
)
8994 ", attach RT as-is for VPNv6 route filtering");
8995 else if (llgr_stale
)
8997 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9000 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9001 else if (accept_own_nexthop
)
9003 ", accept local nexthop");
9005 vty_out(vty
, ", inform peer to blackhole prefix");
9007 vty_out(vty
, ", not advertised to EBGP peer");
9008 else if (no_advertise
)
9009 vty_out(vty
, ", not advertised to any peer");
9011 vty_out(vty
, ", not advertised outside local AS");
9014 ", inform EBGP peer not to advertise to their EBGP peers");
9018 ", Advertisements suppressed by an aggregate.");
9019 vty_out(vty
, ")\n");
9022 /* If we are not using addpath then we can display Advertised to and
9024 * show what peers we advertised the bestpath to. If we are using
9026 * though then we must display Advertised to on a path-by-path basis. */
9027 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9028 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9029 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9030 if (json
&& !json_adv_to
)
9031 json_adv_to
= json_object_new_object();
9033 route_vty_out_advertised_to(
9035 " Advertised to non peer-group peers:\n ",
9042 json_object_object_add(json
, "advertisedTo",
9047 vty_out(vty
, " Not advertised to any peer");
9053 /* Display specified route of BGP table. */
9054 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9055 struct bgp_table
*rib
, const char *ip_str
,
9056 afi_t afi
, safi_t safi
,
9057 struct prefix_rd
*prd
, int prefix_check
,
9058 enum bgp_path_type pathtype
, bool use_json
)
9063 struct prefix match
;
9064 struct bgp_node
*rn
;
9065 struct bgp_node
*rm
;
9066 struct bgp_path_info
*pi
;
9067 struct bgp_table
*table
;
9068 json_object
*json
= NULL
;
9069 json_object
*json_paths
= NULL
;
9071 /* Check IP address argument. */
9072 ret
= str2prefix(ip_str
, &match
);
9074 vty_out(vty
, "address is malformed\n");
9078 match
.family
= afi2family(afi
);
9081 json
= json_object_new_object();
9082 json_paths
= json_object_new_array();
9085 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9086 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9087 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9089 table
= bgp_node_get_bgp_table_info(rn
);
9095 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9099 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9100 bgp_unlock_node(rm
);
9104 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9107 route_vty_out_detail_header(
9109 (struct prefix_rd
*)&rn
->p
,
9110 AFI_IP
, safi
, json
);
9115 if (pathtype
== BGP_PATH_SHOW_ALL
9116 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9117 && CHECK_FLAG(pi
->flags
,
9119 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9120 && (CHECK_FLAG(pi
->flags
,
9122 || CHECK_FLAG(pi
->flags
,
9123 BGP_PATH_SELECTED
))))
9124 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9129 bgp_unlock_node(rm
);
9131 } else if (safi
== SAFI_FLOWSPEC
) {
9132 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9133 &match
, prefix_check
,
9140 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9142 || rn
->p
.prefixlen
== match
.prefixlen
) {
9143 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9146 route_vty_out_detail_header(
9147 vty
, bgp
, rn
, NULL
, afi
,
9153 if (pathtype
== BGP_PATH_SHOW_ALL
9155 == BGP_PATH_SHOW_BESTPATH
9160 == BGP_PATH_SHOW_MULTIPATH
9166 BGP_PATH_SELECTED
))))
9167 route_vty_out_detail(
9168 vty
, bgp
, &rn
->p
, pi
,
9169 afi
, safi
, json_paths
);
9173 bgp_unlock_node(rn
);
9179 json_object_object_add(json
, "paths", json_paths
);
9181 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9182 json
, JSON_C_TO_STRING_PRETTY
));
9183 json_object_free(json
);
9186 vty_out(vty
, "%% Network not in table\n");
9194 /* Display specified route of Main RIB */
9195 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9196 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9197 int prefix_check
, enum bgp_path_type pathtype
,
9201 bgp
= bgp_get_default();
9204 vty_out(vty
, "No BGP process is configured\n");
9206 vty_out(vty
, "{}\n");
9211 /* labeled-unicast routes live in the unicast table */
9212 if (safi
== SAFI_LABELED_UNICAST
)
9213 safi
= SAFI_UNICAST
;
9215 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9216 afi
, safi
, prd
, prefix_check
, pathtype
,
9220 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9221 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9224 struct lcommunity
*lcom
;
9230 b
= buffer_new(1024);
9231 for (i
= 0; i
< argc
; i
++) {
9233 buffer_putc(b
, ' ');
9235 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9237 buffer_putstr(b
, argv
[i
]->arg
);
9241 buffer_putc(b
, '\0');
9243 str
= buffer_getstr(b
);
9246 lcom
= lcommunity_str2com(str
);
9247 XFREE(MTYPE_TMP
, str
);
9249 vty_out(vty
, "%% Large-community malformed\n");
9253 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9257 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9258 const char *lcom
, afi_t afi
, safi_t safi
,
9261 struct community_list
*list
;
9263 list
= community_list_lookup(bgp_clist
, lcom
,
9264 LARGE_COMMUNITY_LIST_MASTER
);
9266 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9271 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9275 DEFUN (show_ip_bgp_large_community_list
,
9276 show_ip_bgp_large_community_list_cmd
,
9277 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9281 BGP_INSTANCE_HELP_STR
9283 BGP_SAFI_WITH_LABEL_HELP_STR
9284 "Display routes matching the large-community-list\n"
9285 "large-community-list number\n"
9286 "large-community-list name\n"
9290 afi_t afi
= AFI_IP6
;
9291 safi_t safi
= SAFI_UNICAST
;
9294 if (argv_find(argv
, argc
, "ip", &idx
))
9296 if (argv_find(argv
, argc
, "view", &idx
)
9297 || argv_find(argv
, argc
, "vrf", &idx
))
9298 vrf
= argv
[++idx
]->arg
;
9299 if (argv_find(argv
, argc
, "ipv4", &idx
)
9300 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9301 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9302 if (argv_find(argv
, argc
, "unicast", &idx
)
9303 || argv_find(argv
, argc
, "multicast", &idx
))
9304 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9307 bool uj
= use_json(argc
, argv
);
9309 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9311 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9315 argv_find(argv
, argc
, "large-community-list", &idx
);
9316 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9319 DEFUN (show_ip_bgp_large_community
,
9320 show_ip_bgp_large_community_cmd
,
9321 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9325 BGP_INSTANCE_HELP_STR
9327 BGP_SAFI_WITH_LABEL_HELP_STR
9328 "Display routes matching the large-communities\n"
9329 "List of large-community numbers\n"
9333 afi_t afi
= AFI_IP6
;
9334 safi_t safi
= SAFI_UNICAST
;
9337 if (argv_find(argv
, argc
, "ip", &idx
))
9339 if (argv_find(argv
, argc
, "view", &idx
)
9340 || argv_find(argv
, argc
, "vrf", &idx
))
9341 vrf
= argv
[++idx
]->arg
;
9342 if (argv_find(argv
, argc
, "ipv4", &idx
)
9343 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9344 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9345 if (argv_find(argv
, argc
, "unicast", &idx
)
9346 || argv_find(argv
, argc
, "multicast", &idx
))
9347 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9350 bool uj
= use_json(argc
, argv
);
9352 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9354 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9358 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9359 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9361 return bgp_show(vty
, bgp
, afi
, safi
,
9362 bgp_show_type_lcommunity_all
, NULL
, uj
);
9365 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9369 /* BGP route print out function without JSON */
9372 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9373 <dampening <parameters>\
9378 |community-list <(1-500)|WORD> [exact-match]\
9379 |A.B.C.D/M longer-prefixes\
9380 |X:X::X:X/M longer-prefixes\
9385 BGP_INSTANCE_HELP_STR
9387 BGP_SAFI_WITH_LABEL_HELP_STR
9388 "Display detailed information about dampening\n"
9389 "Display detail of configured dampening parameters\n"
9390 "Display routes matching the route-map\n"
9391 "A route-map to match on\n"
9392 "Display routes conforming to the prefix-list\n"
9393 "Prefix-list name\n"
9394 "Display routes conforming to the filter-list\n"
9395 "Regular expression access list name\n"
9396 "BGP RIB advertisement statistics\n"
9397 "Display routes matching the community-list\n"
9398 "community-list number\n"
9399 "community-list name\n"
9400 "Exact match of the communities\n"
9402 "Display route and more specific routes\n"
9404 "Display route and more specific routes\n")
9406 afi_t afi
= AFI_IP6
;
9407 safi_t safi
= SAFI_UNICAST
;
9408 int exact_match
= 0;
9409 struct bgp
*bgp
= NULL
;
9412 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9417 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9418 if (argv_find(argv
, argc
, "parameters", &idx
))
9419 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9422 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9423 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9424 safi
, bgp_show_type_prefix_list
);
9426 if (argv_find(argv
, argc
, "filter-list", &idx
))
9427 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9428 safi
, bgp_show_type_filter_list
);
9430 if (argv_find(argv
, argc
, "statistics", &idx
))
9431 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9433 if (argv_find(argv
, argc
, "route-map", &idx
))
9434 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9435 safi
, bgp_show_type_route_map
);
9437 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9438 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9439 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9441 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9442 exact_match
, afi
, safi
);
9445 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9446 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9447 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9449 bgp_show_type_prefix_longer
);
9454 /* BGP route print out function with JSON */
9455 DEFUN (show_ip_bgp_json
,
9456 show_ip_bgp_json_cmd
,
9457 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9459 |dampening <flap-statistics|dampened-paths>\
9460 |community [AA:NN|local-AS|no-advertise|no-export\
9461 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9462 |accept-own|accept-own-nexthop|route-filter-v6\
9463 |route-filter-v4|route-filter-translated-v6\
9464 |route-filter-translated-v4] [exact-match]\
9469 BGP_INSTANCE_HELP_STR
9471 BGP_SAFI_WITH_LABEL_HELP_STR
9472 "Display only routes with non-natural netmasks\n"
9473 "Display detailed information about dampening\n"
9474 "Display flap statistics of routes\n"
9475 "Display paths suppressed due to dampening\n"
9476 "Display routes matching the communities\n"
9478 "Do not send outside local AS (well-known community)\n"
9479 "Do not advertise to any peer (well-known community)\n"
9480 "Do not export to next AS (well-known community)\n"
9481 "Graceful shutdown (well-known community)\n"
9482 "Do not export to any peer (well-known community)\n"
9483 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9484 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9485 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9486 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9487 "Should accept VPN route with local nexthop (well-known community)\n"
9488 "RT VPNv6 route filtering (well-known community)\n"
9489 "RT VPNv4 route filtering (well-known community)\n"
9490 "RT translated VPNv6 route filtering (well-known community)\n"
9491 "RT translated VPNv4 route filtering (well-known community)\n"
9492 "Exact match of the communities\n"
9495 afi_t afi
= AFI_IP6
;
9496 safi_t safi
= SAFI_UNICAST
;
9497 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9498 struct bgp
*bgp
= NULL
;
9500 int exact_match
= 0;
9501 bool uj
= use_json(argc
, argv
);
9506 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9511 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9512 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9515 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9516 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9517 return bgp_show(vty
, bgp
, afi
, safi
,
9518 bgp_show_type_dampend_paths
, NULL
, uj
);
9519 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9520 return bgp_show(vty
, bgp
, afi
, safi
,
9521 bgp_show_type_flap_statistics
, NULL
,
9525 if (argv_find(argv
, argc
, "community", &idx
)) {
9526 char *maybecomm
= idx
+ 1 < argc
? argv
[idx
+ 1]->text
: NULL
;
9527 char *community
= NULL
;
9529 if (maybecomm
&& !strmatch(maybecomm
, "json")
9530 && !strmatch(maybecomm
, "exact-match"))
9531 community
= maybecomm
;
9533 if (argv_find(argv
, argc
, "exact-match", &idx
))
9537 return bgp_show_community(vty
, bgp
, community
,
9538 exact_match
, afi
, safi
, uj
);
9540 return (bgp_show(vty
, bgp
, afi
, safi
,
9541 bgp_show_type_community_all
, NULL
,
9545 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9548 DEFUN (show_ip_bgp_route
,
9549 show_ip_bgp_route_cmd
,
9550 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9551 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9555 BGP_INSTANCE_HELP_STR
9557 BGP_SAFI_WITH_LABEL_HELP_STR
9558 "Network in the BGP routing table to display\n"
9560 "Network in the BGP routing table to display\n"
9562 "Display only the bestpath\n"
9563 "Display only multipaths\n"
9566 int prefix_check
= 0;
9568 afi_t afi
= AFI_IP6
;
9569 safi_t safi
= SAFI_UNICAST
;
9570 char *prefix
= NULL
;
9571 struct bgp
*bgp
= NULL
;
9572 enum bgp_path_type path_type
;
9573 bool uj
= use_json(argc
, argv
);
9577 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9584 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9588 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9589 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9590 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9592 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9593 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9596 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9597 && afi
!= AFI_IP6
) {
9599 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9602 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9605 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9609 prefix
= argv
[idx
]->arg
;
9611 /* [<bestpath|multipath>] */
9612 if (argv_find(argv
, argc
, "bestpath", &idx
))
9613 path_type
= BGP_PATH_SHOW_BESTPATH
;
9614 else if (argv_find(argv
, argc
, "multipath", &idx
))
9615 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9617 path_type
= BGP_PATH_SHOW_ALL
;
9619 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9623 DEFUN (show_ip_bgp_regexp
,
9624 show_ip_bgp_regexp_cmd
,
9625 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9629 BGP_INSTANCE_HELP_STR
9631 BGP_SAFI_WITH_LABEL_HELP_STR
9632 "Display routes matching the AS path regular expression\n"
9633 "A regular-expression to match the BGP AS paths\n")
9635 afi_t afi
= AFI_IP6
;
9636 safi_t safi
= SAFI_UNICAST
;
9637 struct bgp
*bgp
= NULL
;
9640 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9645 // get index of regex
9646 argv_find(argv
, argc
, "regexp", &idx
);
9649 char *regstr
= argv_concat(argv
, argc
, idx
);
9650 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9651 bgp_show_type_regexp
);
9652 XFREE(MTYPE_TMP
, regstr
);
9656 DEFUN (show_ip_bgp_instance_all
,
9657 show_ip_bgp_instance_all_cmd
,
9658 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9662 BGP_INSTANCE_ALL_HELP_STR
9664 BGP_SAFI_WITH_LABEL_HELP_STR
9668 safi_t safi
= SAFI_UNICAST
;
9669 struct bgp
*bgp
= NULL
;
9671 bool uj
= use_json(argc
, argv
);
9676 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9681 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9685 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9686 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9691 regex
= bgp_regcomp(regstr
);
9693 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9697 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9698 bgp_regex_free(regex
);
9702 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9703 const char *prefix_list_str
, afi_t afi
,
9704 safi_t safi
, enum bgp_show_type type
)
9706 struct prefix_list
*plist
;
9708 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9709 if (plist
== NULL
) {
9710 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9715 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9718 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9719 const char *filter
, afi_t afi
, safi_t safi
,
9720 enum bgp_show_type type
)
9722 struct as_list
*as_list
;
9724 as_list
= as_list_lookup(filter
);
9725 if (as_list
== NULL
) {
9726 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9731 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9734 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9735 const char *rmap_str
, afi_t afi
, safi_t safi
,
9736 enum bgp_show_type type
)
9738 struct route_map
*rmap
;
9740 rmap
= route_map_lookup_by_name(rmap_str
);
9742 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9746 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9749 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9750 const char *comstr
, int exact
, afi_t afi
,
9751 safi_t safi
, bool use_json
)
9753 struct community
*com
;
9756 com
= community_str2com(comstr
);
9758 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9762 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9763 (exact
? bgp_show_type_community_exact
9764 : bgp_show_type_community
),
9766 community_free(&com
);
9771 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9772 const char *com
, int exact
, afi_t afi
,
9775 struct community_list
*list
;
9777 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9779 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9783 return bgp_show(vty
, bgp
, afi
, safi
,
9784 (exact
? bgp_show_type_community_list_exact
9785 : bgp_show_type_community_list
),
9789 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9790 const char *prefix
, afi_t afi
, safi_t safi
,
9791 enum bgp_show_type type
)
9798 ret
= str2prefix(prefix
, p
);
9800 vty_out(vty
, "%% Malformed Prefix\n");
9804 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9809 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9810 const char *ip_str
, bool use_json
)
9816 /* Get peer sockunion. */
9817 ret
= str2sockunion(ip_str
, &su
);
9819 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9821 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9825 json_object
*json_no
= NULL
;
9826 json_no
= json_object_new_object();
9827 json_object_string_add(
9829 "malformedAddressOrName",
9831 vty_out(vty
, "%s\n",
9832 json_object_to_json_string_ext(
9834 JSON_C_TO_STRING_PRETTY
));
9835 json_object_free(json_no
);
9838 "%% Malformed address or name: %s\n",
9846 /* Peer structure lookup. */
9847 peer
= peer_lookup(bgp
, &su
);
9850 json_object
*json_no
= NULL
;
9851 json_no
= json_object_new_object();
9852 json_object_string_add(json_no
, "warning",
9853 "No such neighbor in this view/vrf");
9854 vty_out(vty
, "%s\n",
9855 json_object_to_json_string_ext(
9856 json_no
, JSON_C_TO_STRING_PRETTY
));
9857 json_object_free(json_no
);
9859 vty_out(vty
, "No such neighbor in this view/vrf\n");
9867 BGP_STATS_MAXBITLEN
= 0,
9871 BGP_STATS_UNAGGREGATEABLE
,
9872 BGP_STATS_MAX_AGGREGATEABLE
,
9873 BGP_STATS_AGGREGATES
,
9875 BGP_STATS_ASPATH_COUNT
,
9876 BGP_STATS_ASPATH_MAXHOPS
,
9877 BGP_STATS_ASPATH_TOTHOPS
,
9878 BGP_STATS_ASPATH_MAXSIZE
,
9879 BGP_STATS_ASPATH_TOTSIZE
,
9880 BGP_STATS_ASN_HIGHEST
,
9884 static const char *table_stats_strs
[] = {
9885 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9886 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9887 [BGP_STATS_RIB
] = "Total Advertisements",
9888 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9889 [BGP_STATS_MAX_AGGREGATEABLE
] =
9890 "Maximum aggregateable prefixes",
9891 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9892 [BGP_STATS_SPACE
] = "Address space advertised",
9893 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9894 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9895 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9896 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9897 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9898 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9899 [BGP_STATS_MAX
] = NULL
,
9902 struct bgp_table_stats
{
9903 struct bgp_table
*table
;
9904 unsigned long long counts
[BGP_STATS_MAX
];
9909 #define TALLY_SIGFIG 100000
9910 static unsigned long
9911 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9913 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9914 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9915 unsigned long ret
= newtot
/ count
;
9917 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9924 static int bgp_table_stats_walker(struct thread
*t
)
9926 struct bgp_node
*rn
;
9927 struct bgp_node
*top
;
9928 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9929 unsigned int space
= 0;
9931 if (!(top
= bgp_table_top(ts
->table
)))
9934 switch (top
->p
.family
) {
9936 space
= IPV4_MAX_BITLEN
;
9939 space
= IPV6_MAX_BITLEN
;
9943 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9945 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9946 struct bgp_path_info
*pi
;
9947 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9948 unsigned int pinum
= 0;
9953 if (!bgp_node_has_bgp_path_info_data(rn
))
9956 ts
->counts
[BGP_STATS_PREFIXES
]++;
9957 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9960 ts
->counts
[BGP_STATS_AVGPLEN
]
9961 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9962 ts
->counts
[BGP_STATS_AVGPLEN
],
9966 /* check if the prefix is included by any other announcements */
9967 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
9968 prn
= bgp_node_parent_nolock(prn
);
9970 if (prn
== NULL
|| prn
== top
) {
9971 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9972 /* announced address space */
9975 pow(2.0, space
- rn
->p
.prefixlen
);
9976 } else if (bgp_node_has_bgp_path_info_data(prn
))
9977 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9979 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9981 ts
->counts
[BGP_STATS_RIB
]++;
9984 && (CHECK_FLAG(pi
->attr
->flag
,
9986 BGP_ATTR_ATOMIC_AGGREGATE
))))
9987 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9990 if (pi
->attr
&& pi
->attr
->aspath
) {
9992 aspath_count_hops(pi
->attr
->aspath
);
9994 aspath_size(pi
->attr
->aspath
);
9995 as_t highest
= aspath_highest(pi
->attr
->aspath
);
9997 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9999 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10000 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
10003 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10004 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
10007 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10008 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10010 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10011 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10012 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10014 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10015 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10016 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10019 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10020 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
10028 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10031 struct bgp_table_stats ts
;
10034 if (!bgp
->rib
[afi
][safi
]) {
10035 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10037 return CMD_WARNING
;
10040 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10042 /* labeled-unicast routes live in the unicast table */
10043 if (safi
== SAFI_LABELED_UNICAST
)
10044 safi
= SAFI_UNICAST
;
10046 memset(&ts
, 0, sizeof(ts
));
10047 ts
.table
= bgp
->rib
[afi
][safi
];
10048 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10050 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10051 if (!table_stats_strs
[i
])
10056 case BGP_STATS_ASPATH_AVGHOPS
:
10057 case BGP_STATS_ASPATH_AVGSIZE
:
10058 case BGP_STATS_AVGPLEN
:
10059 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10060 vty_out (vty
, "%12.2f",
10061 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10064 case BGP_STATS_ASPATH_TOTHOPS
:
10065 case BGP_STATS_ASPATH_TOTSIZE
:
10066 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10067 vty_out(vty
, "%12.2f",
10069 ? (float)ts
.counts
[i
]
10071 [BGP_STATS_ASPATH_COUNT
]
10074 case BGP_STATS_TOTPLEN
:
10075 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10076 vty_out(vty
, "%12.2f",
10078 ? (float)ts
.counts
[i
]
10080 [BGP_STATS_PREFIXES
]
10083 case BGP_STATS_SPACE
:
10084 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10085 vty_out(vty
, "%12g\n", ts
.total_space
);
10087 if (afi
== AFI_IP6
) {
10088 vty_out(vty
, "%30s: ", "/32 equivalent ");
10089 vty_out(vty
, "%12g\n",
10090 ts
.total_space
* pow(2.0, -128 + 32));
10091 vty_out(vty
, "%30s: ", "/48 equivalent ");
10092 vty_out(vty
, "%12g\n",
10093 ts
.total_space
* pow(2.0, -128 + 48));
10095 vty_out(vty
, "%30s: ", "% announced ");
10096 vty_out(vty
, "%12.2f\n",
10097 ts
.total_space
* 100. * pow(2.0, -32));
10098 vty_out(vty
, "%30s: ", "/8 equivalent ");
10099 vty_out(vty
, "%12.2f\n",
10100 ts
.total_space
* pow(2.0, -32 + 8));
10101 vty_out(vty
, "%30s: ", "/24 equivalent ");
10102 vty_out(vty
, "%12.2f\n",
10103 ts
.total_space
* pow(2.0, -32 + 24));
10107 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10108 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10111 vty_out(vty
, "\n");
10113 return CMD_SUCCESS
;
10125 PCOUNT_PFCNT
, /* the figure we display to users */
10129 static const char *pcount_strs
[] = {
10130 [PCOUNT_ADJ_IN
] = "Adj-in",
10131 [PCOUNT_DAMPED
] = "Damped",
10132 [PCOUNT_REMOVED
] = "Removed",
10133 [PCOUNT_HISTORY
] = "History",
10134 [PCOUNT_STALE
] = "Stale",
10135 [PCOUNT_VALID
] = "Valid",
10136 [PCOUNT_ALL
] = "All RIB",
10137 [PCOUNT_COUNTED
] = "PfxCt counted",
10138 [PCOUNT_PFCNT
] = "Useable",
10139 [PCOUNT_MAX
] = NULL
,
10142 struct peer_pcounts
{
10143 unsigned int count
[PCOUNT_MAX
];
10144 const struct peer
*peer
;
10145 const struct bgp_table
*table
;
10148 static int bgp_peer_count_walker(struct thread
*t
)
10150 struct bgp_node
*rn
;
10151 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10152 const struct peer
*peer
= pc
->peer
;
10154 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10155 struct bgp_adj_in
*ain
;
10156 struct bgp_path_info
*pi
;
10158 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10159 if (ain
->peer
== peer
)
10160 pc
->count
[PCOUNT_ADJ_IN
]++;
10162 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10164 if (pi
->peer
!= peer
)
10167 pc
->count
[PCOUNT_ALL
]++;
10169 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10170 pc
->count
[PCOUNT_DAMPED
]++;
10171 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10172 pc
->count
[PCOUNT_HISTORY
]++;
10173 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10174 pc
->count
[PCOUNT_REMOVED
]++;
10175 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10176 pc
->count
[PCOUNT_STALE
]++;
10177 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10178 pc
->count
[PCOUNT_VALID
]++;
10179 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10180 pc
->count
[PCOUNT_PFCNT
]++;
10182 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10183 pc
->count
[PCOUNT_COUNTED
]++;
10184 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10186 EC_LIB_DEVELOPMENT
,
10187 "Attempting to count but flags say it is unusable");
10189 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10191 EC_LIB_DEVELOPMENT
,
10192 "Not counted but flags say we should");
10199 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10200 safi_t safi
, bool use_json
)
10202 struct peer_pcounts pcounts
= {.peer
= peer
};
10204 json_object
*json
= NULL
;
10205 json_object
*json_loop
= NULL
;
10208 json
= json_object_new_object();
10209 json_loop
= json_object_new_object();
10212 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10213 || !peer
->bgp
->rib
[afi
][safi
]) {
10215 json_object_string_add(
10217 "No such neighbor or address family");
10218 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10219 json_object_free(json
);
10221 vty_out(vty
, "%% No such neighbor or address family\n");
10223 return CMD_WARNING
;
10226 memset(&pcounts
, 0, sizeof(pcounts
));
10227 pcounts
.peer
= peer
;
10228 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10230 /* in-place call via thread subsystem so as to record execution time
10231 * stats for the thread-walk (i.e. ensure this can't be blamed on
10232 * on just vty_read()).
10234 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10237 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10238 json_object_string_add(json
, "multiProtocol",
10239 afi_safi_print(afi
, safi
));
10240 json_object_int_add(json
, "pfxCounter",
10241 peer
->pcount
[afi
][safi
]);
10243 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10244 json_object_int_add(json_loop
, pcount_strs
[i
],
10247 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10249 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10250 json_object_string_add(json
, "pfxctDriftFor",
10252 json_object_string_add(
10253 json
, "recommended",
10254 "Please report this bug, with the above command output");
10256 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10257 json
, JSON_C_TO_STRING_PRETTY
));
10258 json_object_free(json
);
10262 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10263 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10264 peer
->hostname
, peer
->host
,
10265 afi_safi_print(afi
, safi
));
10267 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10268 afi_safi_print(afi
, safi
));
10271 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10272 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10274 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10275 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10278 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10279 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10281 "Please report this bug, with the above command output\n");
10285 return CMD_SUCCESS
;
10288 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10289 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10290 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10291 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10295 BGP_INSTANCE_HELP_STR
10298 "Detailed information on TCP and BGP neighbor connections\n"
10299 "Neighbor to display information about\n"
10300 "Neighbor to display information about\n"
10301 "Neighbor on BGP configured interface\n"
10302 "Display detailed prefix count information\n"
10305 afi_t afi
= AFI_IP6
;
10306 safi_t safi
= SAFI_UNICAST
;
10309 struct bgp
*bgp
= NULL
;
10310 bool uj
= use_json(argc
, argv
);
10315 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10318 return CMD_WARNING
;
10320 argv_find(argv
, argc
, "neighbors", &idx
);
10321 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10323 return CMD_WARNING
;
10325 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10328 #ifdef KEEP_OLD_VPN_COMMANDS
10329 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10330 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10331 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10336 "Display information about all VPNv4 NLRIs\n"
10337 "Detailed information on TCP and BGP neighbor connections\n"
10338 "Neighbor to display information about\n"
10339 "Neighbor to display information about\n"
10340 "Neighbor on BGP configured interface\n"
10341 "Display detailed prefix count information\n"
10346 bool uj
= use_json(argc
, argv
);
10348 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10350 return CMD_WARNING
;
10352 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10355 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10356 show_ip_bgp_vpn_all_route_prefix_cmd
,
10357 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10362 "Display information about all VPNv4 NLRIs\n"
10363 "Network in the BGP routing table to display\n"
10364 "Network in the BGP routing table to display\n"
10368 char *network
= NULL
;
10369 struct bgp
*bgp
= bgp_get_default();
10371 vty_out(vty
, "Can't find default instance\n");
10372 return CMD_WARNING
;
10375 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10376 network
= argv
[idx
]->arg
;
10377 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10378 network
= argv
[idx
]->arg
;
10380 vty_out(vty
, "Unable to figure out Network\n");
10381 return CMD_WARNING
;
10384 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10385 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10387 #endif /* KEEP_OLD_VPN_COMMANDS */
10389 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10390 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10391 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10397 "Display information about all EVPN NLRIs\n"
10398 "Network in the BGP routing table to display\n"
10399 "Network in the BGP routing table to display\n"
10403 char *network
= NULL
;
10405 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10406 network
= argv
[idx
]->arg
;
10407 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10408 network
= argv
[idx
]->arg
;
10410 vty_out(vty
, "Unable to figure out Network\n");
10411 return CMD_WARNING
;
10413 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10414 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10417 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10418 safi_t safi
, enum bgp_show_adj_route_type type
,
10419 const char *rmap_name
, bool use_json
,
10422 struct bgp_table
*table
;
10423 struct bgp_adj_in
*ain
;
10424 struct bgp_adj_out
*adj
;
10425 unsigned long output_count
;
10426 unsigned long filtered_count
;
10427 struct bgp_node
*rn
;
10433 struct update_subgroup
*subgrp
;
10434 json_object
*json_scode
= NULL
;
10435 json_object
*json_ocode
= NULL
;
10436 json_object
*json_ar
= NULL
;
10437 struct peer_af
*paf
;
10438 bool route_filtered
;
10441 json_scode
= json_object_new_object();
10442 json_ocode
= json_object_new_object();
10443 json_ar
= json_object_new_object();
10445 json_object_string_add(json_scode
, "suppressed", "s");
10446 json_object_string_add(json_scode
, "damped", "d");
10447 json_object_string_add(json_scode
, "history", "h");
10448 json_object_string_add(json_scode
, "valid", "*");
10449 json_object_string_add(json_scode
, "best", ">");
10450 json_object_string_add(json_scode
, "multipath", "=");
10451 json_object_string_add(json_scode
, "internal", "i");
10452 json_object_string_add(json_scode
, "ribFailure", "r");
10453 json_object_string_add(json_scode
, "stale", "S");
10454 json_object_string_add(json_scode
, "removed", "R");
10456 json_object_string_add(json_ocode
, "igp", "i");
10457 json_object_string_add(json_ocode
, "egp", "e");
10458 json_object_string_add(json_ocode
, "incomplete", "?");
10465 json_object_string_add(json
, "alert", "no BGP");
10466 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10467 json_object_free(json
);
10469 vty_out(vty
, "%% No bgp\n");
10473 table
= bgp
->rib
[afi
][safi
];
10475 output_count
= filtered_count
= 0;
10476 subgrp
= peer_subgroup(peer
, afi
, safi
);
10478 if (type
== bgp_show_adj_route_advertised
&& subgrp
10479 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10481 json_object_int_add(json
, "bgpTableVersion",
10483 json_object_string_add(json
, "bgpLocalRouterId",
10484 inet_ntoa(bgp
->router_id
));
10485 json_object_int_add(json
, "defaultLocPrf",
10486 bgp
->default_local_pref
);
10487 json_object_int_add(json
, "localAS", bgp
->as
);
10488 json_object_object_add(json
, "bgpStatusCodes",
10490 json_object_object_add(json
, "bgpOriginCodes",
10492 json_object_string_add(
10493 json
, "bgpOriginatingDefaultNetwork",
10494 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10496 vty_out(vty
, "BGP table version is %" PRIu64
10497 ", local router ID is %s, vrf id ",
10498 table
->version
, inet_ntoa(bgp
->router_id
));
10499 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10500 vty_out(vty
, "%s", VRFID_NONE_STR
);
10502 vty_out(vty
, "%u", bgp
->vrf_id
);
10503 vty_out(vty
, "\n");
10504 vty_out(vty
, "Default local pref %u, ",
10505 bgp
->default_local_pref
);
10506 vty_out(vty
, "local AS %u\n", bgp
->as
);
10507 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10508 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10509 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10511 vty_out(vty
, "Originating default network %s\n\n",
10512 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10517 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10518 if (type
== bgp_show_adj_route_received
10519 || type
== bgp_show_adj_route_filtered
) {
10520 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10521 if (ain
->peer
!= peer
|| !ain
->attr
)
10526 json_object_int_add(
10527 json
, "bgpTableVersion",
10529 json_object_string_add(
10531 "bgpLocalRouterId",
10534 json_object_int_add(json
,
10536 bgp
->default_local_pref
);
10537 json_object_int_add(json
,
10538 "localAS", bgp
->as
);
10539 json_object_object_add(
10540 json
, "bgpStatusCodes",
10542 json_object_object_add(
10543 json
, "bgpOriginCodes",
10547 "BGP table version is 0, local router ID is %s, vrf id ",
10550 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10556 vty_out(vty
, "\n");
10558 "Default local pref %u, ",
10559 bgp
->default_local_pref
);
10560 vty_out(vty
, "local AS %u\n",
10563 BGP_SHOW_SCODE_HEADER
);
10565 BGP_SHOW_NCODE_HEADER
);
10567 BGP_SHOW_OCODE_HEADER
);
10573 vty_out(vty
, BGP_SHOW_HEADER
);
10577 bgp_attr_dup(&attr
, ain
->attr
);
10578 route_filtered
= false;
10580 /* Filter prefix using distribute list,
10581 * filter list or prefix list
10583 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10584 safi
)) == FILTER_DENY
)
10585 route_filtered
= true;
10587 /* Filter prefix using route-map */
10588 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10589 afi
, safi
, rmap_name
);
10591 if (type
== bgp_show_adj_route_filtered
&&
10592 !route_filtered
&& ret
!= RMAP_DENY
) {
10593 bgp_attr_undup(&attr
, ain
->attr
);
10597 if (type
== bgp_show_adj_route_received
&&
10598 (route_filtered
|| ret
== RMAP_DENY
))
10601 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10602 use_json
, json_ar
);
10603 bgp_attr_undup(&attr
, ain
->attr
);
10606 } else if (type
== bgp_show_adj_route_advertised
) {
10607 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
10608 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10609 if (paf
->peer
!= peer
|| !adj
->attr
)
10614 json_object_int_add(
10618 json_object_string_add(
10620 "bgpLocalRouterId",
10623 json_object_int_add(
10624 json
, "defaultLocPrf",
10625 bgp
->default_local_pref
10627 json_object_int_add(
10630 json_object_object_add(
10634 json_object_object_add(
10640 "BGP table version is %" PRIu64
10641 ", local router ID is %s, vrf id ",
10654 vty_out(vty
, "\n");
10656 "Default local pref %u, ",
10657 bgp
->default_local_pref
10663 BGP_SHOW_SCODE_HEADER
);
10665 BGP_SHOW_NCODE_HEADER
);
10667 BGP_SHOW_OCODE_HEADER
);
10678 bgp_attr_dup(&attr
, adj
->attr
);
10679 ret
= bgp_output_modifier(
10680 peer
, &rn
->p
, &attr
, afi
, safi
,
10683 if (ret
!= RMAP_DENY
) {
10684 route_vty_out_tmp(vty
, &rn
->p
,
10693 bgp_attr_undup(&attr
, adj
->attr
);
10699 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10700 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10701 json_object_int_add(json
, "filteredPrefixCounter",
10704 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10705 json
, JSON_C_TO_STRING_PRETTY
));
10706 json_object_free(json
);
10707 } else if (output_count
> 0) {
10708 if (filtered_count
> 0)
10710 "\nTotal number of prefixes %ld (%ld filtered)\n",
10711 output_count
, filtered_count
);
10713 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10718 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10719 safi_t safi
, enum bgp_show_adj_route_type type
,
10720 const char *rmap_name
, bool use_json
)
10722 json_object
*json
= NULL
;
10725 json
= json_object_new_object();
10727 /* labeled-unicast routes live in the unicast table */
10728 if (safi
== SAFI_LABELED_UNICAST
)
10729 safi
= SAFI_UNICAST
;
10731 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10733 json_object_string_add(
10735 "No such neighbor or address family");
10736 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10737 json_object_free(json
);
10739 vty_out(vty
, "%% No such neighbor or address family\n");
10741 return CMD_WARNING
;
10744 if ((type
== bgp_show_adj_route_received
10745 || type
== bgp_show_adj_route_filtered
)
10746 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10747 PEER_FLAG_SOFT_RECONFIG
)) {
10749 json_object_string_add(
10751 "Inbound soft reconfiguration not enabled");
10752 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10753 json_object_free(json
);
10756 "%% Inbound soft reconfiguration not enabled\n");
10758 return CMD_WARNING
;
10761 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10763 return CMD_SUCCESS
;
10766 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10767 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10768 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10769 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10773 BGP_INSTANCE_HELP_STR
10775 BGP_SAFI_WITH_LABEL_HELP_STR
10776 "Detailed information on TCP and BGP neighbor connections\n"
10777 "Neighbor to display information about\n"
10778 "Neighbor to display information about\n"
10779 "Neighbor on BGP configured interface\n"
10780 "Display the routes advertised to a BGP neighbor\n"
10781 "Display the received routes from neighbor\n"
10782 "Display the filtered routes received from neighbor\n"
10783 "Route-map to modify the attributes\n"
10784 "Name of the route map\n"
10787 afi_t afi
= AFI_IP6
;
10788 safi_t safi
= SAFI_UNICAST
;
10789 char *rmap_name
= NULL
;
10790 char *peerstr
= NULL
;
10791 struct bgp
*bgp
= NULL
;
10793 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10795 bool uj
= use_json(argc
, argv
);
10800 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10803 return CMD_WARNING
;
10805 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10806 argv_find(argv
, argc
, "neighbors", &idx
);
10807 peerstr
= argv
[++idx
]->arg
;
10809 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10811 return CMD_WARNING
;
10813 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10814 type
= bgp_show_adj_route_advertised
;
10815 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10816 type
= bgp_show_adj_route_received
;
10817 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10818 type
= bgp_show_adj_route_filtered
;
10820 if (argv_find(argv
, argc
, "route-map", &idx
))
10821 rmap_name
= argv
[++idx
]->arg
;
10823 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10826 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10827 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10828 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10834 "Address Family modifier\n"
10835 "Detailed information on TCP and BGP neighbor connections\n"
10836 "Neighbor to display information about\n"
10837 "Neighbor to display information about\n"
10838 "Neighbor on BGP configured interface\n"
10839 "Display information received from a BGP neighbor\n"
10840 "Display the prefixlist filter\n"
10843 afi_t afi
= AFI_IP6
;
10844 safi_t safi
= SAFI_UNICAST
;
10845 char *peerstr
= NULL
;
10848 union sockunion su
;
10854 /* show [ip] bgp */
10855 if (argv_find(argv
, argc
, "ip", &idx
))
10857 /* [<ipv4|ipv6> [unicast]] */
10858 if (argv_find(argv
, argc
, "ipv4", &idx
))
10860 if (argv_find(argv
, argc
, "ipv6", &idx
))
10862 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10863 argv_find(argv
, argc
, "neighbors", &idx
);
10864 peerstr
= argv
[++idx
]->arg
;
10866 bool uj
= use_json(argc
, argv
);
10868 ret
= str2sockunion(peerstr
, &su
);
10870 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10873 vty_out(vty
, "{}\n");
10876 "%% Malformed address or name: %s\n",
10878 return CMD_WARNING
;
10881 peer
= peer_lookup(NULL
, &su
);
10884 vty_out(vty
, "{}\n");
10886 vty_out(vty
, "No peer\n");
10887 return CMD_WARNING
;
10891 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10892 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10895 vty_out(vty
, "Address Family: %s\n",
10896 afi_safi_print(afi
, safi
));
10897 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10900 vty_out(vty
, "{}\n");
10902 vty_out(vty
, "No functional output\n");
10905 return CMD_SUCCESS
;
10908 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10909 afi_t afi
, safi_t safi
,
10910 enum bgp_show_type type
, bool use_json
)
10912 /* labeled-unicast routes live in the unicast table */
10913 if (safi
== SAFI_LABELED_UNICAST
)
10914 safi
= SAFI_UNICAST
;
10916 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10918 json_object
*json_no
= NULL
;
10919 json_no
= json_object_new_object();
10920 json_object_string_add(
10921 json_no
, "warning",
10922 "No such neighbor or address family");
10923 vty_out(vty
, "%s\n",
10924 json_object_to_json_string(json_no
));
10925 json_object_free(json_no
);
10927 vty_out(vty
, "%% No such neighbor or address family\n");
10928 return CMD_WARNING
;
10931 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10934 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10935 show_ip_bgp_flowspec_routes_detailed_cmd
,
10936 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10940 BGP_INSTANCE_HELP_STR
10943 "Detailed information on flowspec entries\n"
10946 afi_t afi
= AFI_IP
;
10947 safi_t safi
= SAFI_UNICAST
;
10948 struct bgp
*bgp
= NULL
;
10950 bool uj
= use_json(argc
, argv
);
10955 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10958 return CMD_WARNING
;
10960 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
10963 DEFUN (show_ip_bgp_neighbor_routes
,
10964 show_ip_bgp_neighbor_routes_cmd
,
10965 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10966 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10970 BGP_INSTANCE_HELP_STR
10972 BGP_SAFI_WITH_LABEL_HELP_STR
10973 "Detailed information on TCP and BGP neighbor connections\n"
10974 "Neighbor to display information about\n"
10975 "Neighbor to display information about\n"
10976 "Neighbor on BGP configured interface\n"
10977 "Display flap statistics of the routes learned from neighbor\n"
10978 "Display the dampened routes received from neighbor\n"
10979 "Display routes learned from neighbor\n"
10982 char *peerstr
= NULL
;
10983 struct bgp
*bgp
= NULL
;
10984 afi_t afi
= AFI_IP6
;
10985 safi_t safi
= SAFI_UNICAST
;
10987 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10989 bool uj
= use_json(argc
, argv
);
10994 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10997 return CMD_WARNING
;
10999 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11000 argv_find(argv
, argc
, "neighbors", &idx
);
11001 peerstr
= argv
[++idx
]->arg
;
11003 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11005 return CMD_WARNING
;
11007 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11008 sh_type
= bgp_show_type_flap_neighbor
;
11009 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11010 sh_type
= bgp_show_type_damp_neighbor
;
11011 else if (argv_find(argv
, argc
, "routes", &idx
))
11012 sh_type
= bgp_show_type_neighbor
;
11014 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11017 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11019 struct bgp_distance
{
11020 /* Distance value for the IP source prefix. */
11023 /* Name of the access-list to be matched. */
11027 DEFUN (show_bgp_afi_vpn_rd_route
,
11028 show_bgp_afi_vpn_rd_route_cmd
,
11029 "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]",
11033 "Address Family modifier\n"
11034 "Display information for a route distinguisher\n"
11035 "Route Distinguisher\n"
11036 "Network in the BGP routing table to display\n"
11037 "Network in the BGP routing table to display\n"
11041 struct prefix_rd prd
;
11042 afi_t afi
= AFI_MAX
;
11045 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11046 vty_out(vty
, "%% Malformed Address Family\n");
11047 return CMD_WARNING
;
11050 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11052 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11053 return CMD_WARNING
;
11056 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11057 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11060 static struct bgp_distance
*bgp_distance_new(void)
11062 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11065 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11067 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11070 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11071 const char *ip_str
, const char *access_list_str
)
11078 struct bgp_node
*rn
;
11079 struct bgp_distance
*bdistance
;
11081 afi
= bgp_node_afi(vty
);
11082 safi
= bgp_node_safi(vty
);
11084 ret
= str2prefix(ip_str
, &p
);
11086 vty_out(vty
, "Malformed prefix\n");
11087 return CMD_WARNING_CONFIG_FAILED
;
11090 distance
= atoi(distance_str
);
11092 /* Get BGP distance node. */
11093 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11094 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11096 bgp_unlock_node(rn
);
11098 bdistance
= bgp_distance_new();
11099 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11102 /* Set distance value. */
11103 bdistance
->distance
= distance
;
11105 /* Reset access-list configuration. */
11106 if (bdistance
->access_list
) {
11107 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11108 bdistance
->access_list
= NULL
;
11110 if (access_list_str
)
11111 bdistance
->access_list
=
11112 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11114 return CMD_SUCCESS
;
11117 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11118 const char *ip_str
, const char *access_list_str
)
11125 struct bgp_node
*rn
;
11126 struct bgp_distance
*bdistance
;
11128 afi
= bgp_node_afi(vty
);
11129 safi
= bgp_node_safi(vty
);
11131 ret
= str2prefix(ip_str
, &p
);
11133 vty_out(vty
, "Malformed prefix\n");
11134 return CMD_WARNING_CONFIG_FAILED
;
11137 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11138 (struct prefix
*)&p
);
11140 vty_out(vty
, "Can't find specified prefix\n");
11141 return CMD_WARNING_CONFIG_FAILED
;
11144 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11145 distance
= atoi(distance_str
);
11147 if (bdistance
->distance
!= distance
) {
11148 vty_out(vty
, "Distance does not match configured\n");
11149 return CMD_WARNING_CONFIG_FAILED
;
11152 if (bdistance
->access_list
)
11153 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11154 bgp_distance_free(bdistance
);
11156 bgp_node_set_bgp_path_info(rn
, NULL
);
11157 bgp_unlock_node(rn
);
11158 bgp_unlock_node(rn
);
11160 return CMD_SUCCESS
;
11163 /* Apply BGP information to distance method. */
11164 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11165 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11167 struct bgp_node
*rn
;
11170 struct bgp_distance
*bdistance
;
11171 struct access_list
*alist
;
11172 struct bgp_static
*bgp_static
;
11177 peer
= pinfo
->peer
;
11179 /* Check source address. */
11180 sockunion2hostprefix(&peer
->su
, &q
);
11181 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11183 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11184 bgp_unlock_node(rn
);
11186 if (bdistance
->access_list
) {
11187 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11189 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11190 return bdistance
->distance
;
11192 return bdistance
->distance
;
11195 /* Backdoor check. */
11196 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11198 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11199 bgp_unlock_node(rn
);
11201 if (bgp_static
->backdoor
) {
11202 if (bgp
->distance_local
[afi
][safi
])
11203 return bgp
->distance_local
[afi
][safi
];
11205 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11209 if (peer
->sort
== BGP_PEER_EBGP
) {
11210 if (bgp
->distance_ebgp
[afi
][safi
])
11211 return bgp
->distance_ebgp
[afi
][safi
];
11212 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11214 if (bgp
->distance_ibgp
[afi
][safi
])
11215 return bgp
->distance_ibgp
[afi
][safi
];
11216 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11220 DEFUN (bgp_distance
,
11222 "distance bgp (1-255) (1-255) (1-255)",
11223 "Define an administrative distance\n"
11225 "Distance for routes external to the AS\n"
11226 "Distance for routes internal to the AS\n"
11227 "Distance for local routes\n")
11229 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11230 int idx_number
= 2;
11231 int idx_number_2
= 3;
11232 int idx_number_3
= 4;
11236 afi
= bgp_node_afi(vty
);
11237 safi
= bgp_node_safi(vty
);
11239 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11240 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11241 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11242 return CMD_SUCCESS
;
11245 DEFUN (no_bgp_distance
,
11246 no_bgp_distance_cmd
,
11247 "no distance bgp [(1-255) (1-255) (1-255)]",
11249 "Define an administrative distance\n"
11251 "Distance for routes external to the AS\n"
11252 "Distance for routes internal to the AS\n"
11253 "Distance for local routes\n")
11255 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11259 afi
= bgp_node_afi(vty
);
11260 safi
= bgp_node_safi(vty
);
11262 bgp
->distance_ebgp
[afi
][safi
] = 0;
11263 bgp
->distance_ibgp
[afi
][safi
] = 0;
11264 bgp
->distance_local
[afi
][safi
] = 0;
11265 return CMD_SUCCESS
;
11269 DEFUN (bgp_distance_source
,
11270 bgp_distance_source_cmd
,
11271 "distance (1-255) A.B.C.D/M",
11272 "Define an administrative distance\n"
11273 "Administrative distance\n"
11274 "IP source prefix\n")
11276 int idx_number
= 1;
11277 int idx_ipv4_prefixlen
= 2;
11278 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11279 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11280 return CMD_SUCCESS
;
11283 DEFUN (no_bgp_distance_source
,
11284 no_bgp_distance_source_cmd
,
11285 "no distance (1-255) A.B.C.D/M",
11287 "Define an administrative distance\n"
11288 "Administrative distance\n"
11289 "IP source prefix\n")
11291 int idx_number
= 2;
11292 int idx_ipv4_prefixlen
= 3;
11293 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11294 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11295 return CMD_SUCCESS
;
11298 DEFUN (bgp_distance_source_access_list
,
11299 bgp_distance_source_access_list_cmd
,
11300 "distance (1-255) A.B.C.D/M WORD",
11301 "Define an administrative distance\n"
11302 "Administrative distance\n"
11303 "IP source prefix\n"
11304 "Access list name\n")
11306 int idx_number
= 1;
11307 int idx_ipv4_prefixlen
= 2;
11309 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11310 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11311 return CMD_SUCCESS
;
11314 DEFUN (no_bgp_distance_source_access_list
,
11315 no_bgp_distance_source_access_list_cmd
,
11316 "no distance (1-255) A.B.C.D/M WORD",
11318 "Define an administrative distance\n"
11319 "Administrative distance\n"
11320 "IP source prefix\n"
11321 "Access list name\n")
11323 int idx_number
= 2;
11324 int idx_ipv4_prefixlen
= 3;
11326 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11327 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11328 return CMD_SUCCESS
;
11331 DEFUN (ipv6_bgp_distance_source
,
11332 ipv6_bgp_distance_source_cmd
,
11333 "distance (1-255) X:X::X:X/M",
11334 "Define an administrative distance\n"
11335 "Administrative distance\n"
11336 "IP source prefix\n")
11338 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11339 return CMD_SUCCESS
;
11342 DEFUN (no_ipv6_bgp_distance_source
,
11343 no_ipv6_bgp_distance_source_cmd
,
11344 "no distance (1-255) X:X::X:X/M",
11346 "Define an administrative distance\n"
11347 "Administrative distance\n"
11348 "IP source prefix\n")
11350 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11351 return CMD_SUCCESS
;
11354 DEFUN (ipv6_bgp_distance_source_access_list
,
11355 ipv6_bgp_distance_source_access_list_cmd
,
11356 "distance (1-255) X:X::X:X/M WORD",
11357 "Define an administrative distance\n"
11358 "Administrative distance\n"
11359 "IP source prefix\n"
11360 "Access list name\n")
11362 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11363 return CMD_SUCCESS
;
11366 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11367 no_ipv6_bgp_distance_source_access_list_cmd
,
11368 "no distance (1-255) X:X::X:X/M WORD",
11370 "Define an administrative distance\n"
11371 "Administrative distance\n"
11372 "IP source prefix\n"
11373 "Access list name\n")
11375 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11376 return CMD_SUCCESS
;
11379 DEFUN (bgp_damp_set
,
11381 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11382 "BGP Specific commands\n"
11383 "Enable route-flap dampening\n"
11384 "Half-life time for the penalty\n"
11385 "Value to start reusing a route\n"
11386 "Value to start suppressing a route\n"
11387 "Maximum duration to suppress a stable route\n")
11389 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11390 int idx_half_life
= 2;
11392 int idx_suppress
= 4;
11393 int idx_max_suppress
= 5;
11394 int half
= DEFAULT_HALF_LIFE
* 60;
11395 int reuse
= DEFAULT_REUSE
;
11396 int suppress
= DEFAULT_SUPPRESS
;
11397 int max
= 4 * half
;
11400 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11401 reuse
= atoi(argv
[idx_reuse
]->arg
);
11402 suppress
= atoi(argv
[idx_suppress
]->arg
);
11403 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11404 } else if (argc
== 3) {
11405 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11409 if (suppress
< reuse
) {
11411 "Suppress value cannot be less than reuse value \n");
11415 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11416 reuse
, suppress
, max
);
11419 DEFUN (bgp_damp_unset
,
11420 bgp_damp_unset_cmd
,
11421 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11423 "BGP Specific commands\n"
11424 "Enable route-flap dampening\n"
11425 "Half-life time for the penalty\n"
11426 "Value to start reusing a route\n"
11427 "Value to start suppressing a route\n"
11428 "Maximum duration to suppress a stable route\n")
11430 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11431 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11434 /* Display specified route of BGP table. */
11435 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11436 const char *ip_str
, afi_t afi
, safi_t safi
,
11437 struct prefix_rd
*prd
, int prefix_check
)
11440 struct prefix match
;
11441 struct bgp_node
*rn
;
11442 struct bgp_node
*rm
;
11443 struct bgp_path_info
*pi
;
11444 struct bgp_path_info
*pi_temp
;
11446 struct bgp_table
*table
;
11448 /* BGP structure lookup. */
11450 bgp
= bgp_lookup_by_name(view_name
);
11452 vty_out(vty
, "%% Can't find BGP instance %s\n",
11454 return CMD_WARNING
;
11457 bgp
= bgp_get_default();
11459 vty_out(vty
, "%% No BGP process is configured\n");
11460 return CMD_WARNING
;
11464 /* Check IP address argument. */
11465 ret
= str2prefix(ip_str
, &match
);
11467 vty_out(vty
, "%% address is malformed\n");
11468 return CMD_WARNING
;
11471 match
.family
= afi2family(afi
);
11473 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11474 || (safi
== SAFI_EVPN
)) {
11475 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11476 rn
= bgp_route_next(rn
)) {
11477 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11479 table
= bgp_node_get_bgp_table_info(rn
);
11482 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11486 || rm
->p
.prefixlen
== match
.prefixlen
) {
11487 pi
= bgp_node_get_bgp_path_info(rm
);
11489 if (pi
->extra
&& pi
->extra
->damp_info
) {
11490 pi_temp
= pi
->next
;
11491 bgp_damp_info_free(
11492 pi
->extra
->damp_info
,
11500 bgp_unlock_node(rm
);
11503 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11506 || rn
->p
.prefixlen
== match
.prefixlen
) {
11507 pi
= bgp_node_get_bgp_path_info(rn
);
11509 if (pi
->extra
&& pi
->extra
->damp_info
) {
11510 pi_temp
= pi
->next
;
11511 bgp_damp_info_free(
11512 pi
->extra
->damp_info
,
11520 bgp_unlock_node(rn
);
11524 return CMD_SUCCESS
;
11527 DEFUN (clear_ip_bgp_dampening
,
11528 clear_ip_bgp_dampening_cmd
,
11529 "clear ip bgp dampening",
11533 "Clear route flap dampening information\n")
11535 bgp_damp_info_clean();
11536 return CMD_SUCCESS
;
11539 DEFUN (clear_ip_bgp_dampening_prefix
,
11540 clear_ip_bgp_dampening_prefix_cmd
,
11541 "clear ip bgp dampening A.B.C.D/M",
11545 "Clear route flap dampening information\n"
11548 int idx_ipv4_prefixlen
= 4;
11549 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11550 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11553 DEFUN (clear_ip_bgp_dampening_address
,
11554 clear_ip_bgp_dampening_address_cmd
,
11555 "clear ip bgp dampening A.B.C.D",
11559 "Clear route flap dampening information\n"
11560 "Network to clear damping information\n")
11563 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11564 SAFI_UNICAST
, NULL
, 0);
11567 DEFUN (clear_ip_bgp_dampening_address_mask
,
11568 clear_ip_bgp_dampening_address_mask_cmd
,
11569 "clear ip bgp dampening A.B.C.D A.B.C.D",
11573 "Clear route flap dampening information\n"
11574 "Network to clear damping information\n"
11578 int idx_ipv4_2
= 5;
11580 char prefix_str
[BUFSIZ
];
11582 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11585 vty_out(vty
, "%% Inconsistent address and mask\n");
11586 return CMD_WARNING
;
11589 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11593 static void show_bgp_peerhash_entry(struct hash_backet
*backet
, void *arg
)
11595 struct vty
*vty
= arg
;
11596 struct peer
*peer
= backet
->data
;
11597 char buf
[SU_ADDRSTRLEN
];
11599 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
11600 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
11603 DEFUN (show_bgp_peerhash
,
11604 show_bgp_peerhash_cmd
,
11605 "show bgp peerhash",
11608 "Display information about the BGP peerhash\n")
11610 struct list
*instances
= bm
->bgp
;
11611 struct listnode
*node
;
11614 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
11615 vty_out(vty
, "BGP: %s\n", bgp
->name
);
11616 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
11620 return CMD_SUCCESS
;
11623 /* also used for encap safi */
11624 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11625 afi_t afi
, safi_t safi
)
11627 struct bgp_node
*prn
;
11628 struct bgp_node
*rn
;
11629 struct bgp_table
*table
;
11631 struct prefix_rd
*prd
;
11632 struct bgp_static
*bgp_static
;
11633 mpls_label_t label
;
11634 char buf
[SU_ADDRSTRLEN
];
11635 char rdbuf
[RD_ADDRSTRLEN
];
11637 /* Network configuration. */
11638 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11639 prn
= bgp_route_next(prn
)) {
11640 table
= bgp_node_get_bgp_table_info(prn
);
11644 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11645 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11646 if (bgp_static
== NULL
)
11650 prd
= (struct prefix_rd
*)&prn
->p
;
11652 /* "network" configuration display. */
11653 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11654 label
= decode_label(&bgp_static
->label
);
11656 vty_out(vty
, " network %s/%d rd %s",
11657 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11659 p
->prefixlen
, rdbuf
);
11660 if (safi
== SAFI_MPLS_VPN
)
11661 vty_out(vty
, " label %u", label
);
11663 if (bgp_static
->rmap
.name
)
11664 vty_out(vty
, " route-map %s",
11665 bgp_static
->rmap
.name
);
11667 if (bgp_static
->backdoor
)
11668 vty_out(vty
, " backdoor");
11670 vty_out(vty
, "\n");
11675 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11676 afi_t afi
, safi_t safi
)
11678 struct bgp_node
*prn
;
11679 struct bgp_node
*rn
;
11680 struct bgp_table
*table
;
11682 struct prefix_rd
*prd
;
11683 struct bgp_static
*bgp_static
;
11684 char buf
[PREFIX_STRLEN
* 2];
11685 char buf2
[SU_ADDRSTRLEN
];
11686 char rdbuf
[RD_ADDRSTRLEN
];
11688 /* Network configuration. */
11689 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11690 prn
= bgp_route_next(prn
)) {
11691 table
= bgp_node_get_bgp_table_info(prn
);
11695 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11696 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11697 if (bgp_static
== NULL
)
11700 char *macrouter
= NULL
;
11703 if (bgp_static
->router_mac
)
11704 macrouter
= prefix_mac2str(
11705 bgp_static
->router_mac
, NULL
, 0);
11706 if (bgp_static
->eth_s_id
)
11707 esi
= esi2str(bgp_static
->eth_s_id
);
11709 prd
= (struct prefix_rd
*)&prn
->p
;
11711 /* "network" configuration display. */
11712 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11713 if (p
->u
.prefix_evpn
.route_type
== 5) {
11714 char local_buf
[PREFIX_STRLEN
];
11715 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11716 struct prefix_evpn
*)p
)
11720 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11721 local_buf
, PREFIX_STRLEN
);
11722 sprintf(buf
, "%s/%u", local_buf
,
11723 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11725 prefix2str(p
, buf
, sizeof(buf
));
11728 if (bgp_static
->gatewayIp
.family
== AF_INET
11729 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11730 inet_ntop(bgp_static
->gatewayIp
.family
,
11731 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11734 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11736 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11737 decode_label(&bgp_static
->label
), esi
, buf2
,
11741 XFREE(MTYPE_TMP
, macrouter
);
11743 XFREE(MTYPE_TMP
, esi
);
11748 /* Configuration of static route announcement and aggregate
11750 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11753 struct bgp_node
*rn
;
11755 struct bgp_static
*bgp_static
;
11756 struct bgp_aggregate
*bgp_aggregate
;
11757 char buf
[SU_ADDRSTRLEN
];
11759 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11760 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11764 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11765 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11769 /* Network configuration. */
11770 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11771 rn
= bgp_route_next(rn
)) {
11772 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11773 if (bgp_static
== NULL
)
11778 /* "network" configuration display. */
11779 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11780 uint32_t destination
;
11781 struct in_addr netmask
;
11783 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11784 masklen2ip(p
->prefixlen
, &netmask
);
11785 vty_out(vty
, " network %s",
11786 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11789 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11790 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11791 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11792 || p
->u
.prefix4
.s_addr
== 0) {
11793 /* Natural mask is not display. */
11795 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11797 vty_out(vty
, " network %s/%d",
11798 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11803 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11804 vty_out(vty
, " label-index %u",
11805 bgp_static
->label_index
);
11807 if (bgp_static
->rmap
.name
)
11808 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11810 if (bgp_static
->backdoor
)
11811 vty_out(vty
, " backdoor");
11813 vty_out(vty
, "\n");
11816 /* Aggregate-address configuration. */
11817 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11818 rn
= bgp_route_next(rn
)) {
11819 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
11820 if (bgp_aggregate
== NULL
)
11825 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11826 struct in_addr netmask
;
11828 masklen2ip(p
->prefixlen
, &netmask
);
11829 vty_out(vty
, " aggregate-address %s %s",
11830 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11832 inet_ntoa(netmask
));
11834 vty_out(vty
, " aggregate-address %s/%d",
11835 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11840 if (bgp_aggregate
->as_set
)
11841 vty_out(vty
, " as-set");
11843 if (bgp_aggregate
->summary_only
)
11844 vty_out(vty
, " summary-only");
11846 vty_out(vty
, "\n");
11850 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11853 struct bgp_node
*rn
;
11854 struct bgp_distance
*bdistance
;
11856 /* Distance configuration. */
11857 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11858 && bgp
->distance_local
[afi
][safi
]
11859 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11860 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11861 || bgp
->distance_local
[afi
][safi
]
11862 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11863 vty_out(vty
, " distance bgp %d %d %d\n",
11864 bgp
->distance_ebgp
[afi
][safi
],
11865 bgp
->distance_ibgp
[afi
][safi
],
11866 bgp
->distance_local
[afi
][safi
]);
11869 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11870 rn
= bgp_route_next(rn
)) {
11871 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11872 if (bdistance
!= NULL
) {
11873 char buf
[PREFIX_STRLEN
];
11875 vty_out(vty
, " distance %d %s %s\n",
11876 bdistance
->distance
,
11877 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11878 bdistance
->access_list
? bdistance
->access_list
11884 /* Allocate routing table structure and install commands. */
11885 void bgp_route_init(void)
11890 /* Init BGP distance table. */
11891 FOREACH_AFI_SAFI (afi
, safi
)
11892 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11894 /* IPv4 BGP commands. */
11895 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11896 install_element(BGP_NODE
, &bgp_network_cmd
);
11897 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11899 install_element(BGP_NODE
, &aggregate_address_cmd
);
11900 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11901 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11902 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11904 /* IPv4 unicast configuration. */
11905 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11906 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11907 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11909 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11910 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11911 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11912 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11914 /* IPv4 multicast configuration. */
11915 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11916 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11917 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11918 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11919 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11920 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11921 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11923 /* IPv4 labeled-unicast configuration. */
11924 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11925 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11926 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11927 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11928 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11930 install_element(VIEW_NODE
,
11931 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11932 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11933 install_element(VIEW_NODE
,
11934 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11935 #ifdef KEEP_OLD_VPN_COMMANDS
11936 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11937 #endif /* KEEP_OLD_VPN_COMMANDS */
11938 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11939 install_element(VIEW_NODE
,
11940 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11942 /* BGP dampening clear commands */
11943 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11944 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11946 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11947 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11950 install_element(ENABLE_NODE
,
11951 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11952 #ifdef KEEP_OLD_VPN_COMMANDS
11953 install_element(ENABLE_NODE
,
11954 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11955 #endif /* KEEP_OLD_VPN_COMMANDS */
11957 /* New config IPv6 BGP commands. */
11958 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11959 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11960 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11962 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11963 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11965 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11967 install_element(BGP_NODE
, &bgp_distance_cmd
);
11968 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11969 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11970 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11971 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11972 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11973 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11974 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11975 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11976 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11977 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11978 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11979 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11980 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11981 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11982 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11983 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11984 install_element(BGP_IPV4M_NODE
,
11985 &no_bgp_distance_source_access_list_cmd
);
11986 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11987 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11988 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11989 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11990 install_element(BGP_IPV6_NODE
,
11991 &ipv6_bgp_distance_source_access_list_cmd
);
11992 install_element(BGP_IPV6_NODE
,
11993 &no_ipv6_bgp_distance_source_access_list_cmd
);
11994 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11995 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11996 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11997 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11998 install_element(BGP_IPV6M_NODE
,
11999 &ipv6_bgp_distance_source_access_list_cmd
);
12000 install_element(BGP_IPV6M_NODE
,
12001 &no_ipv6_bgp_distance_source_access_list_cmd
);
12003 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12004 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12005 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12006 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12008 /* IPv4 Multicast Mode */
12009 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12010 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12012 /* Large Communities */
12013 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12014 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12016 /* show bgp ipv4 flowspec detailed */
12017 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12019 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12022 void bgp_route_finish(void)
12027 FOREACH_AFI_SAFI (afi
, safi
) {
12028 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12029 bgp_distance_table
[afi
][safi
] = NULL
;