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. Exceptions:
2269 * - label index has changed -> recalculate resulting label
2270 * - path_info sub_type changed -> switch to/from implicit-null
2271 * - no valid label (due to removed static label binding) -> get new one
2273 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2276 || bgp_label_index_differs(new_select
, old_select
)
2277 || new_select
->sub_type
!= old_select
->sub_type
2278 || !bgp_is_valid_label(&rn
->local_label
)) {
2279 /* Enforced penultimate hop popping:
2280 * implicit-null for local routes, aggregate
2281 * and redistributed routes
2283 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2284 || new_select
->sub_type
2285 == BGP_ROUTE_AGGREGATE
2286 || new_select
->sub_type
2287 == BGP_ROUTE_REDISTRIBUTE
) {
2290 BGP_NODE_REGISTERED_FOR_LABEL
))
2291 bgp_unregister_for_label(rn
);
2292 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2294 bgp_set_valid_label(&rn
->local_label
);
2296 bgp_register_for_label(rn
, new_select
);
2298 } else if (CHECK_FLAG(rn
->flags
,
2299 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2300 bgp_unregister_for_label(rn
);
2302 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2303 bgp_unregister_for_label(rn
);
2307 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2309 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2310 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2311 old_select
, new_select
);
2314 /* If best route remains the same and this is not due to user-initiated
2315 * clear, see exactly what needs to be done.
2317 if (old_select
&& old_select
== new_select
2318 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2319 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2320 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2321 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2323 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2324 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2326 if (bgp_fibupd_safi(safi
)
2327 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2329 if (new_select
->type
== ZEBRA_ROUTE_BGP
2330 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2331 || new_select
->sub_type
2332 == BGP_ROUTE_IMPORTED
))
2334 bgp_zebra_announce(rn
, p
, old_select
,
2338 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2339 bgp_zebra_clear_route_change_flags(rn
);
2341 /* If there is a change of interest to peers, reannounce the
2343 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2344 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2345 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2347 /* unicast routes must also be annouced to
2348 * labeled-unicast update-groups */
2349 if (safi
== SAFI_UNICAST
)
2350 group_announce_route(bgp
, afi
,
2351 SAFI_LABELED_UNICAST
, rn
,
2354 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2355 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2358 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2362 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2364 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2366 /* bestpath has changed; bump version */
2367 if (old_select
|| new_select
) {
2368 bgp_bump_version(rn
);
2370 if (!bgp
->t_rmap_def_originate_eval
) {
2374 update_group_refresh_default_originate_route_map
,
2375 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2376 &bgp
->t_rmap_def_originate_eval
);
2381 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2384 zlog_debug("%s: setting SELECTED flag", __func__
);
2385 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2386 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2387 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2391 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2392 if (old_select
!= new_select
) {
2394 vnc_import_bgp_exterior_del_route(bgp
, p
,
2396 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2399 vnc_import_bgp_exterior_add_route(bgp
, p
,
2401 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2407 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2409 /* unicast routes must also be annouced to labeled-unicast update-groups
2411 if (safi
== SAFI_UNICAST
)
2412 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2416 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2417 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2418 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2419 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2420 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2421 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2423 /* if this is an evpn imported type-5 prefix,
2424 * we need to withdraw the route first to clear
2425 * the nh neigh and the RMAC entry.
2428 is_route_parent_evpn(old_select
))
2429 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2431 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2433 /* Withdraw the route from the kernel. */
2434 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2435 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2436 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2437 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2439 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2443 /* advertise/withdraw type-5 routes */
2444 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2445 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2446 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2448 /* apply the route-map */
2449 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2452 ret
= route_map_apply(
2453 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2454 &rn
->p
, RMAP_BGP
, new_select
);
2455 if (ret
== RMAP_MATCH
)
2456 bgp_evpn_advertise_type5_route(
2457 bgp
, &rn
->p
, new_select
->attr
,
2460 bgp_evpn_advertise_type5_route(bgp
,
2466 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2467 (!old_select
->extra
|| !old_select
->extra
->parent
))
2468 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2471 /* Clear any route change flags. */
2472 bgp_zebra_clear_route_change_flags(rn
);
2474 /* Reap old select bgp_path_info, if it has been removed */
2475 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2476 bgp_path_info_reap(rn
, old_select
);
2478 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2482 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2484 struct bgp_process_queue
*pqnode
= data
;
2485 struct bgp
*bgp
= pqnode
->bgp
;
2486 struct bgp_table
*table
;
2487 struct bgp_node
*rn
;
2490 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2491 bgp_process_main_one(bgp
, NULL
, 0, 0);
2492 /* should always have dedicated wq call */
2493 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2497 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2498 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2499 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2500 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2501 table
= bgp_node_table(rn
);
2502 /* note, new RNs may be added as part of processing */
2503 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2505 bgp_unlock_node(rn
);
2506 bgp_table_unlock(table
);
2512 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2514 struct bgp_process_queue
*pqnode
= data
;
2516 bgp_unlock(pqnode
->bgp
);
2518 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2521 void bgp_process_queue_init(void)
2523 if (!bm
->process_main_queue
)
2524 bm
->process_main_queue
=
2525 work_queue_new(bm
->master
, "process_main_queue");
2527 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2528 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2529 bm
->process_main_queue
->spec
.max_retries
= 0;
2530 bm
->process_main_queue
->spec
.hold
= 50;
2531 /* Use a higher yield value of 50ms for main queue processing */
2532 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2535 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2537 struct bgp_process_queue
*pqnode
;
2539 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2540 sizeof(struct bgp_process_queue
));
2542 /* unlocked in bgp_processq_del */
2543 pqnode
->bgp
= bgp_lock(bgp
);
2544 STAILQ_INIT(&pqnode
->pqueue
);
2549 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2551 #define ARBITRARY_PROCESS_QLEN 10000
2552 struct work_queue
*wq
= bm
->process_main_queue
;
2553 struct bgp_process_queue
*pqnode
;
2554 int pqnode_reuse
= 0;
2556 /* already scheduled for processing? */
2557 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2563 /* Add route nodes to an existing work queue item until reaching the
2564 limit only if is from the same BGP view and it's not an EOIU marker
2566 if (work_queue_item_count(wq
)) {
2567 struct work_queue_item
*item
= work_queue_last_item(wq
);
2568 pqnode
= item
->data
;
2570 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2571 || pqnode
->bgp
!= bgp
2572 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2573 pqnode
= bgp_processq_alloc(bgp
);
2577 pqnode
= bgp_processq_alloc(bgp
);
2578 /* all unlocked in bgp_process_wq */
2579 bgp_table_lock(bgp_node_table(rn
));
2581 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2584 /* can't be enqueued twice */
2585 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2586 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2590 work_queue_add(wq
, pqnode
);
2595 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2597 struct bgp_process_queue
*pqnode
;
2599 if (bm
->process_main_queue
== NULL
)
2602 pqnode
= bgp_processq_alloc(bgp
);
2604 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2605 work_queue_add(bm
->process_main_queue
, pqnode
);
2608 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2612 peer
= THREAD_ARG(thread
);
2613 peer
->t_pmax_restart
= NULL
;
2615 if (bgp_debug_neighbor_events(peer
))
2617 "%s Maximum-prefix restart timer expired, restore peering",
2620 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2621 zlog_debug("%s: %s peer_clear failed",
2622 __PRETTY_FUNCTION__
, peer
->host
);
2627 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2631 iana_safi_t pkt_safi
;
2633 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2636 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2637 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2638 PEER_STATUS_PREFIX_LIMIT
)
2643 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2645 afi_safi_print(afi
, safi
), peer
->host
,
2646 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2647 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2649 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2650 PEER_FLAG_MAX_PREFIX_WARNING
))
2653 /* Convert AFI, SAFI to values for packet. */
2654 pkt_afi
= afi_int2iana(afi
);
2655 pkt_safi
= safi_int2iana(safi
);
2659 ndata
[0] = (pkt_afi
>> 8);
2661 ndata
[2] = pkt_safi
;
2662 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2663 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2664 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2665 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2667 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2668 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2669 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2673 /* Dynamic peers will just close their connection. */
2674 if (peer_dynamic_neighbor(peer
))
2677 /* restart timer start */
2678 if (peer
->pmax_restart
[afi
][safi
]) {
2679 peer
->v_pmax_restart
=
2680 peer
->pmax_restart
[afi
][safi
] * 60;
2682 if (bgp_debug_neighbor_events(peer
))
2684 "%s Maximum-prefix restart timer started for %d secs",
2685 peer
->host
, peer
->v_pmax_restart
);
2687 BGP_TIMER_ON(peer
->t_pmax_restart
,
2688 bgp_maximum_prefix_restart_timer
,
2689 peer
->v_pmax_restart
);
2694 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2695 PEER_STATUS_PREFIX_LIMIT
);
2697 if (peer
->pcount
[afi
][safi
]
2698 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2699 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2700 PEER_STATUS_PREFIX_THRESHOLD
)
2705 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2706 afi_safi_print(afi
, safi
), peer
->host
,
2707 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2708 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2709 PEER_STATUS_PREFIX_THRESHOLD
);
2711 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2712 PEER_STATUS_PREFIX_THRESHOLD
);
2716 /* Unconditionally remove the route from the RIB, without taking
2717 * damping into consideration (eg, because the session went down)
2719 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2720 struct peer
*peer
, afi_t afi
, safi_t safi
)
2722 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2724 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2725 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2727 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2730 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2731 struct peer
*peer
, afi_t afi
, safi_t safi
,
2732 struct prefix_rd
*prd
)
2734 /* apply dampening, if result is suppressed, we'll be retaining
2735 * the bgp_path_info in the RIB for historical reference.
2737 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2738 && peer
->sort
== BGP_PEER_EBGP
)
2739 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2740 == BGP_DAMP_SUPPRESSED
) {
2741 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2747 if (safi
== SAFI_MPLS_VPN
) {
2748 struct bgp_node
*prn
= NULL
;
2749 struct bgp_table
*table
= NULL
;
2751 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2752 (struct prefix
*)prd
);
2753 if (bgp_node_has_bgp_path_info_data(prn
)) {
2754 table
= bgp_node_get_bgp_table_info(prn
);
2756 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2757 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2759 bgp_unlock_node(prn
);
2761 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2762 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2764 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2765 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2771 /* If this is an EVPN route, process for un-import. */
2772 if (safi
== SAFI_EVPN
)
2773 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2775 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2778 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2779 struct peer
*peer
, struct attr
*attr
,
2780 struct bgp_node
*rn
)
2782 struct bgp_path_info
*new;
2784 /* Make new BGP info. */
2785 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2787 new->instance
= instance
;
2788 new->sub_type
= sub_type
;
2791 new->uptime
= bgp_clock();
2796 static void overlay_index_update(struct attr
*attr
,
2797 struct eth_segment_id
*eth_s_id
,
2798 union gw_addr
*gw_ip
)
2803 if (eth_s_id
== NULL
) {
2804 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2805 sizeof(struct eth_segment_id
));
2807 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2808 sizeof(struct eth_segment_id
));
2810 if (gw_ip
== NULL
) {
2811 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2813 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2814 sizeof(union gw_addr
));
2818 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2819 struct eth_segment_id
*eth_s_id
,
2820 union gw_addr
*gw_ip
)
2822 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2823 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2825 struct eth_segment_id esi
;
2829 if (afi
!= AFI_L2VPN
)
2832 memset(&temp
, 0, sizeof(temp
));
2833 path_eth_s_id
= &temp
.esi
;
2834 path_gw_ip
= &temp
.ip
;
2836 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2839 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2840 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2843 if (gw_ip
== NULL
) {
2844 memset(&temp
, 0, sizeof(temp
));
2845 path_gw_ip_remote
= &temp
.ip
;
2847 path_gw_ip_remote
= gw_ip
;
2849 if (eth_s_id
== NULL
) {
2850 memset(&temp
, 0, sizeof(temp
));
2851 path_eth_s_id_remote
= &temp
.esi
;
2853 path_eth_s_id_remote
= eth_s_id
;
2855 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2858 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2859 sizeof(struct eth_segment_id
));
2862 /* Check if received nexthop is valid or not. */
2863 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2868 /* Only validated for unicast and multicast currently. */
2869 /* Also valid for EVPN where the nexthop is an IP address. */
2870 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2873 /* If NEXT_HOP is present, validate it. */
2874 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2875 if (attr
->nexthop
.s_addr
== 0
2876 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2877 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2881 /* If MP_NEXTHOP is present, validate it. */
2882 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2883 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2884 * it is not an IPv6 link-local address.
2886 if (attr
->mp_nexthop_len
) {
2887 switch (attr
->mp_nexthop_len
) {
2888 case BGP_ATTR_NHLEN_IPV4
:
2889 case BGP_ATTR_NHLEN_VPNV4
:
2890 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2891 || IPV4_CLASS_DE(ntohl(
2892 attr
->mp_nexthop_global_in
.s_addr
))
2893 || bgp_nexthop_self(bgp
,
2894 attr
->mp_nexthop_global_in
));
2897 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2898 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2899 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2900 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2901 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2902 || IN6_IS_ADDR_MULTICAST(
2903 &attr
->mp_nexthop_global
));
2915 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2916 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2917 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2918 uint32_t num_labels
, int soft_reconfig
,
2919 struct bgp_route_evpn
*evpn
)
2922 int aspath_loop_count
= 0;
2923 struct bgp_node
*rn
;
2925 struct attr new_attr
;
2926 struct attr
*attr_new
;
2927 struct bgp_path_info
*pi
;
2928 struct bgp_path_info
*new;
2929 struct bgp_path_info_extra
*extra
;
2931 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2933 int do_loop_check
= 1;
2934 int has_valid_label
= 0;
2936 int vnc_implicit_withdraw
= 0;
2940 memset(&new_attr
, 0, sizeof(struct attr
));
2941 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2942 new_attr
.label
= MPLS_INVALID_LABEL
;
2945 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2946 /* TODO: Check to see if we can get rid of "is_valid_label" */
2947 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2948 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2950 has_valid_label
= bgp_is_valid_label(label
);
2952 /* When peer's soft reconfiguration enabled. Record input packet in
2955 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2956 && peer
!= bgp
->peer_self
)
2957 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2959 /* Check previously received route. */
2960 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
2961 if (pi
->peer
== peer
&& pi
->type
== type
2962 && pi
->sub_type
== sub_type
2963 && pi
->addpath_rx_id
== addpath_id
)
2966 /* AS path local-as loop check. */
2967 if (peer
->change_local_as
) {
2968 if (peer
->allowas_in
[afi
][safi
])
2969 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2970 else if (!CHECK_FLAG(peer
->flags
,
2971 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2972 aspath_loop_count
= 1;
2974 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2975 > aspath_loop_count
) {
2976 reason
= "as-path contains our own AS;";
2981 /* If the peer is configured for "allowas-in origin" and the last ASN in
2983 * as-path is our ASN then we do not need to call aspath_loop_check
2985 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2986 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2989 /* AS path loop check. */
2990 if (do_loop_check
) {
2991 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2992 > peer
->allowas_in
[afi
][safi
]
2993 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2994 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2995 > peer
->allowas_in
[afi
][safi
])) {
2996 reason
= "as-path contains our own AS;";
3001 /* Route reflector originator ID check. */
3002 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3003 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3004 reason
= "originator is us;";
3008 /* Route reflector cluster ID check. */
3009 if (bgp_cluster_filter(peer
, attr
)) {
3010 reason
= "reflected from the same cluster;";
3014 /* Apply incoming filter. */
3015 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3020 bgp_attr_dup(&new_attr
, attr
);
3022 /* Apply incoming route-map.
3023 * NB: new_attr may now contain newly allocated values from route-map
3025 * commands, so we need bgp_attr_flush in the error paths, until we
3027 * the attr (which takes over the memory references) */
3028 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3030 reason
= "route-map;";
3031 bgp_attr_flush(&new_attr
);
3035 if (peer
->sort
== BGP_PEER_EBGP
) {
3037 /* If we receive the graceful-shutdown community from an eBGP
3038 * peer we must lower local-preference */
3039 if (new_attr
.community
3040 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3041 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3042 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3044 /* If graceful-shutdown is configured then add the GSHUT
3045 * community to all paths received from eBGP peers */
3046 } else if (bgp_flag_check(peer
->bgp
,
3047 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3048 bgp_attr_add_gshut_community(&new_attr
);
3052 /* next hop check. */
3053 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3054 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3055 reason
= "martian or self next-hop;";
3056 bgp_attr_flush(&new_attr
);
3060 attr_new
= bgp_attr_intern(&new_attr
);
3062 /* If the update is implicit withdraw. */
3064 pi
->uptime
= bgp_clock();
3065 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3067 /* Same attribute comes in. */
3068 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3069 && attrhash_cmp(pi
->attr
, attr_new
)
3070 && (!has_valid_label
3071 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3072 num_labels
* sizeof(mpls_label_t
))
3074 && (overlay_index_equal(
3075 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3076 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3077 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3078 BGP_CONFIG_DAMPENING
)
3079 && peer
->sort
== BGP_PEER_EBGP
3080 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3081 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3082 bgp_debug_rdpfxpath2str(
3083 afi
, safi
, prd
, p
, label
,
3084 num_labels
, addpath_id
? 1 : 0,
3085 addpath_id
, pfx_buf
,
3087 zlog_debug("%s rcvd %s", peer
->host
,
3091 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3092 != BGP_DAMP_SUPPRESSED
) {
3093 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3095 bgp_process(bgp
, rn
, afi
, safi
);
3097 } else /* Duplicate - odd */
3099 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3100 if (!peer
->rcvd_attr_printed
) {
3102 "%s rcvd UPDATE w/ attr: %s",
3104 peer
->rcvd_attr_str
);
3105 peer
->rcvd_attr_printed
= 1;
3108 bgp_debug_rdpfxpath2str(
3109 afi
, safi
, prd
, p
, label
,
3110 num_labels
, addpath_id
? 1 : 0,
3111 addpath_id
, pfx_buf
,
3114 "%s rcvd %s...duplicate ignored",
3115 peer
->host
, pfx_buf
);
3118 /* graceful restart STALE flag unset. */
3119 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3120 bgp_path_info_unset_flag(
3121 rn
, pi
, BGP_PATH_STALE
);
3122 bgp_process(bgp
, rn
, afi
, safi
);
3126 bgp_unlock_node(rn
);
3127 bgp_attr_unintern(&attr_new
);
3132 /* Withdraw/Announce before we fully processed the withdraw */
3133 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3134 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3135 bgp_debug_rdpfxpath2str(
3136 afi
, safi
, prd
, p
, label
, num_labels
,
3137 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3140 "%s rcvd %s, flapped quicker than processing",
3141 peer
->host
, pfx_buf
);
3144 bgp_path_info_restore(rn
, pi
);
3147 /* Received Logging. */
3148 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3149 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3150 num_labels
, addpath_id
? 1 : 0,
3151 addpath_id
, pfx_buf
,
3153 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3156 /* graceful restart STALE flag unset. */
3157 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3158 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3160 /* The attribute is changed. */
3161 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3163 /* implicit withdraw, decrement aggregate and pcount here.
3164 * only if update is accepted, they'll increment below.
3166 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3168 /* Update bgp route dampening information. */
3169 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3170 && peer
->sort
== BGP_PEER_EBGP
) {
3171 /* This is implicit withdraw so we should update
3174 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3175 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3178 if (safi
== SAFI_MPLS_VPN
) {
3179 struct bgp_node
*prn
= NULL
;
3180 struct bgp_table
*table
= NULL
;
3182 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3183 (struct prefix
*)prd
);
3184 if (bgp_node_has_bgp_path_info_data(prn
)) {
3185 table
= bgp_node_get_bgp_table_info(prn
);
3187 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3188 bgp
, prd
, table
, p
, pi
);
3190 bgp_unlock_node(prn
);
3192 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3193 && (safi
== SAFI_UNICAST
)) {
3194 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3196 * Implicit withdraw case.
3198 ++vnc_implicit_withdraw
;
3199 vnc_import_bgp_del_route(bgp
, p
, pi
);
3200 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3205 /* Special handling for EVPN update of an existing route. If the
3206 * extended community attribute has changed, we need to
3208 * the route using its existing extended community. It will be
3209 * subsequently processed for import with the new extended
3212 if (safi
== SAFI_EVPN
&& !same_attr
) {
3214 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3216 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3219 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3220 attr_new
->ecommunity
);
3222 if (bgp_debug_update(peer
, p
, NULL
, 1))
3224 "Change in EXT-COMM, existing %s new %s",
3226 pi
->attr
->ecommunity
),
3228 attr_new
->ecommunity
));
3229 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3235 /* Update to new attribute. */
3236 bgp_attr_unintern(&pi
->attr
);
3237 pi
->attr
= attr_new
;
3239 /* Update MPLS label */
3240 if (has_valid_label
) {
3241 extra
= bgp_path_info_extra_get(pi
);
3242 memcpy(&extra
->label
, label
,
3243 num_labels
* sizeof(mpls_label_t
));
3244 extra
->num_labels
= num_labels
;
3245 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3246 bgp_set_valid_label(&extra
->label
[0]);
3250 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3251 && (safi
== SAFI_UNICAST
)) {
3252 if (vnc_implicit_withdraw
) {
3254 * Add back the route with its new attributes
3256 * The route is still selected, until the route
3258 * queued by bgp_process actually runs. We have
3260 * update to the VNC side immediately to avoid
3262 * configuration changes (e.g., route-map
3264 * trigger re-importation of the entire RIB.
3266 vnc_import_bgp_add_route(bgp
, p
, pi
);
3267 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3271 /* Update Overlay Index */
3272 if (afi
== AFI_L2VPN
) {
3273 overlay_index_update(
3274 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3275 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3278 /* Update bgp route dampening information. */
3279 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3280 && peer
->sort
== BGP_PEER_EBGP
) {
3281 /* Now we do normal update dampening. */
3282 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3283 if (ret
== BGP_DAMP_SUPPRESSED
) {
3284 bgp_unlock_node(rn
);
3289 /* Nexthop reachability check - for unicast and
3290 * labeled-unicast.. */
3291 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3292 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3293 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3294 && !CHECK_FLAG(peer
->flags
,
3295 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3297 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3302 struct bgp
*bgp_nexthop
= bgp
;
3304 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3305 bgp_nexthop
= pi
->extra
->bgp_orig
;
3307 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3309 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3310 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3312 if (BGP_DEBUG(nht
, NHT
)) {
3313 char buf1
[INET6_ADDRSTRLEN
];
3315 (const void *)&attr_new
3317 buf1
, INET6_ADDRSTRLEN
);
3318 zlog_debug("%s(%s): NH unresolved",
3319 __FUNCTION__
, buf1
);
3321 bgp_path_info_unset_flag(rn
, pi
,
3325 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3328 if (safi
== SAFI_MPLS_VPN
) {
3329 struct bgp_node
*prn
= NULL
;
3330 struct bgp_table
*table
= NULL
;
3332 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3333 (struct prefix
*)prd
);
3334 if (bgp_node_has_bgp_path_info_data(prn
)) {
3335 table
= bgp_node_get_bgp_table_info(prn
);
3337 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3338 bgp
, prd
, table
, p
, pi
);
3340 bgp_unlock_node(prn
);
3344 /* If this is an EVPN route and some attribute has changed,
3346 * route for import. If the extended community has changed, we
3348 * have done the un-import earlier and the import would result
3350 * route getting injected into appropriate L2 VNIs. If it is
3352 * some other attribute change, the import will result in
3354 * the attributes for the route in the VNI(s).
3356 if (safi
== SAFI_EVPN
&& !same_attr
)
3357 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3359 /* Process change. */
3360 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3362 bgp_process(bgp
, rn
, afi
, safi
);
3363 bgp_unlock_node(rn
);
3365 if (SAFI_UNICAST
== safi
3366 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3367 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3369 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3371 if ((SAFI_MPLS_VPN
== safi
)
3372 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3374 vpn_leak_to_vrf_update(bgp
, pi
);
3378 if (SAFI_MPLS_VPN
== safi
) {
3379 mpls_label_t label_decoded
= decode_label(label
);
3381 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3382 type
, sub_type
, &label_decoded
);
3384 if (SAFI_ENCAP
== safi
) {
3385 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3386 type
, sub_type
, NULL
);
3391 } // End of implicit withdraw
3393 /* Received Logging. */
3394 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3395 if (!peer
->rcvd_attr_printed
) {
3396 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3397 peer
->rcvd_attr_str
);
3398 peer
->rcvd_attr_printed
= 1;
3401 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3402 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3404 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3407 /* Make new BGP info. */
3408 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3410 /* Update MPLS label */
3411 if (has_valid_label
) {
3412 extra
= bgp_path_info_extra_get(new);
3413 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3414 extra
->num_labels
= num_labels
;
3415 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3416 bgp_set_valid_label(&extra
->label
[0]);
3419 /* Update Overlay Index */
3420 if (afi
== AFI_L2VPN
) {
3421 overlay_index_update(new->attr
,
3422 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3423 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3425 /* Nexthop reachability check. */
3426 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3427 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3428 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3429 && !CHECK_FLAG(peer
->flags
,
3430 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3431 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3436 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3437 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3438 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3440 if (BGP_DEBUG(nht
, NHT
)) {
3441 char buf1
[INET6_ADDRSTRLEN
];
3443 (const void *)&attr_new
->nexthop
,
3444 buf1
, INET6_ADDRSTRLEN
);
3445 zlog_debug("%s(%s): NH unresolved",
3446 __FUNCTION__
, buf1
);
3448 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3451 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3454 new->addpath_rx_id
= addpath_id
;
3456 /* Increment prefix */
3457 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3459 /* Register new BGP information. */
3460 bgp_path_info_add(rn
, new);
3462 /* route_node_get lock */
3463 bgp_unlock_node(rn
);
3466 if (safi
== SAFI_MPLS_VPN
) {
3467 struct bgp_node
*prn
= NULL
;
3468 struct bgp_table
*table
= NULL
;
3470 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3471 if (bgp_node_has_bgp_path_info_data(prn
)) {
3472 table
= bgp_node_get_bgp_table_info(prn
);
3474 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3475 bgp
, prd
, table
, p
, new);
3477 bgp_unlock_node(prn
);
3481 /* If maximum prefix count is configured and current prefix
3483 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3486 /* If this is an EVPN route, process for import. */
3487 if (safi
== SAFI_EVPN
)
3488 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3490 /* Process change. */
3491 bgp_process(bgp
, rn
, afi
, safi
);
3493 if (SAFI_UNICAST
== safi
3494 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3495 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3496 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3498 if ((SAFI_MPLS_VPN
== safi
)
3499 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3501 vpn_leak_to_vrf_update(bgp
, new);
3504 if (SAFI_MPLS_VPN
== safi
) {
3505 mpls_label_t label_decoded
= decode_label(label
);
3507 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3508 sub_type
, &label_decoded
);
3510 if (SAFI_ENCAP
== safi
) {
3511 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3518 /* This BGP update is filtered. Log the reason then update BGP
3521 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3522 if (!peer
->rcvd_attr_printed
) {
3523 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3524 peer
->rcvd_attr_str
);
3525 peer
->rcvd_attr_printed
= 1;
3528 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3529 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3531 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3532 peer
->host
, pfx_buf
, reason
);
3536 /* If this is an EVPN route, un-import it as it is now filtered.
3538 if (safi
== SAFI_EVPN
)
3539 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3541 if (SAFI_UNICAST
== safi
3542 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3543 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3545 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3547 if ((SAFI_MPLS_VPN
== safi
)
3548 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3550 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3553 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3556 bgp_unlock_node(rn
);
3560 * Filtered update is treated as an implicit withdrawal (see
3562 * a few lines above)
3564 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3565 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3573 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3574 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3575 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3576 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3579 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3580 struct bgp_node
*rn
;
3581 struct bgp_path_info
*pi
;
3584 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3585 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3593 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3595 /* If peer is soft reconfiguration enabled. Record input packet for
3596 * further calculation.
3598 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3599 * routes that are filtered. This tanks out Quagga RS pretty badly due
3601 * the iteration over all RS clients.
3602 * Since we need to remove the entry from adj_in anyway, do that first
3604 * if there was no entry, we don't need to do anything more.
3606 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3607 && peer
!= bgp
->peer_self
)
3608 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3609 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3610 bgp_debug_rdpfxpath2str(
3611 afi
, safi
, prd
, p
, label
, num_labels
,
3612 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3615 "%s withdrawing route %s not in adj-in",
3616 peer
->host
, pfx_buf
);
3618 bgp_unlock_node(rn
);
3622 /* Lookup withdrawn route. */
3623 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3624 if (pi
->peer
== peer
&& pi
->type
== type
3625 && pi
->sub_type
== sub_type
3626 && pi
->addpath_rx_id
== addpath_id
)
3630 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3631 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3632 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3634 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3638 /* Withdraw specified route from routing table. */
3639 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3640 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3641 if (SAFI_UNICAST
== safi
3642 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3643 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3644 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3646 if ((SAFI_MPLS_VPN
== safi
)
3647 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3649 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3651 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3652 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3653 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3655 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3658 /* Unlock bgp_node_get() lock. */
3659 bgp_unlock_node(rn
);
3664 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3667 struct update_subgroup
*subgrp
;
3668 subgrp
= peer_subgroup(peer
, afi
, safi
);
3669 subgroup_default_originate(subgrp
, withdraw
);
3674 * bgp_stop_announce_route_timer
3676 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3678 if (!paf
->t_announce_route
)
3681 THREAD_TIMER_OFF(paf
->t_announce_route
);
3685 * bgp_announce_route_timer_expired
3687 * Callback that is invoked when the route announcement timer for a
3690 static int bgp_announce_route_timer_expired(struct thread
*t
)
3692 struct peer_af
*paf
;
3695 paf
= THREAD_ARG(t
);
3698 if (peer
->status
!= Established
)
3701 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3704 peer_af_announce_route(paf
, 1);
3709 * bgp_announce_route
3711 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3713 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3715 struct peer_af
*paf
;
3716 struct update_subgroup
*subgrp
;
3718 paf
= peer_af_find(peer
, afi
, safi
);
3721 subgrp
= PAF_SUBGRP(paf
);
3724 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3725 * or a refresh has already been triggered.
3727 if (!subgrp
|| paf
->t_announce_route
)
3731 * Start a timer to stagger/delay the announce. This serves
3732 * two purposes - announcement can potentially be combined for
3733 * multiple peers and the announcement doesn't happen in the
3736 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3737 (subgrp
->peer_count
== 1)
3738 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3739 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3740 &paf
->t_announce_route
);
3744 * Announce routes from all AF tables to a peer.
3746 * This should ONLY be called when there is a need to refresh the
3747 * routes to the peer based on a policy change for this peer alone
3748 * or a route refresh request received from the peer.
3749 * The operation will result in splitting the peer from its existing
3750 * subgroups and putting it in new subgroups.
3752 void bgp_announce_route_all(struct peer
*peer
)
3757 FOREACH_AFI_SAFI (afi
, safi
)
3758 bgp_announce_route(peer
, afi
, safi
);
3761 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3762 struct bgp_table
*table
,
3763 struct prefix_rd
*prd
)
3766 struct bgp_node
*rn
;
3767 struct bgp_adj_in
*ain
;
3770 table
= peer
->bgp
->rib
[afi
][safi
];
3772 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3773 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3774 if (ain
->peer
!= peer
)
3777 struct bgp_path_info
*pi
=
3778 bgp_node_get_bgp_path_info(rn
);
3779 uint32_t num_labels
= 0;
3780 mpls_label_t
*label_pnt
= NULL
;
3782 if (pi
&& pi
->extra
)
3783 num_labels
= pi
->extra
->num_labels
;
3785 label_pnt
= &pi
->extra
->label
[0];
3787 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3788 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3789 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3790 num_labels
, 1, NULL
);
3793 bgp_unlock_node(rn
);
3799 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3801 struct bgp_node
*rn
;
3802 struct bgp_table
*table
;
3804 if (peer
->status
!= Established
)
3807 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3808 && (safi
!= SAFI_EVPN
))
3809 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3811 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3812 rn
= bgp_route_next(rn
)) {
3813 table
= bgp_node_get_bgp_table_info(rn
);
3814 if (table
!= NULL
) {
3815 struct prefix_rd prd
;
3817 prd
.family
= AF_UNSPEC
;
3819 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3821 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3828 struct bgp_clear_node_queue
{
3829 struct bgp_node
*rn
;
3832 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3834 struct bgp_clear_node_queue
*cnq
= data
;
3835 struct bgp_node
*rn
= cnq
->rn
;
3836 struct peer
*peer
= wq
->spec
.data
;
3837 struct bgp_path_info
*pi
;
3839 afi_t afi
= bgp_node_table(rn
)->afi
;
3840 safi_t safi
= bgp_node_table(rn
)->safi
;
3845 /* It is possible that we have multiple paths for a prefix from a peer
3846 * if that peer is using AddPath.
3848 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3849 if (pi
->peer
!= peer
)
3852 /* graceful restart STALE flag set. */
3853 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3854 && peer
->nsf
[afi
][safi
]
3855 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3856 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3857 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3859 /* If this is an EVPN route, process for
3861 if (safi
== SAFI_EVPN
)
3862 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3864 /* Handle withdraw for VRF route-leaking and L3VPN */
3865 if (SAFI_UNICAST
== safi
3866 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3867 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3868 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3871 if (SAFI_MPLS_VPN
== safi
&&
3872 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3873 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3876 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3882 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3884 struct bgp_clear_node_queue
*cnq
= data
;
3885 struct bgp_node
*rn
= cnq
->rn
;
3886 struct bgp_table
*table
= bgp_node_table(rn
);
3888 bgp_unlock_node(rn
);
3889 bgp_table_unlock(table
);
3890 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3893 static void bgp_clear_node_complete(struct work_queue
*wq
)
3895 struct peer
*peer
= wq
->spec
.data
;
3897 /* Tickle FSM to start moving again */
3898 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3900 peer_unlock(peer
); /* bgp_clear_route */
3903 static void bgp_clear_node_queue_init(struct peer
*peer
)
3905 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3907 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3908 #undef CLEAR_QUEUE_NAME_LEN
3910 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3911 peer
->clear_node_queue
->spec
.hold
= 10;
3912 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3913 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3914 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3915 peer
->clear_node_queue
->spec
.max_retries
= 0;
3917 /* we only 'lock' this peer reference when the queue is actually active
3919 peer
->clear_node_queue
->spec
.data
= peer
;
3922 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3923 struct bgp_table
*table
)
3925 struct bgp_node
*rn
;
3926 int force
= bm
->process_main_queue
? 0 : 1;
3929 table
= peer
->bgp
->rib
[afi
][safi
];
3931 /* If still no table => afi/safi isn't configured at all or smth. */
3935 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3936 struct bgp_path_info
*pi
, *next
;
3937 struct bgp_adj_in
*ain
;
3938 struct bgp_adj_in
*ain_next
;
3940 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3941 * queued for every clearing peer, regardless of whether it is
3942 * relevant to the peer at hand.
3944 * Overview: There are 3 different indices which need to be
3945 * scrubbed, potentially, when a peer is removed:
3947 * 1 peer's routes visible via the RIB (ie accepted routes)
3948 * 2 peer's routes visible by the (optional) peer's adj-in index
3949 * 3 other routes visible by the peer's adj-out index
3951 * 3 there is no hurry in scrubbing, once the struct peer is
3952 * removed from bgp->peer, we could just GC such deleted peer's
3953 * adj-outs at our leisure.
3955 * 1 and 2 must be 'scrubbed' in some way, at least made
3956 * invisible via RIB index before peer session is allowed to be
3957 * brought back up. So one needs to know when such a 'search' is
3962 * - there'd be a single global queue or a single RIB walker
3963 * - rather than tracking which route_nodes still need to be
3964 * examined on a peer basis, we'd track which peers still
3967 * Given that our per-peer prefix-counts now should be reliable,
3968 * this may actually be achievable. It doesn't seem to be a huge
3969 * problem at this time,
3971 * It is possible that we have multiple paths for a prefix from
3973 * if that peer is using AddPath.
3977 ain_next
= ain
->next
;
3979 if (ain
->peer
== peer
) {
3980 bgp_adj_in_remove(rn
, ain
);
3981 bgp_unlock_node(rn
);
3987 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
3989 if (pi
->peer
!= peer
)
3993 bgp_path_info_reap(rn
, pi
);
3995 struct bgp_clear_node_queue
*cnq
;
3997 /* both unlocked in bgp_clear_node_queue_del */
3998 bgp_table_lock(bgp_node_table(rn
));
4001 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4002 sizeof(struct bgp_clear_node_queue
));
4004 work_queue_add(peer
->clear_node_queue
, cnq
);
4012 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4014 struct bgp_node
*rn
;
4015 struct bgp_table
*table
;
4017 if (peer
->clear_node_queue
== NULL
)
4018 bgp_clear_node_queue_init(peer
);
4020 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4021 * Idle until it receives a Clearing_Completed event. This protects
4022 * against peers which flap faster than we can we clear, which could
4025 * a) race with routes from the new session being installed before
4026 * clear_route_node visits the node (to delete the route of that
4028 * b) resource exhaustion, clear_route_node likely leads to an entry
4029 * on the process_main queue. Fast-flapping could cause that queue
4033 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4034 * the unlock will happen upon work-queue completion; other wise, the
4035 * unlock happens at the end of this function.
4037 if (!peer
->clear_node_queue
->thread
)
4040 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4041 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4043 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4044 rn
= bgp_route_next(rn
)) {
4045 table
= bgp_node_get_bgp_table_info(rn
);
4049 bgp_clear_route_table(peer
, afi
, safi
, table
);
4052 /* unlock if no nodes got added to the clear-node-queue. */
4053 if (!peer
->clear_node_queue
->thread
)
4057 void bgp_clear_route_all(struct peer
*peer
)
4062 FOREACH_AFI_SAFI (afi
, safi
)
4063 bgp_clear_route(peer
, afi
, safi
);
4066 rfapiProcessPeerDown(peer
);
4070 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4072 struct bgp_table
*table
;
4073 struct bgp_node
*rn
;
4074 struct bgp_adj_in
*ain
;
4075 struct bgp_adj_in
*ain_next
;
4077 table
= peer
->bgp
->rib
[afi
][safi
];
4079 /* It is possible that we have multiple paths for a prefix from a peer
4080 * if that peer is using AddPath.
4082 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4086 ain_next
= ain
->next
;
4088 if (ain
->peer
== peer
) {
4089 bgp_adj_in_remove(rn
, ain
);
4090 bgp_unlock_node(rn
);
4098 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4100 struct bgp_node
*rn
;
4101 struct bgp_path_info
*pi
;
4102 struct bgp_table
*table
;
4104 if (safi
== SAFI_MPLS_VPN
) {
4105 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4106 rn
= bgp_route_next(rn
)) {
4107 struct bgp_node
*rm
;
4109 /* look for neighbor in tables */
4110 table
= bgp_node_get_bgp_table_info(rn
);
4114 for (rm
= bgp_table_top(table
); rm
;
4115 rm
= bgp_route_next(rm
))
4116 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4118 if (pi
->peer
!= peer
)
4120 if (!CHECK_FLAG(pi
->flags
,
4124 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4129 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4130 rn
= bgp_route_next(rn
))
4131 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4133 if (pi
->peer
!= peer
)
4135 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4137 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4143 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4146 struct bgp_node
*rn
;
4147 struct bgp_path_info
*pi
;
4148 struct bgp_path_info
*next
;
4150 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4151 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4153 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4154 && pi
->type
== ZEBRA_ROUTE_BGP
4155 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4156 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4157 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4159 if (bgp_fibupd_safi(safi
))
4160 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4162 bgp_path_info_reap(rn
, pi
);
4167 /* Delete all kernel routes. */
4168 void bgp_cleanup_routes(struct bgp
*bgp
)
4171 struct bgp_node
*rn
;
4172 struct bgp_table
*table
;
4174 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4175 if (afi
== AFI_L2VPN
)
4177 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4180 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4182 if (afi
!= AFI_L2VPN
) {
4184 safi
= SAFI_MPLS_VPN
;
4185 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4186 rn
= bgp_route_next(rn
)) {
4187 table
= bgp_node_get_bgp_table_info(rn
);
4188 if (table
!= NULL
) {
4189 bgp_cleanup_table(bgp
, table
, safi
);
4190 bgp_table_finish(&table
);
4191 bgp_node_set_bgp_table_info(rn
, NULL
);
4192 bgp_unlock_node(rn
);
4196 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4197 rn
= bgp_route_next(rn
)) {
4198 table
= bgp_node_get_bgp_table_info(rn
);
4199 if (table
!= NULL
) {
4200 bgp_cleanup_table(bgp
, table
, safi
);
4201 bgp_table_finish(&table
);
4202 bgp_node_set_bgp_table_info(rn
, NULL
);
4203 bgp_unlock_node(rn
);
4208 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4209 rn
= bgp_route_next(rn
)) {
4210 table
= bgp_node_get_bgp_table_info(rn
);
4211 if (table
!= NULL
) {
4212 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4213 bgp_table_finish(&table
);
4214 bgp_node_set_bgp_table_info(rn
, NULL
);
4215 bgp_unlock_node(rn
);
4220 void bgp_reset(void)
4223 bgp_zclient_reset();
4224 access_list_reset();
4225 prefix_list_reset();
4228 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4230 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4231 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4232 PEER_CAP_ADDPATH_AF_TX_RCV
));
4235 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4237 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4238 struct bgp_nlri
*packet
)
4247 int addpath_encoded
;
4248 uint32_t addpath_id
;
4251 lim
= pnt
+ packet
->length
;
4253 safi
= packet
->safi
;
4255 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4257 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4258 syntactic validity. If the field is syntactically incorrect,
4259 then the Error Subcode is set to Invalid Network Field. */
4260 for (; pnt
< lim
; pnt
+= psize
) {
4261 /* Clear prefix structure. */
4262 memset(&p
, 0, sizeof(struct prefix
));
4264 if (addpath_encoded
) {
4266 /* When packet overflow occurs return immediately. */
4267 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4270 addpath_id
= ntohl(*((uint32_t *)pnt
));
4271 pnt
+= BGP_ADDPATH_ID_LEN
;
4274 /* Fetch prefix length. */
4275 p
.prefixlen
= *pnt
++;
4276 /* afi/safi validity already verified by caller,
4277 * bgp_update_receive */
4278 p
.family
= afi2family(afi
);
4280 /* Prefix length check. */
4281 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4284 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4285 peer
->host
, p
.prefixlen
, packet
->afi
);
4289 /* Packet size overflow check. */
4290 psize
= PSIZE(p
.prefixlen
);
4292 /* When packet overflow occur return immediately. */
4293 if (pnt
+ psize
> lim
) {
4296 "%s [Error] Update packet error (prefix length %d overflows packet)",
4297 peer
->host
, p
.prefixlen
);
4301 /* Defensive coding, double-check the psize fits in a struct
4303 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4306 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4307 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4311 /* Fetch prefix from NLRI packet. */
4312 memcpy(p
.u
.val
, pnt
, psize
);
4314 /* Check address. */
4315 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4316 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4317 /* From RFC4271 Section 6.3:
4319 * If a prefix in the NLRI field is semantically
4321 * (e.g., an unexpected multicast IP address),
4323 * be logged locally, and the prefix SHOULD be
4328 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4329 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4334 /* Check address. */
4335 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4336 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4341 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4343 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4348 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4353 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4355 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4362 /* Normal process. */
4364 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4365 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4366 NULL
, NULL
, 0, 0, NULL
);
4368 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4369 safi
, ZEBRA_ROUTE_BGP
,
4370 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4373 /* Address family configuration mismatch or maximum-prefix count
4379 /* Packet length consistency check. */
4383 "%s [Error] Update packet error (prefix length mismatch with total length)",
4391 static struct bgp_static
*bgp_static_new(void)
4393 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4396 static void bgp_static_free(struct bgp_static
*bgp_static
)
4398 if (bgp_static
->rmap
.name
)
4399 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4400 if (bgp_static
->eth_s_id
)
4401 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4402 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4405 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4406 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4408 struct bgp_node
*rn
;
4409 struct bgp_path_info
*pi
;
4410 struct bgp_path_info
*new;
4411 struct bgp_path_info rmap_path
;
4413 struct attr
*attr_new
;
4416 int vnc_implicit_withdraw
= 0;
4423 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4425 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4427 attr
.nexthop
= bgp_static
->igpnexthop
;
4428 attr
.med
= bgp_static
->igpmetric
;
4429 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4431 if (bgp_static
->atomic
)
4432 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4434 /* Store label index, if required. */
4435 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4436 attr
.label_index
= bgp_static
->label_index
;
4437 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4440 /* Apply route-map. */
4441 if (bgp_static
->rmap
.name
) {
4442 struct attr attr_tmp
= attr
;
4444 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4445 rmap_path
.peer
= bgp
->peer_self
;
4446 rmap_path
.attr
= &attr_tmp
;
4448 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4450 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4453 bgp
->peer_self
->rmap_type
= 0;
4455 if (ret
== RMAP_DENYMATCH
) {
4456 /* Free uninterned attribute. */
4457 bgp_attr_flush(&attr_tmp
);
4459 /* Unintern original. */
4460 aspath_unintern(&attr
.aspath
);
4461 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4465 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4466 bgp_attr_add_gshut_community(&attr_tmp
);
4468 attr_new
= bgp_attr_intern(&attr_tmp
);
4471 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4472 bgp_attr_add_gshut_community(&attr
);
4474 attr_new
= bgp_attr_intern(&attr
);
4477 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4478 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4479 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4483 if (attrhash_cmp(pi
->attr
, attr_new
)
4484 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4485 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4486 bgp_unlock_node(rn
);
4487 bgp_attr_unintern(&attr_new
);
4488 aspath_unintern(&attr
.aspath
);
4491 /* The attribute is changed. */
4492 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4494 /* Rewrite BGP route information. */
4495 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4496 bgp_path_info_restore(rn
, pi
);
4498 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4500 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4501 && (safi
== SAFI_UNICAST
)) {
4502 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4504 * Implicit withdraw case.
4505 * We have to do this before pi is
4508 ++vnc_implicit_withdraw
;
4509 vnc_import_bgp_del_route(bgp
, p
, pi
);
4510 vnc_import_bgp_exterior_del_route(
4515 bgp_attr_unintern(&pi
->attr
);
4516 pi
->attr
= attr_new
;
4517 pi
->uptime
= bgp_clock();
4519 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4520 && (safi
== SAFI_UNICAST
)) {
4521 if (vnc_implicit_withdraw
) {
4522 vnc_import_bgp_add_route(bgp
, p
, pi
);
4523 vnc_import_bgp_exterior_add_route(
4529 /* Nexthop reachability check. */
4530 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4531 && (safi
== SAFI_UNICAST
4532 || safi
== SAFI_LABELED_UNICAST
)) {
4534 struct bgp
*bgp_nexthop
= bgp
;
4536 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4537 bgp_nexthop
= pi
->extra
->bgp_orig
;
4539 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4541 bgp_path_info_set_flag(rn
, pi
,
4544 if (BGP_DEBUG(nht
, NHT
)) {
4545 char buf1
[INET6_ADDRSTRLEN
];
4546 inet_ntop(p
->family
,
4550 "%s(%s): Route not in table, not advertising",
4551 __FUNCTION__
, buf1
);
4553 bgp_path_info_unset_flag(
4554 rn
, pi
, BGP_PATH_VALID
);
4557 /* Delete the NHT structure if any, if we're
4559 * enabling/disabling import check. We
4560 * deregister the route
4561 * from NHT to avoid overloading NHT and the
4562 * process interaction
4564 bgp_unlink_nexthop(pi
);
4565 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4567 /* Process change. */
4568 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4569 bgp_process(bgp
, rn
, afi
, safi
);
4571 if (SAFI_UNICAST
== safi
4572 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4574 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4575 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4579 bgp_unlock_node(rn
);
4580 aspath_unintern(&attr
.aspath
);
4585 /* Make new BGP info. */
4586 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4588 /* Nexthop reachability check. */
4589 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4590 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4591 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4592 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4594 if (BGP_DEBUG(nht
, NHT
)) {
4595 char buf1
[INET6_ADDRSTRLEN
];
4596 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4599 "%s(%s): Route not in table, not advertising",
4600 __FUNCTION__
, buf1
);
4602 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4605 /* Delete the NHT structure if any, if we're toggling between
4606 * enabling/disabling import check. We deregister the route
4607 * from NHT to avoid overloading NHT and the process interaction
4609 bgp_unlink_nexthop(new);
4611 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4614 /* Aggregate address increment. */
4615 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4617 /* Register new BGP information. */
4618 bgp_path_info_add(rn
, new);
4620 /* route_node_get lock */
4621 bgp_unlock_node(rn
);
4623 /* Process change. */
4624 bgp_process(bgp
, rn
, afi
, safi
);
4626 if (SAFI_UNICAST
== safi
4627 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4628 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4629 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4632 /* Unintern original. */
4633 aspath_unintern(&attr
.aspath
);
4636 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4639 struct bgp_node
*rn
;
4640 struct bgp_path_info
*pi
;
4642 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4644 /* Check selected route and self inserted route. */
4645 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4646 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4647 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4650 /* Withdraw static BGP route from routing table. */
4652 if (SAFI_UNICAST
== safi
4653 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4654 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4655 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4657 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4658 bgp_unlink_nexthop(pi
);
4659 bgp_path_info_delete(rn
, pi
);
4660 bgp_process(bgp
, rn
, afi
, safi
);
4663 /* Unlock bgp_node_lookup. */
4664 bgp_unlock_node(rn
);
4668 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4670 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4671 afi_t afi
, safi_t safi
,
4672 struct prefix_rd
*prd
)
4674 struct bgp_node
*rn
;
4675 struct bgp_path_info
*pi
;
4677 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4679 /* Check selected route and self inserted route. */
4680 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4681 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4682 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4685 /* Withdraw static BGP route from routing table. */
4688 rfapiProcessWithdraw(
4689 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4690 1); /* Kill, since it is an administrative change */
4692 if (SAFI_MPLS_VPN
== safi
4693 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4694 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4696 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4697 bgp_path_info_delete(rn
, pi
);
4698 bgp_process(bgp
, rn
, afi
, safi
);
4701 /* Unlock bgp_node_lookup. */
4702 bgp_unlock_node(rn
);
4705 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4706 struct bgp_static
*bgp_static
, afi_t afi
,
4709 struct bgp_node
*rn
;
4710 struct bgp_path_info
*new;
4711 struct attr
*attr_new
;
4712 struct attr attr
= {0};
4713 struct bgp_path_info
*pi
;
4715 mpls_label_t label
= 0;
4717 uint32_t num_labels
= 0;
4722 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4724 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4727 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4729 attr
.nexthop
= bgp_static
->igpnexthop
;
4730 attr
.med
= bgp_static
->igpmetric
;
4731 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4733 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4734 || (safi
== SAFI_ENCAP
)) {
4735 if (afi
== AFI_IP
) {
4736 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4737 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4740 if (afi
== AFI_L2VPN
) {
4741 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4743 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4744 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4745 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4746 sizeof(struct in6_addr
));
4747 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4748 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4749 struct bgp_encap_type_vxlan bet
;
4750 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4751 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4752 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4754 if (bgp_static
->router_mac
) {
4755 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4758 /* Apply route-map. */
4759 if (bgp_static
->rmap
.name
) {
4760 struct attr attr_tmp
= attr
;
4761 struct bgp_path_info rmap_path
;
4764 rmap_path
.peer
= bgp
->peer_self
;
4765 rmap_path
.attr
= &attr_tmp
;
4767 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4769 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4772 bgp
->peer_self
->rmap_type
= 0;
4774 if (ret
== RMAP_DENYMATCH
) {
4775 /* Free uninterned attribute. */
4776 bgp_attr_flush(&attr_tmp
);
4778 /* Unintern original. */
4779 aspath_unintern(&attr
.aspath
);
4780 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4785 attr_new
= bgp_attr_intern(&attr_tmp
);
4787 attr_new
= bgp_attr_intern(&attr
);
4790 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4791 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4792 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4796 memset(&add
, 0, sizeof(union gw_addr
));
4797 if (attrhash_cmp(pi
->attr
, attr_new
)
4798 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4799 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4800 bgp_unlock_node(rn
);
4801 bgp_attr_unintern(&attr_new
);
4802 aspath_unintern(&attr
.aspath
);
4805 /* The attribute is changed. */
4806 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4808 /* Rewrite BGP route information. */
4809 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4810 bgp_path_info_restore(rn
, pi
);
4812 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4813 bgp_attr_unintern(&pi
->attr
);
4814 pi
->attr
= attr_new
;
4815 pi
->uptime
= bgp_clock();
4818 label
= decode_label(&pi
->extra
->label
[0]);
4821 /* Process change. */
4822 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4823 bgp_process(bgp
, rn
, afi
, safi
);
4825 if (SAFI_MPLS_VPN
== safi
4826 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4827 vpn_leak_to_vrf_update(bgp
, pi
);
4830 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4831 pi
->attr
, afi
, safi
, pi
->type
,
4832 pi
->sub_type
, &label
);
4834 bgp_unlock_node(rn
);
4835 aspath_unintern(&attr
.aspath
);
4841 /* Make new BGP info. */
4842 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4844 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4845 new->extra
= bgp_path_info_extra_new();
4847 new->extra
->label
[0] = bgp_static
->label
;
4848 new->extra
->num_labels
= num_labels
;
4851 label
= decode_label(&bgp_static
->label
);
4854 /* Aggregate address increment. */
4855 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4857 /* Register new BGP information. */
4858 bgp_path_info_add(rn
, new);
4859 /* route_node_get lock */
4860 bgp_unlock_node(rn
);
4862 /* Process change. */
4863 bgp_process(bgp
, rn
, afi
, safi
);
4865 if (SAFI_MPLS_VPN
== safi
4866 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4867 vpn_leak_to_vrf_update(bgp
, new);
4870 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4871 safi
, new->type
, new->sub_type
, &label
);
4874 /* Unintern original. */
4875 aspath_unintern(&attr
.aspath
);
4878 /* Configure static BGP network. When user don't run zebra, static
4879 route should be installed as valid. */
4880 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4881 const char *ip_str
, afi_t afi
, safi_t safi
,
4882 const char *rmap
, int backdoor
, uint32_t label_index
)
4884 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4887 struct bgp_static
*bgp_static
;
4888 struct bgp_node
*rn
;
4889 uint8_t need_update
= 0;
4891 /* Convert IP prefix string to struct prefix. */
4892 ret
= str2prefix(ip_str
, &p
);
4894 vty_out(vty
, "%% Malformed prefix\n");
4895 return CMD_WARNING_CONFIG_FAILED
;
4897 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4898 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4899 return CMD_WARNING_CONFIG_FAILED
;
4906 /* Set BGP static route configuration. */
4907 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4910 vty_out(vty
, "%% Can't find static route specified\n");
4911 return CMD_WARNING_CONFIG_FAILED
;
4914 bgp_static
= bgp_node_get_bgp_static_info(rn
);
4916 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4917 && (label_index
!= bgp_static
->label_index
)) {
4919 "%% label-index doesn't match static route\n");
4920 return CMD_WARNING_CONFIG_FAILED
;
4923 if ((rmap
&& bgp_static
->rmap
.name
)
4924 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4926 "%% route-map name doesn't match static route\n");
4927 return CMD_WARNING_CONFIG_FAILED
;
4930 /* Update BGP RIB. */
4931 if (!bgp_static
->backdoor
)
4932 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4934 /* Clear configuration. */
4935 bgp_static_free(bgp_static
);
4936 bgp_node_set_bgp_static_info(rn
, NULL
);
4937 bgp_unlock_node(rn
);
4938 bgp_unlock_node(rn
);
4941 /* Set BGP static route configuration. */
4942 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4944 bgp_static
= bgp_node_get_bgp_static_info(rn
);
4946 /* Configuration change. */
4947 /* Label index cannot be changed. */
4948 if (bgp_static
->label_index
!= label_index
) {
4949 vty_out(vty
, "%% cannot change label-index\n");
4950 return CMD_WARNING_CONFIG_FAILED
;
4953 /* Check previous routes are installed into BGP. */
4954 if (bgp_static
->valid
4955 && bgp_static
->backdoor
!= backdoor
)
4958 bgp_static
->backdoor
= backdoor
;
4961 if (bgp_static
->rmap
.name
)
4962 XFREE(MTYPE_ROUTE_MAP_NAME
,
4963 bgp_static
->rmap
.name
);
4964 bgp_static
->rmap
.name
=
4965 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4966 bgp_static
->rmap
.map
=
4967 route_map_lookup_by_name(rmap
);
4969 if (bgp_static
->rmap
.name
)
4970 XFREE(MTYPE_ROUTE_MAP_NAME
,
4971 bgp_static
->rmap
.name
);
4972 bgp_static
->rmap
.name
= NULL
;
4973 bgp_static
->rmap
.map
= NULL
;
4974 bgp_static
->valid
= 0;
4976 bgp_unlock_node(rn
);
4978 /* New configuration. */
4979 bgp_static
= bgp_static_new();
4980 bgp_static
->backdoor
= backdoor
;
4981 bgp_static
->valid
= 0;
4982 bgp_static
->igpmetric
= 0;
4983 bgp_static
->igpnexthop
.s_addr
= 0;
4984 bgp_static
->label_index
= label_index
;
4987 if (bgp_static
->rmap
.name
)
4988 XFREE(MTYPE_ROUTE_MAP_NAME
,
4989 bgp_static
->rmap
.name
);
4990 bgp_static
->rmap
.name
=
4991 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4992 bgp_static
->rmap
.map
=
4993 route_map_lookup_by_name(rmap
);
4995 bgp_node_set_bgp_static_info(rn
, bgp_static
);
4998 bgp_static
->valid
= 1;
5000 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5002 if (!bgp_static
->backdoor
)
5003 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5009 void bgp_static_add(struct bgp
*bgp
)
5013 struct bgp_node
*rn
;
5014 struct bgp_node
*rm
;
5015 struct bgp_table
*table
;
5016 struct bgp_static
*bgp_static
;
5018 FOREACH_AFI_SAFI (afi
, safi
)
5019 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5020 rn
= bgp_route_next(rn
)) {
5021 if (!bgp_node_has_bgp_path_info_data(rn
))
5024 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5025 || (safi
== SAFI_EVPN
)) {
5026 table
= bgp_node_get_bgp_table_info(rn
);
5028 for (rm
= bgp_table_top(table
); rm
;
5029 rm
= bgp_route_next(rm
)) {
5031 bgp_node_get_bgp_static_info(
5033 bgp_static_update_safi(bgp
, &rm
->p
,
5040 bgp_node_get_bgp_static_info(rn
), afi
,
5046 /* Called from bgp_delete(). Delete all static routes from the BGP
5048 void bgp_static_delete(struct bgp
*bgp
)
5052 struct bgp_node
*rn
;
5053 struct bgp_node
*rm
;
5054 struct bgp_table
*table
;
5055 struct bgp_static
*bgp_static
;
5057 FOREACH_AFI_SAFI (afi
, safi
)
5058 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5059 rn
= bgp_route_next(rn
)) {
5060 if (!bgp_node_has_bgp_path_info_data(rn
))
5063 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5064 || (safi
== SAFI_EVPN
)) {
5065 table
= bgp_node_get_bgp_table_info(rn
);
5067 for (rm
= bgp_table_top(table
); rm
;
5068 rm
= bgp_route_next(rm
)) {
5070 bgp_node_get_bgp_static_info(
5072 bgp_static_withdraw_safi(
5073 bgp
, &rm
->p
, AFI_IP
, safi
,
5074 (struct prefix_rd
*)&rn
->p
);
5075 bgp_static_free(bgp_static
);
5076 bgp_node_set_bgp_static_info(rn
, NULL
);
5077 bgp_unlock_node(rn
);
5080 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5081 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5082 bgp_static_free(bgp_static
);
5083 bgp_node_set_bgp_static_info(rn
, NULL
);
5084 bgp_unlock_node(rn
);
5089 void bgp_static_redo_import_check(struct bgp
*bgp
)
5093 struct bgp_node
*rn
;
5094 struct bgp_node
*rm
;
5095 struct bgp_table
*table
;
5096 struct bgp_static
*bgp_static
;
5098 /* Use this flag to force reprocessing of the route */
5099 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5100 FOREACH_AFI_SAFI (afi
, safi
) {
5101 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5102 rn
= bgp_route_next(rn
)) {
5103 if (!bgp_node_has_bgp_path_info_data(rn
))
5106 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5107 || (safi
== SAFI_EVPN
)) {
5108 table
= bgp_node_get_bgp_table_info(rn
);
5110 for (rm
= bgp_table_top(table
); rm
;
5111 rm
= bgp_route_next(rm
)) {
5113 bgp_node_get_bgp_static_info(
5115 bgp_static_update_safi(bgp
, &rm
->p
,
5120 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5121 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5126 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5129 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5132 struct bgp_table
*table
;
5133 struct bgp_node
*rn
;
5134 struct bgp_path_info
*pi
;
5136 table
= bgp
->rib
[afi
][safi
];
5137 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5138 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5139 if (pi
->peer
== bgp
->peer_self
5140 && ((pi
->type
== ZEBRA_ROUTE_BGP
5141 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5142 || (pi
->type
!= ZEBRA_ROUTE_BGP
5144 == BGP_ROUTE_REDISTRIBUTE
))) {
5145 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5147 bgp_unlink_nexthop(pi
);
5148 bgp_path_info_delete(rn
, pi
);
5149 bgp_process(bgp
, rn
, afi
, safi
);
5156 * Purge all networks and redistributed routes from routing table.
5157 * Invoked upon the instance going down.
5159 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5164 FOREACH_AFI_SAFI (afi
, safi
)
5165 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5170 * Currently this is used to set static routes for VPN and ENCAP.
5171 * I think it can probably be factored with bgp_static_set.
5173 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5174 const char *ip_str
, const char *rd_str
,
5175 const char *label_str
, const char *rmap_str
,
5176 int evpn_type
, const char *esi
, const char *gwip
,
5177 const char *ethtag
, const char *routermac
)
5179 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5182 struct prefix_rd prd
;
5183 struct bgp_node
*prn
;
5184 struct bgp_node
*rn
;
5185 struct bgp_table
*table
;
5186 struct bgp_static
*bgp_static
;
5187 mpls_label_t label
= MPLS_INVALID_LABEL
;
5188 struct prefix gw_ip
;
5190 /* validate ip prefix */
5191 ret
= str2prefix(ip_str
, &p
);
5193 vty_out(vty
, "%% Malformed prefix\n");
5194 return CMD_WARNING_CONFIG_FAILED
;
5197 if ((afi
== AFI_L2VPN
)
5198 && (bgp_build_evpn_prefix(evpn_type
,
5199 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5200 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5201 return CMD_WARNING_CONFIG_FAILED
;
5204 ret
= str2prefix_rd(rd_str
, &prd
);
5206 vty_out(vty
, "%% Malformed rd\n");
5207 return CMD_WARNING_CONFIG_FAILED
;
5211 unsigned long label_val
;
5212 label_val
= strtoul(label_str
, NULL
, 10);
5213 encode_label(label_val
, &label
);
5216 if (safi
== SAFI_EVPN
) {
5217 if (esi
&& str2esi(esi
, NULL
) == 0) {
5218 vty_out(vty
, "%% Malformed ESI\n");
5219 return CMD_WARNING_CONFIG_FAILED
;
5221 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5222 vty_out(vty
, "%% Malformed Router MAC\n");
5223 return CMD_WARNING_CONFIG_FAILED
;
5226 memset(&gw_ip
, 0, sizeof(struct prefix
));
5227 ret
= str2prefix(gwip
, &gw_ip
);
5229 vty_out(vty
, "%% Malformed GatewayIp\n");
5230 return CMD_WARNING_CONFIG_FAILED
;
5232 if ((gw_ip
.family
== AF_INET
5233 && is_evpn_prefix_ipaddr_v6(
5234 (struct prefix_evpn
*)&p
))
5235 || (gw_ip
.family
== AF_INET6
5236 && is_evpn_prefix_ipaddr_v4(
5237 (struct prefix_evpn
*)&p
))) {
5239 "%% GatewayIp family differs with IP prefix\n");
5240 return CMD_WARNING_CONFIG_FAILED
;
5244 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5245 if (!bgp_node_has_bgp_path_info_data(prn
))
5246 bgp_node_set_bgp_table_info(prn
,
5247 bgp_table_init(bgp
, afi
, safi
));
5249 bgp_unlock_node(prn
);
5250 table
= bgp_node_get_bgp_table_info(prn
);
5252 rn
= bgp_node_get(table
, &p
);
5254 if (bgp_node_has_bgp_path_info_data(rn
)) {
5255 vty_out(vty
, "%% Same network configuration exists\n");
5256 bgp_unlock_node(rn
);
5258 /* New configuration. */
5259 bgp_static
= bgp_static_new();
5260 bgp_static
->backdoor
= 0;
5261 bgp_static
->valid
= 0;
5262 bgp_static
->igpmetric
= 0;
5263 bgp_static
->igpnexthop
.s_addr
= 0;
5264 bgp_static
->label
= label
;
5265 bgp_static
->prd
= prd
;
5268 if (bgp_static
->rmap
.name
)
5269 XFREE(MTYPE_ROUTE_MAP_NAME
,
5270 bgp_static
->rmap
.name
);
5271 bgp_static
->rmap
.name
=
5272 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5273 bgp_static
->rmap
.map
=
5274 route_map_lookup_by_name(rmap_str
);
5277 if (safi
== SAFI_EVPN
) {
5279 bgp_static
->eth_s_id
=
5281 sizeof(struct eth_segment_id
));
5282 str2esi(esi
, bgp_static
->eth_s_id
);
5285 bgp_static
->router_mac
=
5286 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5287 (void)prefix_str2mac(routermac
,
5288 bgp_static
->router_mac
);
5291 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5293 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5295 bgp_static
->valid
= 1;
5296 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5302 /* Configure static BGP network. */
5303 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5304 const char *ip_str
, const char *rd_str
,
5305 const char *label_str
, int evpn_type
, const char *esi
,
5306 const char *gwip
, const char *ethtag
)
5308 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5311 struct prefix_rd prd
;
5312 struct bgp_node
*prn
;
5313 struct bgp_node
*rn
;
5314 struct bgp_table
*table
;
5315 struct bgp_static
*bgp_static
;
5316 mpls_label_t label
= MPLS_INVALID_LABEL
;
5318 /* Convert IP prefix string to struct prefix. */
5319 ret
= str2prefix(ip_str
, &p
);
5321 vty_out(vty
, "%% Malformed prefix\n");
5322 return CMD_WARNING_CONFIG_FAILED
;
5325 if ((afi
== AFI_L2VPN
)
5326 && (bgp_build_evpn_prefix(evpn_type
,
5327 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5328 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5329 return CMD_WARNING_CONFIG_FAILED
;
5331 ret
= str2prefix_rd(rd_str
, &prd
);
5333 vty_out(vty
, "%% Malformed rd\n");
5334 return CMD_WARNING_CONFIG_FAILED
;
5338 unsigned long label_val
;
5339 label_val
= strtoul(label_str
, NULL
, 10);
5340 encode_label(label_val
, &label
);
5343 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5344 if (!bgp_node_has_bgp_path_info_data(prn
))
5345 bgp_node_set_bgp_table_info(prn
,
5346 bgp_table_init(bgp
, afi
, safi
));
5348 bgp_unlock_node(prn
);
5349 table
= bgp_node_get_bgp_table_info(prn
);
5351 rn
= bgp_node_lookup(table
, &p
);
5354 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5356 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5357 bgp_static_free(bgp_static
);
5358 bgp_node_set_bgp_static_info(rn
, NULL
);
5359 bgp_unlock_node(rn
);
5360 bgp_unlock_node(rn
);
5362 vty_out(vty
, "%% Can't find the route\n");
5367 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5368 const char *rmap_name
)
5370 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5371 struct bgp_rmap
*rmap
;
5373 rmap
= &bgp
->table_map
[afi
][safi
];
5376 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5377 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5378 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5381 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5386 if (bgp_fibupd_safi(safi
))
5387 bgp_zebra_announce_table(bgp
, afi
, safi
);
5392 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5393 const char *rmap_name
)
5395 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5396 struct bgp_rmap
*rmap
;
5398 rmap
= &bgp
->table_map
[afi
][safi
];
5400 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5404 if (bgp_fibupd_safi(safi
))
5405 bgp_zebra_announce_table(bgp
, afi
, safi
);
5410 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5413 if (bgp
->table_map
[afi
][safi
].name
) {
5414 vty_out(vty
, " table-map %s\n",
5415 bgp
->table_map
[afi
][safi
].name
);
5419 DEFUN (bgp_table_map
,
5422 "BGP table to RIB route download filter\n"
5423 "Name of the route map\n")
5426 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5427 argv
[idx_word
]->arg
);
5429 DEFUN (no_bgp_table_map
,
5430 no_bgp_table_map_cmd
,
5431 "no table-map WORD",
5433 "BGP table to RIB route download filter\n"
5434 "Name of the route map\n")
5437 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5438 argv
[idx_word
]->arg
);
5444 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5445 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5446 backdoor$backdoor}]",
5448 "Specify a network to announce via BGP\n"
5453 "Route-map to modify the attributes\n"
5454 "Name of the route map\n"
5455 "Label index to associate with the prefix\n"
5456 "Label index value\n"
5457 "Specify a BGP backdoor route\n")
5459 char addr_prefix_str
[BUFSIZ
];
5464 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5467 vty_out(vty
, "%% Inconsistent address and mask\n");
5468 return CMD_WARNING_CONFIG_FAILED
;
5472 return bgp_static_set(
5473 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5474 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5475 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5478 DEFPY(ipv6_bgp_network
,
5479 ipv6_bgp_network_cmd
,
5480 "[no] network X:X::X:X/M$prefix \
5481 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5483 "Specify a network to announce via BGP\n"
5485 "Route-map to modify the attributes\n"
5486 "Name of the route map\n"
5487 "Label index to associate with the prefix\n"
5488 "Label index value\n")
5490 return bgp_static_set(
5491 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5492 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5495 /* Aggreagete address:
5497 advertise-map Set condition to advertise attribute
5498 as-set Generate AS set path information
5499 attribute-map Set attributes of aggregate
5500 route-map Set parameters of aggregate
5501 summary-only Filter more specific routes from updates
5502 suppress-map Conditionally filter more specific routes from updates
5505 struct bgp_aggregate
{
5506 /* Summary-only flag. */
5507 uint8_t summary_only
;
5509 /* AS set generation. */
5512 /* Route-map for aggregated route. */
5513 struct route_map
*map
;
5515 /* Suppress-count. */
5516 unsigned long count
;
5518 /* SAFI configuration. */
5522 static struct bgp_aggregate
*bgp_aggregate_new(void)
5524 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5527 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5529 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5532 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5533 struct aspath
*aspath
,
5534 struct community
*comm
,
5535 struct ecommunity
*ecomm
,
5536 struct lcommunity
*lcomm
)
5538 static struct aspath
*ae
= NULL
;
5541 ae
= aspath_empty();
5546 if (origin
!= pi
->attr
->origin
)
5549 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5552 if (!community_cmp(pi
->attr
->community
, comm
))
5555 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5558 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5561 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5567 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5568 struct prefix
*p
, uint8_t origin
,
5569 struct aspath
*aspath
,
5570 struct community
*community
,
5571 struct ecommunity
*ecommunity
,
5572 struct lcommunity
*lcommunity
,
5573 uint8_t atomic_aggregate
,
5574 struct bgp_aggregate
*aggregate
)
5576 struct bgp_node
*rn
;
5577 struct bgp_table
*table
;
5578 struct bgp_path_info
*pi
, *orig
, *new;
5580 table
= bgp
->rib
[afi
][safi
];
5582 rn
= bgp_node_get(table
, p
);
5584 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5585 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5586 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5589 if (aggregate
->count
> 0) {
5591 * If the aggregate information has not changed
5592 * no need to re-install it again.
5594 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5595 ecommunity
, lcommunity
)) {
5596 bgp_unlock_node(rn
);
5599 aspath_free(aspath
);
5601 community_free(&community
);
5603 ecommunity_free(&ecommunity
);
5605 lcommunity_free(&lcommunity
);
5611 * Mark the old as unusable
5614 bgp_path_info_delete(rn
, pi
);
5616 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5618 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5619 community
, ecommunity
,
5624 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5626 bgp_path_info_add(rn
, new);
5627 bgp_process(bgp
, rn
, afi
, safi
);
5629 for (pi
= orig
; pi
; pi
= pi
->next
)
5630 if (pi
->peer
== bgp
->peer_self
5631 && pi
->type
== ZEBRA_ROUTE_BGP
5632 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5635 /* Withdraw static BGP route from routing table. */
5637 bgp_path_info_delete(rn
, pi
);
5638 bgp_process(bgp
, rn
, afi
, safi
);
5642 bgp_unlock_node(rn
);
5645 /* Update an aggregate as routes are added/removed from the BGP table */
5646 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5647 struct bgp_path_info
*pinew
, afi_t afi
,
5648 safi_t safi
, struct bgp_path_info
*del
,
5649 struct bgp_aggregate
*aggregate
)
5651 struct bgp_table
*table
;
5652 struct bgp_node
*top
;
5653 struct bgp_node
*rn
;
5655 struct aspath
*aspath
= NULL
;
5656 struct aspath
*asmerge
= NULL
;
5657 struct community
*community
= NULL
;
5658 struct community
*commerge
= NULL
;
5659 struct ecommunity
*ecommunity
= NULL
;
5660 struct ecommunity
*ecommerge
= NULL
;
5661 struct lcommunity
*lcommunity
= NULL
;
5662 struct lcommunity
*lcommerge
= NULL
;
5663 struct bgp_path_info
*pi
;
5664 unsigned long match
= 0;
5665 uint8_t atomic_aggregate
= 0;
5667 /* ORIGIN attribute: If at least one route among routes that are
5668 aggregated has ORIGIN with the value INCOMPLETE, then the
5669 aggregated route must have the ORIGIN attribute with the value
5670 INCOMPLETE. Otherwise, if at least one route among routes that
5671 are aggregated has ORIGIN with the value EGP, then the aggregated
5672 route must have the origin attribute with the value EGP. In all
5673 other case the value of the ORIGIN attribute of the aggregated
5674 route is INTERNAL. */
5675 origin
= BGP_ORIGIN_IGP
;
5677 table
= bgp
->rib
[afi
][safi
];
5679 top
= bgp_node_get(table
, p
);
5680 for (rn
= bgp_node_get(table
, p
); rn
;
5681 rn
= bgp_route_next_until(rn
, top
)) {
5682 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5687 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5688 if (BGP_PATH_HOLDDOWN(pi
))
5691 if (del
&& pi
== del
)
5695 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5696 atomic_aggregate
= 1;
5698 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5702 * summary-only aggregate route suppress
5703 * aggregated route announcements.
5705 if (aggregate
->summary_only
) {
5706 (bgp_path_info_extra_get(pi
))->suppress
++;
5707 bgp_path_info_set_flag(rn
, pi
,
5708 BGP_PATH_ATTR_CHANGED
);
5715 * If at least one route among routes that are
5716 * aggregated has ORIGIN with the value INCOMPLETE,
5717 * then the aggregated route MUST have the ORIGIN
5718 * attribute with the value INCOMPLETE. Otherwise, if
5719 * at least one route among routes that are aggregated
5720 * has ORIGIN with the value EGP, then the aggregated
5721 * route MUST have the ORIGIN attribute with the value
5724 if (origin
< pi
->attr
->origin
)
5725 origin
= pi
->attr
->origin
;
5727 if (!aggregate
->as_set
)
5731 * as-set aggregate route generate origin, as path,
5732 * and community aggregation.
5735 asmerge
= aspath_aggregate(aspath
,
5737 aspath_free(aspath
);
5740 aspath
= aspath_dup(pi
->attr
->aspath
);
5742 if (pi
->attr
->community
) {
5744 commerge
= community_merge(
5745 community
, pi
->attr
->community
);
5747 community_uniq_sort(commerge
);
5748 community_free(&commerge
);
5750 community
= community_dup(
5751 pi
->attr
->community
);
5754 if (pi
->attr
->ecommunity
) {
5756 ecommerge
= ecommunity_merge(
5758 pi
->attr
->ecommunity
);
5760 ecommunity_uniq_sort(ecommerge
);
5761 ecommunity_free(&ecommerge
);
5763 ecommunity
= ecommunity_dup(
5764 pi
->attr
->ecommunity
);
5767 if (pi
->attr
->lcommunity
) {
5769 lcommerge
= lcommunity_merge(
5771 pi
->attr
->lcommunity
);
5773 lcommunity_uniq_sort(lcommerge
);
5774 lcommunity_free(&lcommerge
);
5776 lcommunity
= lcommunity_dup(
5777 pi
->attr
->lcommunity
);
5781 bgp_process(bgp
, rn
, afi
, safi
);
5783 bgp_unlock_node(top
);
5788 if (aggregate
->summary_only
)
5789 (bgp_path_info_extra_get(pinew
))->suppress
++;
5791 if (origin
< pinew
->attr
->origin
)
5792 origin
= pinew
->attr
->origin
;
5794 if (aggregate
->as_set
) {
5796 asmerge
= aspath_aggregate(aspath
,
5797 pinew
->attr
->aspath
);
5798 aspath_free(aspath
);
5801 aspath
= aspath_dup(pinew
->attr
->aspath
);
5803 if (pinew
->attr
->community
) {
5805 commerge
= community_merge(
5807 pinew
->attr
->community
);
5809 community_uniq_sort(commerge
);
5810 community_free(&commerge
);
5812 community
= community_dup(
5813 pinew
->attr
->community
);
5816 if (pinew
->attr
->ecommunity
) {
5818 ecommerge
= ecommunity_merge(
5820 pinew
->attr
->ecommunity
);
5822 ecommunity_uniq_sort(ecommerge
);
5823 ecommunity_free(&ecommerge
);
5825 ecommunity
= ecommunity_dup(
5826 pinew
->attr
->ecommunity
);
5829 if (pinew
->attr
->lcommunity
) {
5831 lcommerge
= lcommunity_merge(
5833 pinew
->attr
->lcommunity
);
5835 lcommunity_uniq_sort(lcommerge
);
5836 lcommunity_free(&lcommerge
);
5838 lcommunity
= lcommunity_dup(
5839 pinew
->attr
->lcommunity
);
5844 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5845 ecommunity
, lcommunity
, atomic_aggregate
,
5848 if (aggregate
->count
== 0) {
5850 aspath_free(aspath
);
5852 community_free(&community
);
5854 ecommunity_free(&ecommunity
);
5856 lcommunity_free(&lcommunity
);
5860 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5861 safi_t safi
, struct bgp_aggregate
*aggregate
)
5863 struct bgp_table
*table
;
5864 struct bgp_node
*top
;
5865 struct bgp_node
*rn
;
5866 struct bgp_path_info
*pi
;
5867 unsigned long match
;
5869 table
= bgp
->rib
[afi
][safi
];
5871 /* If routes exists below this node, generate aggregate routes. */
5872 top
= bgp_node_get(table
, p
);
5873 for (rn
= bgp_node_get(table
, p
); rn
;
5874 rn
= bgp_route_next_until(rn
, top
)) {
5875 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5879 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5880 if (BGP_PATH_HOLDDOWN(pi
))
5883 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5886 if (aggregate
->summary_only
&& pi
->extra
) {
5887 pi
->extra
->suppress
--;
5889 if (pi
->extra
->suppress
== 0) {
5890 bgp_path_info_set_flag(
5891 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5898 /* If this node was suppressed, process the change. */
5900 bgp_process(bgp
, rn
, afi
, safi
);
5902 bgp_unlock_node(top
);
5905 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5906 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
5908 struct bgp_node
*child
;
5909 struct bgp_node
*rn
;
5910 struct bgp_aggregate
*aggregate
;
5911 struct bgp_table
*table
;
5913 table
= bgp
->aggregate
[afi
][safi
];
5915 /* No aggregates configured. */
5916 if (bgp_table_top_nolock(table
) == NULL
)
5919 if (p
->prefixlen
== 0)
5922 if (BGP_PATH_HOLDDOWN(pi
))
5925 child
= bgp_node_get(table
, p
);
5927 /* Aggregate address configuration check. */
5928 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5929 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
5930 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5931 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5932 bgp_aggregate_route(bgp
, &rn
->p
, pi
, afi
, safi
, NULL
,
5936 bgp_unlock_node(child
);
5939 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5940 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
5942 struct bgp_node
*child
;
5943 struct bgp_node
*rn
;
5944 struct bgp_aggregate
*aggregate
;
5945 struct bgp_table
*table
;
5947 table
= bgp
->aggregate
[afi
][safi
];
5949 /* No aggregates configured. */
5950 if (bgp_table_top_nolock(table
) == NULL
)
5953 if (p
->prefixlen
== 0)
5956 child
= bgp_node_get(table
, p
);
5958 /* Aggregate address configuration check. */
5959 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5960 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
5961 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5962 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5963 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5967 bgp_unlock_node(child
);
5970 /* Aggregate route attribute. */
5971 #define AGGREGATE_SUMMARY_ONLY 1
5972 #define AGGREGATE_AS_SET 1
5974 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5975 afi_t afi
, safi_t safi
)
5977 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5980 struct bgp_node
*rn
;
5981 struct bgp_aggregate
*aggregate
;
5983 /* Convert string to prefix structure. */
5984 ret
= str2prefix(prefix_str
, &p
);
5986 vty_out(vty
, "Malformed prefix\n");
5987 return CMD_WARNING_CONFIG_FAILED
;
5991 /* Old configuration check. */
5992 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5995 "%% There is no aggregate-address configuration.\n");
5996 return CMD_WARNING_CONFIG_FAILED
;
5999 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6000 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6001 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6002 NULL
, NULL
, 0, aggregate
);
6004 /* Unlock aggregate address configuration. */
6005 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6006 bgp_aggregate_free(aggregate
);
6007 bgp_unlock_node(rn
);
6008 bgp_unlock_node(rn
);
6013 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6014 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6016 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6019 struct bgp_node
*rn
;
6020 struct bgp_aggregate
*aggregate
;
6022 /* Convert string to prefix structure. */
6023 ret
= str2prefix(prefix_str
, &p
);
6025 vty_out(vty
, "Malformed prefix\n");
6026 return CMD_WARNING_CONFIG_FAILED
;
6030 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6031 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6032 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6034 return CMD_WARNING_CONFIG_FAILED
;
6037 /* Old configuration check. */
6038 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6040 if (bgp_node_has_bgp_path_info_data(rn
)) {
6041 vty_out(vty
, "There is already same aggregate network.\n");
6042 /* try to remove the old entry */
6043 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6045 vty_out(vty
, "Error deleting aggregate.\n");
6046 bgp_unlock_node(rn
);
6047 return CMD_WARNING_CONFIG_FAILED
;
6051 /* Make aggregate address structure. */
6052 aggregate
= bgp_aggregate_new();
6053 aggregate
->summary_only
= summary_only
;
6054 aggregate
->as_set
= as_set
;
6055 aggregate
->safi
= safi
;
6056 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6058 /* Aggregate address insert into BGP routing table. */
6059 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
6064 DEFUN (aggregate_address
,
6065 aggregate_address_cmd
,
6066 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6067 "Configure BGP aggregate entries\n"
6068 "Aggregate prefix\n"
6069 "Generate AS set path information\n"
6070 "Filter more specific routes from updates\n"
6071 "Filter more specific routes from updates\n"
6072 "Generate AS set path information\n")
6075 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6076 char *prefix
= argv
[idx
]->arg
;
6078 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6080 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6081 ? AGGREGATE_SUMMARY_ONLY
6084 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6085 summary_only
, as_set
);
6088 DEFUN (aggregate_address_mask
,
6089 aggregate_address_mask_cmd
,
6090 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6091 "Configure BGP aggregate entries\n"
6092 "Aggregate address\n"
6094 "Generate AS set path information\n"
6095 "Filter more specific routes from updates\n"
6096 "Filter more specific routes from updates\n"
6097 "Generate AS set path information\n")
6100 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6101 char *prefix
= argv
[idx
]->arg
;
6102 char *mask
= argv
[idx
+ 1]->arg
;
6104 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6106 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6107 ? AGGREGATE_SUMMARY_ONLY
6110 char prefix_str
[BUFSIZ
];
6111 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6114 vty_out(vty
, "%% Inconsistent address and mask\n");
6115 return CMD_WARNING_CONFIG_FAILED
;
6118 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6119 summary_only
, as_set
);
6122 DEFUN (no_aggregate_address
,
6123 no_aggregate_address_cmd
,
6124 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6126 "Configure BGP aggregate entries\n"
6127 "Aggregate prefix\n"
6128 "Generate AS set path information\n"
6129 "Filter more specific routes from updates\n"
6130 "Filter more specific routes from updates\n"
6131 "Generate AS set path information\n")
6134 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6135 char *prefix
= argv
[idx
]->arg
;
6136 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6139 DEFUN (no_aggregate_address_mask
,
6140 no_aggregate_address_mask_cmd
,
6141 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6143 "Configure BGP aggregate entries\n"
6144 "Aggregate address\n"
6146 "Generate AS set path information\n"
6147 "Filter more specific routes from updates\n"
6148 "Filter more specific routes from updates\n"
6149 "Generate AS set path information\n")
6152 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6153 char *prefix
= argv
[idx
]->arg
;
6154 char *mask
= argv
[idx
+ 1]->arg
;
6156 char prefix_str
[BUFSIZ
];
6157 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6160 vty_out(vty
, "%% Inconsistent address and mask\n");
6161 return CMD_WARNING_CONFIG_FAILED
;
6164 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6167 DEFUN (ipv6_aggregate_address
,
6168 ipv6_aggregate_address_cmd
,
6169 "aggregate-address X:X::X:X/M [summary-only]",
6170 "Configure BGP aggregate entries\n"
6171 "Aggregate prefix\n"
6172 "Filter more specific routes from updates\n")
6175 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6176 char *prefix
= argv
[idx
]->arg
;
6177 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6178 ? AGGREGATE_SUMMARY_ONLY
6180 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6184 DEFUN (no_ipv6_aggregate_address
,
6185 no_ipv6_aggregate_address_cmd
,
6186 "no aggregate-address X:X::X:X/M [summary-only]",
6188 "Configure BGP aggregate entries\n"
6189 "Aggregate prefix\n"
6190 "Filter more specific routes from updates\n")
6193 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6194 char *prefix
= argv
[idx
]->arg
;
6195 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6198 /* Redistribute route treatment. */
6199 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6200 const union g_addr
*nexthop
, ifindex_t ifindex
,
6201 enum nexthop_types_t nhtype
, uint32_t metric
,
6202 uint8_t type
, unsigned short instance
,
6205 struct bgp_path_info
*new;
6206 struct bgp_path_info
*bpi
;
6207 struct bgp_path_info rmap_path
;
6208 struct bgp_node
*bn
;
6210 struct attr
*new_attr
;
6213 struct bgp_redist
*red
;
6215 /* Make default attribute. */
6216 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6219 case NEXTHOP_TYPE_IFINDEX
:
6221 case NEXTHOP_TYPE_IPV4
:
6222 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6223 attr
.nexthop
= nexthop
->ipv4
;
6225 case NEXTHOP_TYPE_IPV6
:
6226 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6227 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6228 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6230 case NEXTHOP_TYPE_BLACKHOLE
:
6231 switch (p
->family
) {
6233 attr
.nexthop
.s_addr
= INADDR_ANY
;
6236 memset(&attr
.mp_nexthop_global
, 0,
6237 sizeof(attr
.mp_nexthop_global
));
6238 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6243 attr
.nh_ifindex
= ifindex
;
6246 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6249 afi
= family2afi(p
->family
);
6251 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6253 struct attr attr_new
;
6255 /* Copy attribute for modification. */
6256 bgp_attr_dup(&attr_new
, &attr
);
6258 if (red
->redist_metric_flag
)
6259 attr_new
.med
= red
->redist_metric
;
6261 /* Apply route-map. */
6262 if (red
->rmap
.name
) {
6263 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6264 rmap_path
.peer
= bgp
->peer_self
;
6265 rmap_path
.attr
= &attr_new
;
6267 SET_FLAG(bgp
->peer_self
->rmap_type
,
6268 PEER_RMAP_TYPE_REDISTRIBUTE
);
6270 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6273 bgp
->peer_self
->rmap_type
= 0;
6275 if (ret
== RMAP_DENYMATCH
) {
6276 /* Free uninterned attribute. */
6277 bgp_attr_flush(&attr_new
);
6279 /* Unintern original. */
6280 aspath_unintern(&attr
.aspath
);
6281 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6286 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6287 bgp_attr_add_gshut_community(&attr_new
);
6289 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6290 SAFI_UNICAST
, p
, NULL
);
6292 new_attr
= bgp_attr_intern(&attr_new
);
6294 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6296 if (bpi
->peer
== bgp
->peer_self
6297 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6301 /* Ensure the (source route) type is updated. */
6303 if (attrhash_cmp(bpi
->attr
, new_attr
)
6304 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6305 bgp_attr_unintern(&new_attr
);
6306 aspath_unintern(&attr
.aspath
);
6307 bgp_unlock_node(bn
);
6310 /* The attribute is changed. */
6311 bgp_path_info_set_flag(bn
, bpi
,
6312 BGP_PATH_ATTR_CHANGED
);
6314 /* Rewrite BGP route information. */
6315 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6316 bgp_path_info_restore(bn
, bpi
);
6318 bgp_aggregate_decrement(
6319 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6320 bgp_attr_unintern(&bpi
->attr
);
6321 bpi
->attr
= new_attr
;
6322 bpi
->uptime
= bgp_clock();
6324 /* Process change. */
6325 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6327 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6328 bgp_unlock_node(bn
);
6329 aspath_unintern(&attr
.aspath
);
6331 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6333 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6335 vpn_leak_from_vrf_update(
6336 bgp_get_default(), bgp
, bpi
);
6342 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6343 bgp
->peer_self
, new_attr
, bn
);
6344 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6346 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6347 bgp_path_info_add(bn
, new);
6348 bgp_unlock_node(bn
);
6349 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6351 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6352 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6354 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6358 /* Unintern original. */
6359 aspath_unintern(&attr
.aspath
);
6362 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6363 unsigned short instance
)
6366 struct bgp_node
*rn
;
6367 struct bgp_path_info
*pi
;
6368 struct bgp_redist
*red
;
6370 afi
= family2afi(p
->family
);
6372 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6374 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6375 SAFI_UNICAST
, p
, NULL
);
6377 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6378 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6382 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6383 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6385 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6388 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6389 bgp_path_info_delete(rn
, pi
);
6390 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6392 bgp_unlock_node(rn
);
6396 /* Withdraw specified route type's route. */
6397 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6398 unsigned short instance
)
6400 struct bgp_node
*rn
;
6401 struct bgp_path_info
*pi
;
6402 struct bgp_table
*table
;
6404 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6406 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6407 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6408 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6409 && pi
->instance
== instance
)
6413 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6414 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6416 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6419 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6421 bgp_path_info_delete(rn
, pi
);
6422 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6427 /* Static function to display route. */
6428 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6435 if (p
->family
== AF_INET
) {
6439 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6442 json_object_string_add(json
, "prefix",
6443 inet_ntop(p
->family
,
6446 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6447 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6448 json_object_string_add(json
, "network", buf2
);
6450 } else if (p
->family
== AF_ETHERNET
) {
6451 prefix2str(p
, buf
, PREFIX_STRLEN
);
6452 len
= vty_out(vty
, "%s", buf
);
6453 } else if (p
->family
== AF_EVPN
) {
6457 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6460 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6461 } else if (p
->family
== AF_FLOWSPEC
) {
6462 route_vty_out_flowspec(vty
, p
, NULL
,
6464 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6465 NLRI_STRING_FORMAT_MIN
, json
);
6470 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6473 json_object_string_add(json
, "prefix",
6474 inet_ntop(p
->family
,
6477 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6478 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6479 json_object_string_add(json
, "network", buf2
);
6486 vty_out(vty
, "\n%*s", 20, " ");
6488 vty_out(vty
, "%*s", len
, " ");
6492 enum bgp_display_type
{
6496 /* Print the short form route status for a bgp_path_info */
6497 static void route_vty_short_status_out(struct vty
*vty
,
6498 struct bgp_path_info
*path
,
6499 json_object
*json_path
)
6503 /* Route status display. */
6504 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6505 json_object_boolean_true_add(json_path
, "removed");
6507 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6508 json_object_boolean_true_add(json_path
, "stale");
6510 if (path
->extra
&& path
->extra
->suppress
)
6511 json_object_boolean_true_add(json_path
, "suppressed");
6513 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6514 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6515 json_object_boolean_true_add(json_path
, "valid");
6518 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6519 json_object_boolean_true_add(json_path
, "history");
6521 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6522 json_object_boolean_true_add(json_path
, "damped");
6524 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6525 json_object_boolean_true_add(json_path
, "bestpath");
6527 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6528 json_object_boolean_true_add(json_path
, "multipath");
6530 /* Internal route. */
6531 if ((path
->peer
->as
)
6532 && (path
->peer
->as
== path
->peer
->local_as
))
6533 json_object_string_add(json_path
, "pathFrom",
6536 json_object_string_add(json_path
, "pathFrom",
6542 /* Route status display. */
6543 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6545 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6547 else if (path
->extra
&& path
->extra
->suppress
)
6549 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6550 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6556 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6558 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6560 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6562 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6567 /* Internal route. */
6568 if (path
->peer
&& (path
->peer
->as
)
6569 && (path
->peer
->as
== path
->peer
->local_as
))
6575 /* called from terminal list command */
6576 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6577 struct bgp_path_info
*path
, int display
, safi_t safi
,
6578 json_object
*json_paths
)
6581 json_object
*json_path
= NULL
;
6582 json_object
*json_nexthops
= NULL
;
6583 json_object
*json_nexthop_global
= NULL
;
6584 json_object
*json_nexthop_ll
= NULL
;
6585 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6587 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6588 bool nexthop_othervrf
= false;
6589 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6590 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6593 json_path
= json_object_new_object();
6595 /* short status lead text */
6596 route_vty_short_status_out(vty
, path
, json_path
);
6599 /* print prefix and mask */
6601 route_vty_out_route(p
, vty
, json_path
);
6603 vty_out(vty
, "%*s", 17, " ");
6605 route_vty_out_route(p
, vty
, json_path
);
6608 /* Print attribute */
6612 json_object_array_add(json_paths
, json_path
);
6620 * If vrf id of nexthop is different from that of prefix,
6621 * set up printable string to append
6623 if (path
->extra
&& path
->extra
->bgp_orig
) {
6624 const char *self
= "";
6629 nexthop_othervrf
= true;
6630 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6632 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6633 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6634 "@%s%s", VRFID_NONE_STR
, self
);
6636 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6637 path
->extra
->bgp_orig
->vrf_id
, self
);
6639 if (path
->extra
->bgp_orig
->inst_type
6640 != BGP_INSTANCE_TYPE_DEFAULT
)
6642 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6644 const char *self
= "";
6649 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6653 * For ENCAP and EVPN routes, nexthop address family is not
6654 * neccessarily the same as the prefix address family.
6655 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6656 * EVPN routes are also exchanged with a MP nexthop. Currently,
6658 * is only IPv4, the value will be present in either
6660 * attr->mp_nexthop_global_in
6662 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6665 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6669 sprintf(nexthop
, "%s",
6670 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6674 sprintf(nexthop
, "%s",
6675 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6679 sprintf(nexthop
, "?");
6684 json_nexthop_global
= json_object_new_object();
6686 json_object_string_add(json_nexthop_global
, "afi",
6687 (af
== AF_INET
) ? "ip" : "ipv6");
6688 json_object_string_add(json_nexthop_global
,
6689 (af
== AF_INET
) ? "ip" : "ipv6",
6691 json_object_boolean_true_add(json_nexthop_global
,
6694 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6695 } else if (safi
== SAFI_EVPN
) {
6697 json_nexthop_global
= json_object_new_object();
6699 json_object_string_add(json_nexthop_global
, "ip",
6700 inet_ntoa(attr
->nexthop
));
6701 json_object_string_add(json_nexthop_global
, "afi",
6703 json_object_boolean_true_add(json_nexthop_global
,
6706 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6708 } else if (safi
== SAFI_FLOWSPEC
) {
6709 if (attr
->nexthop
.s_addr
!= 0) {
6711 json_nexthop_global
= json_object_new_object();
6712 json_object_string_add(
6713 json_nexthop_global
, "ip",
6714 inet_ntoa(attr
->nexthop
));
6715 json_object_string_add(json_nexthop_global
,
6717 json_object_boolean_true_add(
6718 json_nexthop_global
,
6721 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6724 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6726 json_nexthop_global
= json_object_new_object();
6728 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6729 json_object_string_add(
6730 json_nexthop_global
, "ip",
6731 inet_ntoa(attr
->mp_nexthop_global_in
));
6733 json_object_string_add(
6734 json_nexthop_global
, "ip",
6735 inet_ntoa(attr
->nexthop
));
6737 json_object_string_add(json_nexthop_global
, "afi",
6739 json_object_boolean_true_add(json_nexthop_global
,
6744 snprintf(buf
, sizeof(buf
), "%s%s",
6745 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6746 vty_out(vty
, "%-16s", buf
);
6751 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6756 json_nexthop_global
= json_object_new_object();
6757 json_object_string_add(
6758 json_nexthop_global
, "ip",
6759 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6761 json_object_string_add(json_nexthop_global
, "afi",
6763 json_object_string_add(json_nexthop_global
, "scope",
6766 /* We display both LL & GL if both have been
6768 if ((attr
->mp_nexthop_len
== 32)
6769 || (path
->peer
->conf_if
)) {
6770 json_nexthop_ll
= json_object_new_object();
6771 json_object_string_add(
6772 json_nexthop_ll
, "ip",
6774 &attr
->mp_nexthop_local
, buf
,
6776 json_object_string_add(json_nexthop_ll
, "afi",
6778 json_object_string_add(json_nexthop_ll
, "scope",
6781 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6782 &attr
->mp_nexthop_local
)
6784 && !attr
->mp_nexthop_prefer_global
)
6785 json_object_boolean_true_add(
6786 json_nexthop_ll
, "used");
6788 json_object_boolean_true_add(
6789 json_nexthop_global
, "used");
6791 json_object_boolean_true_add(
6792 json_nexthop_global
, "used");
6794 /* Display LL if LL/Global both in table unless
6795 * prefer-global is set */
6796 if (((attr
->mp_nexthop_len
== 32)
6797 && !attr
->mp_nexthop_prefer_global
)
6798 || (path
->peer
->conf_if
)) {
6799 if (path
->peer
->conf_if
) {
6800 len
= vty_out(vty
, "%s",
6801 path
->peer
->conf_if
);
6802 len
= 16 - len
; /* len of IPv6
6808 vty_out(vty
, "\n%*s", 36, " ");
6810 vty_out(vty
, "%*s", len
, " ");
6816 &attr
->mp_nexthop_local
,
6822 vty_out(vty
, "\n%*s", 36, " ");
6824 vty_out(vty
, "%*s", len
, " ");
6830 &attr
->mp_nexthop_global
, buf
,
6836 vty_out(vty
, "\n%*s", 36, " ");
6838 vty_out(vty
, "%*s", len
, " ");
6844 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6848 * Adding "metric" field to match with corresponding
6849 * CLI. "med" will be deprecated in future.
6851 json_object_int_add(json_path
, "med", attr
->med
);
6852 json_object_int_add(json_path
, "metric", attr
->med
);
6854 vty_out(vty
, "%10u", attr
->med
);
6855 else if (!json_paths
)
6859 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6863 * Adding "locPrf" field to match with corresponding
6864 * CLI. "localPref" will be deprecated in future.
6866 json_object_int_add(json_path
, "localpref",
6868 json_object_int_add(json_path
, "locPrf",
6871 vty_out(vty
, "%7u", attr
->local_pref
);
6872 else if (!json_paths
)
6876 json_object_int_add(json_path
, "weight", attr
->weight
);
6878 vty_out(vty
, "%7u ", attr
->weight
);
6882 json_object_string_add(
6883 json_path
, "peerId",
6884 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6892 * Adding "path" field to match with corresponding
6893 * CLI. "aspath" will be deprecated in future.
6895 json_object_string_add(json_path
, "aspath",
6897 json_object_string_add(json_path
, "path",
6900 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6905 json_object_string_add(json_path
, "origin",
6906 bgp_origin_long_str
[attr
->origin
]);
6908 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6912 json_object_boolean_true_add(json_path
,
6913 "announceNexthopSelf");
6914 if (nexthop_othervrf
) {
6915 json_object_string_add(json_path
, "nhVrfName",
6918 json_object_int_add(json_path
, "nhVrfId",
6919 ((nexthop_vrfid
== VRF_UNKNOWN
)
6921 : (int)nexthop_vrfid
));
6926 if (json_nexthop_global
|| json_nexthop_ll
) {
6927 json_nexthops
= json_object_new_array();
6929 if (json_nexthop_global
)
6930 json_object_array_add(json_nexthops
,
6931 json_nexthop_global
);
6933 if (json_nexthop_ll
)
6934 json_object_array_add(json_nexthops
,
6937 json_object_object_add(json_path
, "nexthops",
6941 json_object_array_add(json_paths
, json_path
);
6945 /* prints an additional line, indented, with VNC info, if
6947 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6948 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
6953 /* called from terminal list command */
6954 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6955 safi_t safi
, bool use_json
, json_object
*json_ar
)
6957 json_object
*json_status
= NULL
;
6958 json_object
*json_net
= NULL
;
6961 /* Route status display. */
6963 json_status
= json_object_new_object();
6964 json_net
= json_object_new_object();
6971 /* print prefix and mask */
6973 json_object_string_add(
6974 json_net
, "addrPrefix",
6975 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6976 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
6977 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6978 json_object_string_add(json_net
, "network", buf2
);
6980 route_vty_out_route(p
, vty
, NULL
);
6982 /* Print attribute */
6985 if (p
->family
== AF_INET
6986 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6987 || safi
== SAFI_EVPN
6988 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6989 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6990 || safi
== SAFI_EVPN
)
6991 json_object_string_add(
6992 json_net
, "nextHop",
6994 attr
->mp_nexthop_global_in
));
6996 json_object_string_add(
6997 json_net
, "nextHop",
6998 inet_ntoa(attr
->nexthop
));
6999 } else if (p
->family
== AF_INET6
7000 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7003 json_object_string_add(
7004 json_net
, "nextHopGlobal",
7006 &attr
->mp_nexthop_global
, buf
,
7011 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7012 json_object_int_add(json_net
, "metric",
7015 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7018 * Adding "locPrf" field to match with
7019 * corresponding CLI. "localPref" will be
7020 * deprecated in future.
7022 json_object_int_add(json_net
, "localPref",
7024 json_object_int_add(json_net
, "locPrf",
7028 json_object_int_add(json_net
, "weight", attr
->weight
);
7034 * Adding "path" field to match with
7035 * corresponding CLI. "localPref" will be
7036 * deprecated in future.
7038 json_object_string_add(json_net
, "asPath",
7040 json_object_string_add(json_net
, "path",
7045 json_object_string_add(json_net
, "bgpOriginCode",
7046 bgp_origin_str
[attr
->origin
]);
7048 if (p
->family
== AF_INET
7049 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7050 || safi
== SAFI_EVPN
7051 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7052 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7053 || safi
== SAFI_EVPN
)
7054 vty_out(vty
, "%-16s",
7056 attr
->mp_nexthop_global_in
));
7058 vty_out(vty
, "%-16s",
7059 inet_ntoa(attr
->nexthop
));
7060 } else if (p
->family
== AF_INET6
7061 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7068 &attr
->mp_nexthop_global
, buf
,
7072 vty_out(vty
, "\n%*s", 36, " ");
7074 vty_out(vty
, "%*s", len
, " ");
7077 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7078 vty_out(vty
, "%10u", attr
->med
);
7082 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7083 vty_out(vty
, "%7u", attr
->local_pref
);
7087 vty_out(vty
, "%7u ", attr
->weight
);
7091 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7094 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7098 json_object_boolean_true_add(json_status
, "*");
7099 json_object_boolean_true_add(json_status
, ">");
7100 json_object_object_add(json_net
, "appliedStatusSymbols",
7102 char buf_cut
[BUFSIZ
];
7103 json_object_object_add(
7105 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7111 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7112 struct bgp_path_info
*path
, int display
, safi_t safi
,
7115 json_object
*json_out
= NULL
;
7117 mpls_label_t label
= MPLS_INVALID_LABEL
;
7123 json_out
= json_object_new_object();
7125 /* short status lead text */
7126 route_vty_short_status_out(vty
, path
, json_out
);
7128 /* print prefix and mask */
7131 route_vty_out_route(p
, vty
, NULL
);
7133 vty_out(vty
, "%*s", 17, " ");
7136 /* Print attribute */
7139 if (((p
->family
== AF_INET
)
7140 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7141 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7142 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7143 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7144 || safi
== SAFI_EVPN
) {
7146 json_object_string_add(
7147 json_out
, "mpNexthopGlobalIn",
7149 attr
->mp_nexthop_global_in
));
7151 vty_out(vty
, "%-16s",
7153 attr
->mp_nexthop_global_in
));
7156 json_object_string_add(
7157 json_out
, "nexthop",
7158 inet_ntoa(attr
->nexthop
));
7160 vty_out(vty
, "%-16s",
7161 inet_ntoa(attr
->nexthop
));
7163 } else if (((p
->family
== AF_INET6
)
7164 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7165 || (safi
== SAFI_EVPN
7166 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7167 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7171 if (attr
->mp_nexthop_len
7172 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7174 json_object_string_add(
7175 json_out
, "mpNexthopGlobalIn",
7178 &attr
->mp_nexthop_global
,
7179 buf_a
, sizeof(buf_a
)));
7184 &attr
->mp_nexthop_global
,
7185 buf_a
, sizeof(buf_a
)));
7186 } else if (attr
->mp_nexthop_len
7187 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7190 &attr
->mp_nexthop_global
,
7191 buf_a
, sizeof(buf_a
));
7193 &attr
->mp_nexthop_local
,
7194 buf_b
, sizeof(buf_b
));
7195 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7196 json_object_string_add(
7198 "mpNexthopGlobalLocal", buf_c
);
7200 vty_out(vty
, "%s(%s)",
7203 &attr
->mp_nexthop_global
,
7204 buf_a
, sizeof(buf_a
)),
7207 &attr
->mp_nexthop_local
,
7208 buf_b
, sizeof(buf_b
)));
7213 label
= decode_label(&path
->extra
->label
[0]);
7215 if (bgp_is_valid_label(&label
)) {
7217 json_object_int_add(json_out
, "notag", label
);
7218 json_object_array_add(json
, json_out
);
7220 vty_out(vty
, "notag/%d", label
);
7226 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7227 struct bgp_path_info
*path
, int display
,
7228 json_object
*json_paths
)
7232 json_object
*json_path
= NULL
;
7235 json_path
= json_object_new_object();
7240 /* short status lead text */
7241 route_vty_short_status_out(vty
, path
, json_path
);
7243 /* print prefix and mask */
7245 route_vty_out_route(p
, vty
, NULL
);
7247 vty_out(vty
, "%*s", 17, " ");
7249 /* Print attribute */
7253 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7257 vty_out(vty
, "%-16s",
7258 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7262 vty_out(vty
, "%s(%s)",
7263 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7265 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7272 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7274 vty_out(vty
, "%s", str
);
7275 XFREE(MTYPE_TMP
, str
);
7277 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7279 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7280 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7283 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7286 if (attr
->ecommunity
) {
7288 struct ecommunity_val
*routermac
= ecommunity_lookup(
7289 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7290 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7292 mac
= ecom_mac2str((char *)routermac
->val
);
7294 vty_out(vty
, "/%s", (char *)mac
);
7295 XFREE(MTYPE_TMP
, mac
);
7303 /* dampening route */
7304 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7305 struct bgp_path_info
*path
, int display
,
7306 safi_t safi
, bool use_json
, json_object
*json
)
7310 char timebuf
[BGP_UPTIME_LEN
];
7312 /* short status lead text */
7313 route_vty_short_status_out(vty
, path
, json
);
7315 /* print prefix and mask */
7318 route_vty_out_route(p
, vty
, NULL
);
7320 vty_out(vty
, "%*s", 17, " ");
7323 len
= vty_out(vty
, "%s", path
->peer
->host
);
7327 vty_out(vty
, "\n%*s", 34, " ");
7330 json_object_int_add(json
, "peerHost", len
);
7332 vty_out(vty
, "%*s", len
, " ");
7336 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7340 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7341 BGP_UPTIME_LEN
, use_json
,
7344 /* Print attribute */
7350 json_object_string_add(json
, "asPath",
7353 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7358 json_object_string_add(json
, "origin",
7359 bgp_origin_str
[attr
->origin
]);
7361 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7368 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7369 struct bgp_path_info
*path
, int display
,
7370 safi_t safi
, bool use_json
, json_object
*json
)
7373 struct bgp_damp_info
*bdi
;
7374 char timebuf
[BGP_UPTIME_LEN
];
7380 bdi
= path
->extra
->damp_info
;
7382 /* short status lead text */
7383 route_vty_short_status_out(vty
, path
, json
);
7385 /* print prefix and mask */
7388 route_vty_out_route(p
, vty
, NULL
);
7390 vty_out(vty
, "%*s", 17, " ");
7393 len
= vty_out(vty
, "%s", path
->peer
->host
);
7397 vty_out(vty
, "\n%*s", 33, " ");
7400 json_object_int_add(json
, "peerHost", len
);
7402 vty_out(vty
, "%*s", len
, " ");
7405 len
= vty_out(vty
, "%d", bdi
->flap
);
7412 json_object_int_add(json
, "bdiFlap", len
);
7414 vty_out(vty
, "%*s", len
, " ");
7418 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7421 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7422 BGP_UPTIME_LEN
, 0, NULL
));
7424 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7425 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7427 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7428 BGP_UPTIME_LEN
, use_json
, json
);
7431 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7436 vty_out(vty
, "%*s ", 8, " ");
7439 /* Print attribute */
7445 json_object_string_add(json
, "asPath",
7448 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7453 json_object_string_add(json
, "origin",
7454 bgp_origin_str
[attr
->origin
]);
7456 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7462 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7463 int *first
, const char *header
,
7464 json_object
*json_adv_to
)
7466 char buf1
[INET6_ADDRSTRLEN
];
7467 json_object
*json_peer
= NULL
;
7470 /* 'advertised-to' is a dictionary of peers we have advertised
7472 * prefix too. The key is the peer's IP or swpX, the value is
7474 * hostname if we know it and "" if not.
7476 json_peer
= json_object_new_object();
7479 json_object_string_add(json_peer
, "hostname",
7483 json_object_object_add(json_adv_to
, peer
->conf_if
,
7486 json_object_object_add(
7488 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7492 vty_out(vty
, "%s", header
);
7497 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7499 vty_out(vty
, " %s(%s)", peer
->hostname
,
7502 vty_out(vty
, " %s(%s)", peer
->hostname
,
7503 sockunion2str(&peer
->su
, buf1
,
7507 vty_out(vty
, " %s", peer
->conf_if
);
7510 sockunion2str(&peer
->su
, buf1
,
7516 static void route_vty_out_tx_ids(struct vty
*vty
,
7517 struct bgp_addpath_info_data
*d
)
7521 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7522 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7523 d
->addpath_tx_id
[i
],
7524 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7528 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7529 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7530 json_object
*json_paths
)
7532 char buf
[INET6_ADDRSTRLEN
];
7534 char buf2
[EVPN_ROUTE_STRLEN
];
7536 int sockunion_vty_out(struct vty
*, union sockunion
*);
7538 json_object
*json_bestpath
= NULL
;
7539 json_object
*json_cluster_list
= NULL
;
7540 json_object
*json_cluster_list_list
= NULL
;
7541 json_object
*json_ext_community
= NULL
;
7542 json_object
*json_last_update
= NULL
;
7543 json_object
*json_pmsi
= NULL
;
7544 json_object
*json_nexthop_global
= NULL
;
7545 json_object
*json_nexthop_ll
= NULL
;
7546 json_object
*json_nexthops
= NULL
;
7547 json_object
*json_path
= NULL
;
7548 json_object
*json_peer
= NULL
;
7549 json_object
*json_string
= NULL
;
7550 json_object
*json_adv_to
= NULL
;
7552 struct listnode
*node
, *nnode
;
7554 int addpath_capable
;
7556 unsigned int first_as
;
7558 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7562 json_path
= json_object_new_object();
7563 json_peer
= json_object_new_object();
7564 json_nexthop_global
= json_object_new_object();
7567 if (!json_paths
&& safi
== SAFI_EVPN
) {
7570 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7571 vty_out(vty
, " Route %s", buf2
);
7573 if (path
->extra
&& path
->extra
->num_labels
) {
7574 bgp_evpn_label2str(path
->extra
->label
,
7575 path
->extra
->num_labels
, tag_buf
,
7577 vty_out(vty
, " VNI %s", tag_buf
);
7580 if (path
->extra
&& path
->extra
->parent
) {
7581 struct bgp_path_info
*parent_ri
;
7582 struct bgp_node
*rn
, *prn
;
7584 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7585 rn
= parent_ri
->net
;
7586 if (rn
&& rn
->prn
) {
7588 vty_out(vty
, " Imported from %s:%s\n",
7590 (struct prefix_rd
*)&prn
->p
,
7591 buf1
, sizeof(buf1
)),
7600 /* Line1 display AS-path, Aggregator */
7603 if (!attr
->aspath
->json
)
7604 aspath_str_update(attr
->aspath
, true);
7605 json_object_lock(attr
->aspath
->json
);
7606 json_object_object_add(json_path
, "aspath",
7607 attr
->aspath
->json
);
7609 if (attr
->aspath
->segments
)
7610 aspath_print_vty(vty
, " %s",
7613 vty_out(vty
, " Local");
7617 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7619 json_object_boolean_true_add(json_path
,
7622 vty_out(vty
, ", (removed)");
7625 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7627 json_object_boolean_true_add(json_path
,
7630 vty_out(vty
, ", (stale)");
7633 if (CHECK_FLAG(attr
->flag
,
7634 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7636 json_object_int_add(json_path
, "aggregatorAs",
7637 attr
->aggregator_as
);
7638 json_object_string_add(
7639 json_path
, "aggregatorId",
7640 inet_ntoa(attr
->aggregator_addr
));
7642 vty_out(vty
, ", (aggregated by %u %s)",
7643 attr
->aggregator_as
,
7644 inet_ntoa(attr
->aggregator_addr
));
7648 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7649 PEER_FLAG_REFLECTOR_CLIENT
)) {
7651 json_object_boolean_true_add(
7652 json_path
, "rxedFromRrClient");
7654 vty_out(vty
, ", (Received from a RR-client)");
7657 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7658 PEER_FLAG_RSERVER_CLIENT
)) {
7660 json_object_boolean_true_add(
7661 json_path
, "rxedFromRsClient");
7663 vty_out(vty
, ", (Received from a RS-client)");
7666 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7668 json_object_boolean_true_add(
7669 json_path
, "dampeningHistoryEntry");
7671 vty_out(vty
, ", (history entry)");
7672 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
7674 json_object_boolean_true_add(
7675 json_path
, "dampeningSuppressed");
7677 vty_out(vty
, ", (suppressed due to dampening)");
7683 /* Line2 display Next-hop, Neighbor, Router-id */
7684 /* Display the nexthop */
7685 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7686 || p
->family
== AF_EVPN
)
7687 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7688 || safi
== SAFI_EVPN
7689 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7690 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7691 || safi
== SAFI_EVPN
) {
7693 json_object_string_add(
7694 json_nexthop_global
, "ip",
7696 attr
->mp_nexthop_global_in
));
7700 attr
->mp_nexthop_global_in
));
7703 json_object_string_add(
7704 json_nexthop_global
, "ip",
7705 inet_ntoa(attr
->nexthop
));
7708 inet_ntoa(attr
->nexthop
));
7712 json_object_string_add(json_nexthop_global
,
7716 json_object_string_add(
7717 json_nexthop_global
, "ip",
7719 &attr
->mp_nexthop_global
, buf
,
7721 json_object_string_add(json_nexthop_global
,
7723 json_object_string_add(json_nexthop_global
,
7728 &attr
->mp_nexthop_global
, buf
,
7733 /* Display the IGP cost or 'inaccessible' */
7734 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
7736 json_object_boolean_false_add(
7737 json_nexthop_global
, "accessible");
7739 vty_out(vty
, " (inaccessible)");
7741 if (path
->extra
&& path
->extra
->igpmetric
) {
7743 json_object_int_add(
7744 json_nexthop_global
, "metric",
7745 path
->extra
->igpmetric
);
7747 vty_out(vty
, " (metric %u)",
7748 path
->extra
->igpmetric
);
7751 /* IGP cost is 0, display this only for json */
7754 json_object_int_add(json_nexthop_global
,
7759 json_object_boolean_true_add(
7760 json_nexthop_global
, "accessible");
7763 /* Display peer "from" output */
7764 /* This path was originated locally */
7765 if (path
->peer
== bgp
->peer_self
) {
7767 if (safi
== SAFI_EVPN
7768 || (p
->family
== AF_INET
7769 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7771 json_object_string_add(
7772 json_peer
, "peerId", "0.0.0.0");
7774 vty_out(vty
, " from 0.0.0.0 ");
7777 json_object_string_add(json_peer
,
7780 vty_out(vty
, " from :: ");
7784 json_object_string_add(
7785 json_peer
, "routerId",
7786 inet_ntoa(bgp
->router_id
));
7788 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7791 /* We RXed this path from one of our peers */
7795 json_object_string_add(
7796 json_peer
, "peerId",
7797 sockunion2str(&path
->peer
->su
, buf
,
7799 json_object_string_add(
7800 json_peer
, "routerId",
7802 &path
->peer
->remote_id
, buf1
,
7805 if (path
->peer
->hostname
)
7806 json_object_string_add(
7807 json_peer
, "hostname",
7808 path
->peer
->hostname
);
7810 if (path
->peer
->domainname
)
7811 json_object_string_add(
7812 json_peer
, "domainname",
7813 path
->peer
->domainname
);
7815 if (path
->peer
->conf_if
)
7816 json_object_string_add(
7817 json_peer
, "interface",
7818 path
->peer
->conf_if
);
7820 if (path
->peer
->conf_if
) {
7821 if (path
->peer
->hostname
7824 BGP_FLAG_SHOW_HOSTNAME
))
7825 vty_out(vty
, " from %s(%s)",
7826 path
->peer
->hostname
,
7827 path
->peer
->conf_if
);
7829 vty_out(vty
, " from %s",
7830 path
->peer
->conf_if
);
7832 if (path
->peer
->hostname
7835 BGP_FLAG_SHOW_HOSTNAME
))
7836 vty_out(vty
, " from %s(%s)",
7837 path
->peer
->hostname
,
7840 vty_out(vty
, " from %s",
7848 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7849 vty_out(vty
, " (%s)",
7850 inet_ntoa(attr
->originator_id
));
7852 vty_out(vty
, " (%s)",
7855 &path
->peer
->remote_id
,
7856 buf1
, sizeof(buf1
)));
7861 * Note when vrfid of nexthop is different from that of prefix
7863 if (path
->extra
&& path
->extra
->bgp_orig
) {
7864 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7869 if (path
->extra
->bgp_orig
->inst_type
7870 == BGP_INSTANCE_TYPE_DEFAULT
)
7872 vn
= VRF_DEFAULT_NAME
;
7874 vn
= path
->extra
->bgp_orig
->name
;
7876 json_object_string_add(json_path
, "nhVrfName",
7879 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7880 json_object_int_add(json_path
,
7883 json_object_int_add(json_path
,
7884 "nhVrfId", (int)nexthop_vrfid
);
7887 if (nexthop_vrfid
== VRF_UNKNOWN
)
7888 vty_out(vty
, " vrf ?");
7890 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7896 json_object_boolean_true_add(json_path
,
7897 "announceNexthopSelf");
7899 vty_out(vty
, " announce-nh-self");
7906 /* display the link-local nexthop */
7907 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7909 json_nexthop_ll
= json_object_new_object();
7910 json_object_string_add(
7911 json_nexthop_ll
, "ip",
7913 &attr
->mp_nexthop_local
, buf
,
7915 json_object_string_add(json_nexthop_ll
, "afi",
7917 json_object_string_add(json_nexthop_ll
, "scope",
7920 json_object_boolean_true_add(json_nexthop_ll
,
7923 if (!attr
->mp_nexthop_prefer_global
)
7924 json_object_boolean_true_add(
7925 json_nexthop_ll
, "used");
7927 json_object_boolean_true_add(
7928 json_nexthop_global
, "used");
7930 vty_out(vty
, " (%s) %s\n",
7932 &attr
->mp_nexthop_local
, buf
,
7934 attr
->mp_nexthop_prefer_global
7939 /* If we do not have a link-local nexthop then we must flag the
7943 json_object_boolean_true_add(
7944 json_nexthop_global
, "used");
7947 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7948 * Int/Ext/Local, Atomic, best */
7950 json_object_string_add(
7951 json_path
, "origin",
7952 bgp_origin_long_str
[attr
->origin
]);
7954 vty_out(vty
, " Origin %s",
7955 bgp_origin_long_str
[attr
->origin
]);
7957 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7961 * Adding "metric" field to match with
7962 * corresponding CLI. "med" will be
7963 * deprecated in future.
7965 json_object_int_add(json_path
, "med",
7967 json_object_int_add(json_path
, "metric",
7970 vty_out(vty
, ", metric %u", attr
->med
);
7973 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7975 json_object_int_add(json_path
, "localpref",
7978 vty_out(vty
, ", localpref %u",
7982 if (attr
->weight
!= 0) {
7984 json_object_int_add(json_path
, "weight",
7987 vty_out(vty
, ", weight %u", attr
->weight
);
7990 if (attr
->tag
!= 0) {
7992 json_object_int_add(json_path
, "tag",
7995 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7999 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8001 json_object_boolean_false_add(json_path
,
8004 vty_out(vty
, ", invalid");
8005 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8007 json_object_boolean_true_add(json_path
,
8010 vty_out(vty
, ", valid");
8013 if (path
->peer
!= bgp
->peer_self
) {
8014 if (path
->peer
->as
== path
->peer
->local_as
) {
8015 if (CHECK_FLAG(bgp
->config
,
8016 BGP_CONFIG_CONFEDERATION
)) {
8018 json_object_string_add(
8023 ", confed-internal");
8026 json_object_string_add(
8030 vty_out(vty
, ", internal");
8033 if (bgp_confederation_peers_check(
8034 bgp
, path
->peer
->as
)) {
8036 json_object_string_add(
8041 ", confed-external");
8044 json_object_string_add(
8048 vty_out(vty
, ", external");
8051 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8053 json_object_boolean_true_add(json_path
,
8055 json_object_boolean_true_add(json_path
,
8058 vty_out(vty
, ", aggregated, local");
8060 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8062 json_object_boolean_true_add(json_path
,
8065 vty_out(vty
, ", sourced");
8068 json_object_boolean_true_add(json_path
,
8070 json_object_boolean_true_add(json_path
,
8073 vty_out(vty
, ", sourced, local");
8077 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8079 json_object_boolean_true_add(json_path
,
8082 vty_out(vty
, ", atomic-aggregate");
8085 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8086 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8087 && bgp_path_info_mpath_count(path
))) {
8089 json_object_boolean_true_add(json_path
,
8092 vty_out(vty
, ", multipath");
8095 // Mark the bestpath(s)
8096 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8097 first_as
= aspath_get_first_as(attr
->aspath
);
8102 json_object_new_object();
8103 json_object_int_add(json_bestpath
,
8104 "bestpathFromAs", first_as
);
8107 vty_out(vty
, ", bestpath-from-AS %u",
8111 ", bestpath-from-AS Local");
8115 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8119 json_object_new_object();
8120 json_object_boolean_true_add(json_bestpath
,
8123 vty_out(vty
, ", best");
8127 json_object_object_add(json_path
, "bestpath",
8133 /* Line 4 display Community */
8134 if (attr
->community
) {
8136 if (!attr
->community
->json
)
8137 community_str(attr
->community
, true);
8138 json_object_lock(attr
->community
->json
);
8139 json_object_object_add(json_path
, "community",
8140 attr
->community
->json
);
8142 vty_out(vty
, " Community: %s\n",
8143 attr
->community
->str
);
8147 /* Line 5 display Extended-community */
8148 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8150 json_ext_community
= json_object_new_object();
8151 json_object_string_add(json_ext_community
,
8153 attr
->ecommunity
->str
);
8154 json_object_object_add(json_path
,
8155 "extendedCommunity",
8156 json_ext_community
);
8158 vty_out(vty
, " Extended Community: %s\n",
8159 attr
->ecommunity
->str
);
8163 /* Line 6 display Large community */
8164 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8166 if (!attr
->lcommunity
->json
)
8167 lcommunity_str(attr
->lcommunity
, true);
8168 json_object_lock(attr
->lcommunity
->json
);
8169 json_object_object_add(json_path
,
8171 attr
->lcommunity
->json
);
8173 vty_out(vty
, " Large Community: %s\n",
8174 attr
->lcommunity
->str
);
8178 /* Line 7 display Originator, Cluster-id */
8179 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8180 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8182 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8184 json_object_string_add(
8185 json_path
, "originatorId",
8186 inet_ntoa(attr
->originator_id
));
8188 vty_out(vty
, " Originator: %s",
8189 inet_ntoa(attr
->originator_id
));
8192 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8197 json_object_new_object();
8198 json_cluster_list_list
=
8199 json_object_new_array();
8202 i
< attr
->cluster
->length
/ 4;
8204 json_string
= json_object_new_string(
8208 json_object_array_add(
8209 json_cluster_list_list
,
8213 /* struct cluster_list does not have
8215 * aspath and community do. Add this
8218 json_object_string_add(json_cluster_list,
8219 "string", attr->cluster->str);
8221 json_object_object_add(
8222 json_cluster_list
, "list",
8223 json_cluster_list_list
);
8224 json_object_object_add(
8225 json_path
, "clusterList",
8228 vty_out(vty
, ", Cluster list: ");
8231 i
< attr
->cluster
->length
/ 4;
8245 if (path
->extra
&& path
->extra
->damp_info
)
8246 bgp_damp_info_vty(vty
, path
, json_path
);
8249 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8250 && safi
!= SAFI_EVPN
) {
8251 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8254 json_object_int_add(json_path
, "remoteLabel",
8257 vty_out(vty
, " Remote label: %d\n", label
);
8261 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8263 json_object_int_add(json_path
, "labelIndex",
8266 vty_out(vty
, " Label Index: %d\n",
8270 /* Line 8 display Addpath IDs */
8271 if (path
->addpath_rx_id
8272 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8274 json_object_int_add(json_path
, "addpathRxId",
8275 path
->addpath_rx_id
);
8277 /* Keep backwards compatibility with the old API
8278 * by putting TX All's ID in the old field
8280 json_object_int_add(
8281 json_path
, "addpathTxId",
8282 path
->tx_addpath
.addpath_tx_id
8285 /* ... but create a specific field for each
8288 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8289 json_object_int_add(
8291 bgp_addpath_names(i
)
8297 vty_out(vty
, " AddPath ID: RX %u, ",
8298 path
->addpath_rx_id
);
8300 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8304 /* If we used addpath to TX a non-bestpath we need to display
8305 * "Advertised to" on a path-by-path basis
8307 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8310 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8312 bgp_addpath_encode_tx(peer
, afi
, safi
);
8313 has_adj
= bgp_adj_out_lookup(
8315 bgp_addpath_id_for_peer(
8317 &path
->tx_addpath
));
8319 if ((addpath_capable
&& has_adj
)
8320 || (!addpath_capable
&& has_adj
8321 && CHECK_FLAG(path
->flags
,
8322 BGP_PATH_SELECTED
))) {
8323 if (json_path
&& !json_adv_to
)
8325 json_object_new_object();
8327 route_vty_out_advertised_to(
8336 json_object_object_add(json_path
,
8347 /* Line 9 display Uptime */
8348 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8350 json_last_update
= json_object_new_object();
8351 json_object_int_add(json_last_update
, "epoch", tbuf
);
8352 json_object_string_add(json_last_update
, "string",
8354 json_object_object_add(json_path
, "lastUpdate",
8357 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8359 /* Line 10 display PMSI tunnel attribute, if present */
8360 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8361 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8362 attr
->pmsi_tnl_type
,
8363 PMSI_TNLTYPE_STR_DEFAULT
);
8366 json_pmsi
= json_object_new_object();
8367 json_object_string_add(json_pmsi
,
8369 json_object_object_add(json_path
, "pmsi",
8372 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8378 /* We've constructed the json object for this path, add it to the json
8382 if (json_nexthop_global
|| json_nexthop_ll
) {
8383 json_nexthops
= json_object_new_array();
8385 if (json_nexthop_global
)
8386 json_object_array_add(json_nexthops
,
8387 json_nexthop_global
);
8389 if (json_nexthop_ll
)
8390 json_object_array_add(json_nexthops
,
8393 json_object_object_add(json_path
, "nexthops",
8397 json_object_object_add(json_path
, "peer", json_peer
);
8398 json_object_array_add(json_paths
, json_path
);
8403 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8404 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8405 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8407 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8408 const char *prefix_list_str
, afi_t afi
,
8409 safi_t safi
, enum bgp_show_type type
);
8410 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8411 const char *filter
, afi_t afi
, safi_t safi
,
8412 enum bgp_show_type type
);
8413 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8414 const char *rmap_str
, afi_t afi
, safi_t safi
,
8415 enum bgp_show_type type
);
8416 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8417 const char *com
, int exact
, afi_t afi
,
8419 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8420 const char *prefix
, afi_t afi
, safi_t safi
,
8421 enum bgp_show_type type
);
8422 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8423 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8424 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8425 const char *comstr
, int exact
, afi_t afi
,
8426 safi_t safi
, bool use_json
);
8429 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8430 struct bgp_table
*table
, enum bgp_show_type type
,
8431 void *output_arg
, bool use_json
, char *rd
,
8432 int is_last
, unsigned long *output_cum
,
8433 unsigned long *total_cum
,
8434 unsigned long *json_header_depth
)
8436 struct bgp_path_info
*pi
;
8437 struct bgp_node
*rn
;
8440 unsigned long output_count
= 0;
8441 unsigned long total_count
= 0;
8444 json_object
*json_paths
= NULL
;
8447 if (output_cum
&& *output_cum
!= 0)
8450 if (use_json
&& !*json_header_depth
) {
8452 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8453 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8454 " \"localAS\": %u,\n \"routes\": { ",
8455 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8456 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8459 table
->version
, inet_ntoa(bgp
->router_id
),
8460 bgp
->default_local_pref
, bgp
->as
);
8461 *json_header_depth
= 2;
8463 vty_out(vty
, " \"routeDistinguishers\" : {");
8464 ++*json_header_depth
;
8468 if (use_json
&& rd
) {
8469 vty_out(vty
, " \"%s\" : { ", rd
);
8472 /* Start processing of routes. */
8473 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8474 pi
= bgp_node_get_bgp_path_info(rn
);
8480 json_paths
= json_object_new_array();
8484 for (; pi
; pi
= pi
->next
) {
8486 if (type
== bgp_show_type_flap_statistics
8487 || type
== bgp_show_type_flap_neighbor
8488 || type
== bgp_show_type_dampend_paths
8489 || type
== bgp_show_type_damp_neighbor
) {
8490 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8493 if (type
== bgp_show_type_regexp
) {
8494 regex_t
*regex
= output_arg
;
8496 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8500 if (type
== bgp_show_type_prefix_list
) {
8501 struct prefix_list
*plist
= output_arg
;
8503 if (prefix_list_apply(plist
, &rn
->p
)
8507 if (type
== bgp_show_type_filter_list
) {
8508 struct as_list
*as_list
= output_arg
;
8510 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8511 != AS_FILTER_PERMIT
)
8514 if (type
== bgp_show_type_route_map
) {
8515 struct route_map
*rmap
= output_arg
;
8516 struct bgp_path_info path
;
8517 struct attr dummy_attr
;
8520 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8522 path
.peer
= pi
->peer
;
8523 path
.attr
= &dummy_attr
;
8525 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8527 if (ret
== RMAP_DENYMATCH
)
8530 if (type
== bgp_show_type_neighbor
8531 || type
== bgp_show_type_flap_neighbor
8532 || type
== bgp_show_type_damp_neighbor
) {
8533 union sockunion
*su
= output_arg
;
8535 if (pi
->peer
== NULL
8536 || pi
->peer
->su_remote
== NULL
8537 || !sockunion_same(pi
->peer
->su_remote
, su
))
8540 if (type
== bgp_show_type_cidr_only
) {
8541 uint32_t destination
;
8543 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8544 if (IN_CLASSC(destination
)
8545 && rn
->p
.prefixlen
== 24)
8547 if (IN_CLASSB(destination
)
8548 && rn
->p
.prefixlen
== 16)
8550 if (IN_CLASSA(destination
)
8551 && rn
->p
.prefixlen
== 8)
8554 if (type
== bgp_show_type_prefix_longer
) {
8556 if (!prefix_match(p
, &rn
->p
))
8559 if (type
== bgp_show_type_community_all
) {
8560 if (!pi
->attr
->community
)
8563 if (type
== bgp_show_type_community
) {
8564 struct community
*com
= output_arg
;
8566 if (!pi
->attr
->community
8567 || !community_match(pi
->attr
->community
,
8571 if (type
== bgp_show_type_community_exact
) {
8572 struct community
*com
= output_arg
;
8574 if (!pi
->attr
->community
8575 || !community_cmp(pi
->attr
->community
, com
))
8578 if (type
== bgp_show_type_community_list
) {
8579 struct community_list
*list
= output_arg
;
8581 if (!community_list_match(pi
->attr
->community
,
8585 if (type
== bgp_show_type_community_list_exact
) {
8586 struct community_list
*list
= output_arg
;
8588 if (!community_list_exact_match(
8589 pi
->attr
->community
, list
))
8592 if (type
== bgp_show_type_lcommunity
) {
8593 struct lcommunity
*lcom
= output_arg
;
8595 if (!pi
->attr
->lcommunity
8596 || !lcommunity_match(pi
->attr
->lcommunity
,
8600 if (type
== bgp_show_type_lcommunity_list
) {
8601 struct community_list
*list
= output_arg
;
8603 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8607 if (type
== bgp_show_type_lcommunity_all
) {
8608 if (!pi
->attr
->lcommunity
)
8611 if (type
== bgp_show_type_dampend_paths
8612 || type
== bgp_show_type_damp_neighbor
) {
8613 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8614 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8618 if (!use_json
&& header
) {
8619 vty_out(vty
, "BGP table version is %" PRIu64
8620 ", local router ID is %s, vrf id ",
8622 inet_ntoa(bgp
->router_id
));
8623 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8624 vty_out(vty
, "%s", VRFID_NONE_STR
);
8626 vty_out(vty
, "%u", bgp
->vrf_id
);
8628 vty_out(vty
, "Default local pref %u, ",
8629 bgp
->default_local_pref
);
8630 vty_out(vty
, "local AS %u\n", bgp
->as
);
8631 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8632 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8633 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8634 if (type
== bgp_show_type_dampend_paths
8635 || type
== bgp_show_type_damp_neighbor
)
8636 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8637 else if (type
== bgp_show_type_flap_statistics
8638 || type
== bgp_show_type_flap_neighbor
)
8639 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8641 vty_out(vty
, BGP_SHOW_HEADER
);
8644 if (rd
!= NULL
&& !display
&& !output_count
) {
8647 "Route Distinguisher: %s\n",
8650 if (type
== bgp_show_type_dampend_paths
8651 || type
== bgp_show_type_damp_neighbor
)
8652 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
8653 safi
, use_json
, json_paths
);
8654 else if (type
== bgp_show_type_flap_statistics
8655 || type
== bgp_show_type_flap_neighbor
)
8656 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
8657 safi
, use_json
, json_paths
);
8659 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
8671 if (p
->family
== AF_FLOWSPEC
) {
8672 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
8674 bgp_fs_nlri_get_string((unsigned char *)
8675 p
->u
.prefix_flowspec
.ptr
,
8676 p
->u
.prefix_flowspec
8679 NLRI_STRING_FORMAT_MIN
,
8682 vty_out(vty
, "\"%s/%d\": ",
8684 p
->u
.prefix_flowspec
.prefixlen
);
8686 vty_out(vty
, ",\"%s/%d\": ",
8688 p
->u
.prefix_flowspec
.prefixlen
);
8690 prefix2str(p
, buf2
, sizeof(buf2
));
8692 vty_out(vty
, "\"%s\": ", buf2
);
8694 vty_out(vty
, ",\"%s\": ", buf2
);
8697 json_object_to_json_string(json_paths
));
8698 json_object_free(json_paths
);
8705 output_count
+= *output_cum
;
8706 *output_cum
= output_count
;
8709 total_count
+= *total_cum
;
8710 *total_cum
= total_count
;
8714 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8718 for (i
= 0; i
< *json_header_depth
; ++i
)
8719 vty_out(vty
, " } ");
8723 /* No route is displayed */
8724 if (output_count
== 0) {
8725 if (type
== bgp_show_type_normal
)
8727 "No BGP prefixes displayed, %ld exist\n",
8731 "\nDisplayed %ld routes and %ld total paths\n",
8732 output_count
, total_count
);
8739 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8740 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8741 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8743 struct bgp_node
*rn
, *next
;
8744 unsigned long output_cum
= 0;
8745 unsigned long total_cum
= 0;
8746 unsigned long json_header_depth
= 0;
8747 struct bgp_table
*itable
;
8750 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8752 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8753 next
= bgp_route_next(rn
);
8754 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8757 itable
= bgp_node_get_bgp_table_info(rn
);
8758 if (itable
!= NULL
) {
8759 struct prefix_rd prd
;
8760 char rd
[RD_ADDRSTRLEN
];
8762 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8763 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8764 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
8765 use_json
, rd
, next
== NULL
, &output_cum
,
8766 &total_cum
, &json_header_depth
);
8772 if (output_cum
== 0)
8773 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8777 "\nDisplayed %ld routes and %ld total paths\n",
8778 output_cum
, total_cum
);
8782 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8783 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8785 struct bgp_table
*table
;
8786 unsigned long json_header_depth
= 0;
8789 bgp
= bgp_get_default();
8794 vty_out(vty
, "No BGP process is configured\n");
8796 vty_out(vty
, "{}\n");
8800 table
= bgp
->rib
[afi
][safi
];
8801 /* use MPLS and ENCAP specific shows until they are merged */
8802 if (safi
== SAFI_MPLS_VPN
) {
8803 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8804 output_arg
, use_json
);
8807 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8808 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8809 output_arg
, use_json
,
8812 /* labeled-unicast routes live in the unicast table */
8813 else if (safi
== SAFI_LABELED_UNICAST
)
8814 safi
= SAFI_UNICAST
;
8816 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8817 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8820 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8821 safi_t safi
, bool use_json
)
8823 struct listnode
*node
, *nnode
;
8826 bool route_output
= false;
8829 vty_out(vty
, "{\n");
8831 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8832 route_output
= true;
8835 vty_out(vty
, ",\n");
8839 vty_out(vty
, "\"%s\":",
8840 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8844 vty_out(vty
, "\nInstance %s:\n",
8845 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8849 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8854 vty_out(vty
, "}\n");
8855 else if (!route_output
)
8856 vty_out(vty
, "%% BGP instance not found\n");
8859 /* Header of detailed BGP route information */
8860 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8861 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8862 afi_t afi
, safi_t safi
, json_object
*json
)
8864 struct bgp_path_info
*pi
;
8867 struct listnode
*node
, *nnode
;
8868 char buf1
[RD_ADDRSTRLEN
];
8869 char buf2
[INET6_ADDRSTRLEN
];
8870 char buf3
[EVPN_ROUTE_STRLEN
];
8871 char prefix_str
[BUFSIZ
];
8876 int route_filter_translated_v4
= 0;
8877 int route_filter_v4
= 0;
8878 int route_filter_translated_v6
= 0;
8879 int route_filter_v6
= 0;
8882 int accept_own_nexthop
= 0;
8885 int no_advertise
= 0;
8889 int has_valid_label
= 0;
8890 mpls_label_t label
= 0;
8891 json_object
*json_adv_to
= NULL
;
8894 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8896 if (has_valid_label
)
8897 label
= label_pton(&rn
->local_label
);
8900 if (has_valid_label
)
8901 json_object_int_add(json
, "localLabel", label
);
8903 json_object_string_add(
8905 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8907 if (safi
== SAFI_EVPN
)
8908 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8909 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8912 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8913 buf3
, sizeof(buf3
)));
8915 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8916 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8917 ? prefix_rd2str(prd
, buf1
,
8920 safi
== SAFI_MPLS_VPN
? ":" : "",
8921 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8925 if (has_valid_label
)
8926 vty_out(vty
, "Local label: %d\n", label
);
8927 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8928 vty_out(vty
, "not allocated\n");
8931 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
8933 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
8935 if (pi
->extra
&& pi
->extra
->suppress
)
8938 if (pi
->attr
->community
== NULL
)
8941 no_advertise
+= community_include(
8942 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
8943 no_export
+= community_include(pi
->attr
->community
,
8944 COMMUNITY_NO_EXPORT
);
8945 local_as
+= community_include(pi
->attr
->community
,
8946 COMMUNITY_LOCAL_AS
);
8947 accept_own
+= community_include(pi
->attr
->community
,
8948 COMMUNITY_ACCEPT_OWN
);
8949 route_filter_translated_v4
+= community_include(
8950 pi
->attr
->community
,
8951 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
8952 route_filter_translated_v6
+= community_include(
8953 pi
->attr
->community
,
8954 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
8955 route_filter_v4
+= community_include(
8956 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
8957 route_filter_v6
+= community_include(
8958 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
8959 llgr_stale
+= community_include(pi
->attr
->community
,
8960 COMMUNITY_LLGR_STALE
);
8961 no_llgr
+= community_include(pi
->attr
->community
,
8963 accept_own_nexthop
+=
8964 community_include(pi
->attr
->community
,
8965 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
8966 blackhole
+= community_include(pi
->attr
->community
,
8967 COMMUNITY_BLACKHOLE
);
8968 no_peer
+= community_include(pi
->attr
->community
,
8974 vty_out(vty
, "Paths: (%d available", count
);
8976 vty_out(vty
, ", best #%d", best
);
8977 if (safi
== SAFI_UNICAST
)
8978 vty_out(vty
, ", table %s",
8980 == BGP_INSTANCE_TYPE_DEFAULT
)
8984 vty_out(vty
, ", no best path");
8988 ", accept own local route exported and imported in different VRF");
8989 else if (route_filter_translated_v4
)
8991 ", mark translated RTs for VPNv4 route filtering");
8992 else if (route_filter_v4
)
8994 ", attach RT as-is for VPNv4 route filtering");
8995 else if (route_filter_translated_v6
)
8997 ", mark translated RTs for VPNv6 route filtering");
8998 else if (route_filter_v6
)
9000 ", attach RT as-is for VPNv6 route filtering");
9001 else if (llgr_stale
)
9003 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9006 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9007 else if (accept_own_nexthop
)
9009 ", accept local nexthop");
9011 vty_out(vty
, ", inform peer to blackhole prefix");
9013 vty_out(vty
, ", not advertised to EBGP peer");
9014 else if (no_advertise
)
9015 vty_out(vty
, ", not advertised to any peer");
9017 vty_out(vty
, ", not advertised outside local AS");
9020 ", inform EBGP peer not to advertise to their EBGP peers");
9024 ", Advertisements suppressed by an aggregate.");
9025 vty_out(vty
, ")\n");
9028 /* If we are not using addpath then we can display Advertised to and
9030 * show what peers we advertised the bestpath to. If we are using
9032 * though then we must display Advertised to on a path-by-path basis. */
9033 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9034 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9035 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9036 if (json
&& !json_adv_to
)
9037 json_adv_to
= json_object_new_object();
9039 route_vty_out_advertised_to(
9041 " Advertised to non peer-group peers:\n ",
9048 json_object_object_add(json
, "advertisedTo",
9053 vty_out(vty
, " Not advertised to any peer");
9059 /* Display specified route of BGP table. */
9060 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9061 struct bgp_table
*rib
, const char *ip_str
,
9062 afi_t afi
, safi_t safi
,
9063 struct prefix_rd
*prd
, int prefix_check
,
9064 enum bgp_path_type pathtype
, bool use_json
)
9069 struct prefix match
;
9070 struct bgp_node
*rn
;
9071 struct bgp_node
*rm
;
9072 struct bgp_path_info
*pi
;
9073 struct bgp_table
*table
;
9074 json_object
*json
= NULL
;
9075 json_object
*json_paths
= NULL
;
9077 /* Check IP address argument. */
9078 ret
= str2prefix(ip_str
, &match
);
9080 vty_out(vty
, "address is malformed\n");
9084 match
.family
= afi2family(afi
);
9087 json
= json_object_new_object();
9088 json_paths
= json_object_new_array();
9091 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9092 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9093 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9095 table
= bgp_node_get_bgp_table_info(rn
);
9101 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9105 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9106 bgp_unlock_node(rm
);
9110 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9113 route_vty_out_detail_header(
9115 (struct prefix_rd
*)&rn
->p
,
9116 AFI_IP
, safi
, json
);
9121 if (pathtype
== BGP_PATH_SHOW_ALL
9122 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9123 && CHECK_FLAG(pi
->flags
,
9125 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9126 && (CHECK_FLAG(pi
->flags
,
9128 || CHECK_FLAG(pi
->flags
,
9129 BGP_PATH_SELECTED
))))
9130 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9135 bgp_unlock_node(rm
);
9137 } else if (safi
== SAFI_FLOWSPEC
) {
9138 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9139 &match
, prefix_check
,
9146 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9148 || rn
->p
.prefixlen
== match
.prefixlen
) {
9149 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9152 route_vty_out_detail_header(
9153 vty
, bgp
, rn
, NULL
, afi
,
9159 if (pathtype
== BGP_PATH_SHOW_ALL
9161 == BGP_PATH_SHOW_BESTPATH
9166 == BGP_PATH_SHOW_MULTIPATH
9172 BGP_PATH_SELECTED
))))
9173 route_vty_out_detail(
9174 vty
, bgp
, &rn
->p
, pi
,
9175 afi
, safi
, json_paths
);
9179 bgp_unlock_node(rn
);
9185 json_object_object_add(json
, "paths", json_paths
);
9187 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9188 json
, JSON_C_TO_STRING_PRETTY
));
9189 json_object_free(json
);
9192 vty_out(vty
, "%% Network not in table\n");
9200 /* Display specified route of Main RIB */
9201 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9202 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9203 int prefix_check
, enum bgp_path_type pathtype
,
9207 bgp
= bgp_get_default();
9210 vty_out(vty
, "No BGP process is configured\n");
9212 vty_out(vty
, "{}\n");
9217 /* labeled-unicast routes live in the unicast table */
9218 if (safi
== SAFI_LABELED_UNICAST
)
9219 safi
= SAFI_UNICAST
;
9221 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9222 afi
, safi
, prd
, prefix_check
, pathtype
,
9226 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9227 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9230 struct lcommunity
*lcom
;
9236 b
= buffer_new(1024);
9237 for (i
= 0; i
< argc
; i
++) {
9239 buffer_putc(b
, ' ');
9241 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9243 buffer_putstr(b
, argv
[i
]->arg
);
9247 buffer_putc(b
, '\0');
9249 str
= buffer_getstr(b
);
9252 lcom
= lcommunity_str2com(str
);
9253 XFREE(MTYPE_TMP
, str
);
9255 vty_out(vty
, "%% Large-community malformed\n");
9259 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9263 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9264 const char *lcom
, afi_t afi
, safi_t safi
,
9267 struct community_list
*list
;
9269 list
= community_list_lookup(bgp_clist
, lcom
,
9270 LARGE_COMMUNITY_LIST_MASTER
);
9272 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9277 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9281 DEFUN (show_ip_bgp_large_community_list
,
9282 show_ip_bgp_large_community_list_cmd
,
9283 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9287 BGP_INSTANCE_HELP_STR
9289 BGP_SAFI_WITH_LABEL_HELP_STR
9290 "Display routes matching the large-community-list\n"
9291 "large-community-list number\n"
9292 "large-community-list name\n"
9296 afi_t afi
= AFI_IP6
;
9297 safi_t safi
= SAFI_UNICAST
;
9300 if (argv_find(argv
, argc
, "ip", &idx
))
9302 if (argv_find(argv
, argc
, "view", &idx
)
9303 || argv_find(argv
, argc
, "vrf", &idx
))
9304 vrf
= argv
[++idx
]->arg
;
9305 if (argv_find(argv
, argc
, "ipv4", &idx
)
9306 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9307 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9308 if (argv_find(argv
, argc
, "unicast", &idx
)
9309 || argv_find(argv
, argc
, "multicast", &idx
))
9310 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9313 bool uj
= use_json(argc
, argv
);
9315 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9317 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9321 argv_find(argv
, argc
, "large-community-list", &idx
);
9322 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9325 DEFUN (show_ip_bgp_large_community
,
9326 show_ip_bgp_large_community_cmd
,
9327 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9331 BGP_INSTANCE_HELP_STR
9333 BGP_SAFI_WITH_LABEL_HELP_STR
9334 "Display routes matching the large-communities\n"
9335 "List of large-community numbers\n"
9339 afi_t afi
= AFI_IP6
;
9340 safi_t safi
= SAFI_UNICAST
;
9343 if (argv_find(argv
, argc
, "ip", &idx
))
9345 if (argv_find(argv
, argc
, "view", &idx
)
9346 || argv_find(argv
, argc
, "vrf", &idx
))
9347 vrf
= argv
[++idx
]->arg
;
9348 if (argv_find(argv
, argc
, "ipv4", &idx
)
9349 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9350 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9351 if (argv_find(argv
, argc
, "unicast", &idx
)
9352 || argv_find(argv
, argc
, "multicast", &idx
))
9353 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9356 bool uj
= use_json(argc
, argv
);
9358 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9360 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9364 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9365 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9367 return bgp_show(vty
, bgp
, afi
, safi
,
9368 bgp_show_type_lcommunity_all
, NULL
, uj
);
9371 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9375 /* BGP route print out function without JSON */
9378 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9379 <dampening <parameters>\
9384 |community-list <(1-500)|WORD> [exact-match]\
9385 |A.B.C.D/M longer-prefixes\
9386 |X:X::X:X/M longer-prefixes\
9391 BGP_INSTANCE_HELP_STR
9393 BGP_SAFI_WITH_LABEL_HELP_STR
9394 "Display detailed information about dampening\n"
9395 "Display detail of configured dampening parameters\n"
9396 "Display routes matching the route-map\n"
9397 "A route-map to match on\n"
9398 "Display routes conforming to the prefix-list\n"
9399 "Prefix-list name\n"
9400 "Display routes conforming to the filter-list\n"
9401 "Regular expression access list name\n"
9402 "BGP RIB advertisement statistics\n"
9403 "Display routes matching the community-list\n"
9404 "community-list number\n"
9405 "community-list name\n"
9406 "Exact match of the communities\n"
9408 "Display route and more specific routes\n"
9410 "Display route and more specific routes\n")
9412 afi_t afi
= AFI_IP6
;
9413 safi_t safi
= SAFI_UNICAST
;
9414 int exact_match
= 0;
9415 struct bgp
*bgp
= NULL
;
9418 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9423 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9424 if (argv_find(argv
, argc
, "parameters", &idx
))
9425 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9428 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9429 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9430 safi
, bgp_show_type_prefix_list
);
9432 if (argv_find(argv
, argc
, "filter-list", &idx
))
9433 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9434 safi
, bgp_show_type_filter_list
);
9436 if (argv_find(argv
, argc
, "statistics", &idx
))
9437 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9439 if (argv_find(argv
, argc
, "route-map", &idx
))
9440 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9441 safi
, bgp_show_type_route_map
);
9443 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9444 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9445 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9447 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9448 exact_match
, afi
, safi
);
9451 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9452 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9453 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9455 bgp_show_type_prefix_longer
);
9460 /* BGP route print out function with JSON */
9461 DEFUN (show_ip_bgp_json
,
9462 show_ip_bgp_json_cmd
,
9463 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9465 |dampening <flap-statistics|dampened-paths>\
9466 |community [AA:NN|local-AS|no-advertise|no-export\
9467 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9468 |accept-own|accept-own-nexthop|route-filter-v6\
9469 |route-filter-v4|route-filter-translated-v6\
9470 |route-filter-translated-v4] [exact-match]\
9475 BGP_INSTANCE_HELP_STR
9477 BGP_SAFI_WITH_LABEL_HELP_STR
9478 "Display only routes with non-natural netmasks\n"
9479 "Display detailed information about dampening\n"
9480 "Display flap statistics of routes\n"
9481 "Display paths suppressed due to dampening\n"
9482 "Display routes matching the communities\n"
9484 "Do not send outside local AS (well-known community)\n"
9485 "Do not advertise to any peer (well-known community)\n"
9486 "Do not export to next AS (well-known community)\n"
9487 "Graceful shutdown (well-known community)\n"
9488 "Do not export to any peer (well-known community)\n"
9489 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9490 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9491 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9492 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9493 "Should accept VPN route with local nexthop (well-known community)\n"
9494 "RT VPNv6 route filtering (well-known community)\n"
9495 "RT VPNv4 route filtering (well-known community)\n"
9496 "RT translated VPNv6 route filtering (well-known community)\n"
9497 "RT translated VPNv4 route filtering (well-known community)\n"
9498 "Exact match of the communities\n"
9501 afi_t afi
= AFI_IP6
;
9502 safi_t safi
= SAFI_UNICAST
;
9503 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9504 struct bgp
*bgp
= NULL
;
9506 int exact_match
= 0;
9507 bool uj
= use_json(argc
, argv
);
9512 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9517 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9518 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9521 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9522 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9523 return bgp_show(vty
, bgp
, afi
, safi
,
9524 bgp_show_type_dampend_paths
, NULL
, uj
);
9525 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9526 return bgp_show(vty
, bgp
, afi
, safi
,
9527 bgp_show_type_flap_statistics
, NULL
,
9531 if (argv_find(argv
, argc
, "community", &idx
)) {
9532 char *maybecomm
= idx
+ 1 < argc
? argv
[idx
+ 1]->text
: NULL
;
9533 char *community
= NULL
;
9535 if (maybecomm
&& !strmatch(maybecomm
, "json")
9536 && !strmatch(maybecomm
, "exact-match"))
9537 community
= maybecomm
;
9539 if (argv_find(argv
, argc
, "exact-match", &idx
))
9543 return bgp_show_community(vty
, bgp
, community
,
9544 exact_match
, afi
, safi
, uj
);
9546 return (bgp_show(vty
, bgp
, afi
, safi
,
9547 bgp_show_type_community_all
, NULL
,
9551 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9554 DEFUN (show_ip_bgp_route
,
9555 show_ip_bgp_route_cmd
,
9556 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9557 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9561 BGP_INSTANCE_HELP_STR
9563 BGP_SAFI_WITH_LABEL_HELP_STR
9564 "Network in the BGP routing table to display\n"
9566 "Network in the BGP routing table to display\n"
9568 "Display only the bestpath\n"
9569 "Display only multipaths\n"
9572 int prefix_check
= 0;
9574 afi_t afi
= AFI_IP6
;
9575 safi_t safi
= SAFI_UNICAST
;
9576 char *prefix
= NULL
;
9577 struct bgp
*bgp
= NULL
;
9578 enum bgp_path_type path_type
;
9579 bool uj
= use_json(argc
, argv
);
9583 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9590 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9594 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9595 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9596 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9598 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9599 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9602 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9603 && afi
!= AFI_IP6
) {
9605 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9608 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9611 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9615 prefix
= argv
[idx
]->arg
;
9617 /* [<bestpath|multipath>] */
9618 if (argv_find(argv
, argc
, "bestpath", &idx
))
9619 path_type
= BGP_PATH_SHOW_BESTPATH
;
9620 else if (argv_find(argv
, argc
, "multipath", &idx
))
9621 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9623 path_type
= BGP_PATH_SHOW_ALL
;
9625 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9629 DEFUN (show_ip_bgp_regexp
,
9630 show_ip_bgp_regexp_cmd
,
9631 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9635 BGP_INSTANCE_HELP_STR
9637 BGP_SAFI_WITH_LABEL_HELP_STR
9638 "Display routes matching the AS path regular expression\n"
9639 "A regular-expression to match the BGP AS paths\n")
9641 afi_t afi
= AFI_IP6
;
9642 safi_t safi
= SAFI_UNICAST
;
9643 struct bgp
*bgp
= NULL
;
9646 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9651 // get index of regex
9652 argv_find(argv
, argc
, "regexp", &idx
);
9655 char *regstr
= argv_concat(argv
, argc
, idx
);
9656 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9657 bgp_show_type_regexp
);
9658 XFREE(MTYPE_TMP
, regstr
);
9662 DEFUN (show_ip_bgp_instance_all
,
9663 show_ip_bgp_instance_all_cmd
,
9664 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9668 BGP_INSTANCE_ALL_HELP_STR
9670 BGP_SAFI_WITH_LABEL_HELP_STR
9674 safi_t safi
= SAFI_UNICAST
;
9675 struct bgp
*bgp
= NULL
;
9677 bool uj
= use_json(argc
, argv
);
9682 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9687 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9691 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9692 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9697 regex
= bgp_regcomp(regstr
);
9699 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9703 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9704 bgp_regex_free(regex
);
9708 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9709 const char *prefix_list_str
, afi_t afi
,
9710 safi_t safi
, enum bgp_show_type type
)
9712 struct prefix_list
*plist
;
9714 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9715 if (plist
== NULL
) {
9716 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9721 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9724 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9725 const char *filter
, afi_t afi
, safi_t safi
,
9726 enum bgp_show_type type
)
9728 struct as_list
*as_list
;
9730 as_list
= as_list_lookup(filter
);
9731 if (as_list
== NULL
) {
9732 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9737 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9740 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9741 const char *rmap_str
, afi_t afi
, safi_t safi
,
9742 enum bgp_show_type type
)
9744 struct route_map
*rmap
;
9746 rmap
= route_map_lookup_by_name(rmap_str
);
9748 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9752 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9755 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9756 const char *comstr
, int exact
, afi_t afi
,
9757 safi_t safi
, bool use_json
)
9759 struct community
*com
;
9762 com
= community_str2com(comstr
);
9764 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9768 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9769 (exact
? bgp_show_type_community_exact
9770 : bgp_show_type_community
),
9772 community_free(&com
);
9777 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9778 const char *com
, int exact
, afi_t afi
,
9781 struct community_list
*list
;
9783 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9785 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9789 return bgp_show(vty
, bgp
, afi
, safi
,
9790 (exact
? bgp_show_type_community_list_exact
9791 : bgp_show_type_community_list
),
9795 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9796 const char *prefix
, afi_t afi
, safi_t safi
,
9797 enum bgp_show_type type
)
9804 ret
= str2prefix(prefix
, p
);
9806 vty_out(vty
, "%% Malformed Prefix\n");
9810 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9815 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9816 const char *ip_str
, bool use_json
)
9822 /* Get peer sockunion. */
9823 ret
= str2sockunion(ip_str
, &su
);
9825 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9827 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9831 json_object
*json_no
= NULL
;
9832 json_no
= json_object_new_object();
9833 json_object_string_add(
9835 "malformedAddressOrName",
9837 vty_out(vty
, "%s\n",
9838 json_object_to_json_string_ext(
9840 JSON_C_TO_STRING_PRETTY
));
9841 json_object_free(json_no
);
9844 "%% Malformed address or name: %s\n",
9852 /* Peer structure lookup. */
9853 peer
= peer_lookup(bgp
, &su
);
9856 json_object
*json_no
= NULL
;
9857 json_no
= json_object_new_object();
9858 json_object_string_add(json_no
, "warning",
9859 "No such neighbor in this view/vrf");
9860 vty_out(vty
, "%s\n",
9861 json_object_to_json_string_ext(
9862 json_no
, JSON_C_TO_STRING_PRETTY
));
9863 json_object_free(json_no
);
9865 vty_out(vty
, "No such neighbor in this view/vrf\n");
9873 BGP_STATS_MAXBITLEN
= 0,
9877 BGP_STATS_UNAGGREGATEABLE
,
9878 BGP_STATS_MAX_AGGREGATEABLE
,
9879 BGP_STATS_AGGREGATES
,
9881 BGP_STATS_ASPATH_COUNT
,
9882 BGP_STATS_ASPATH_MAXHOPS
,
9883 BGP_STATS_ASPATH_TOTHOPS
,
9884 BGP_STATS_ASPATH_MAXSIZE
,
9885 BGP_STATS_ASPATH_TOTSIZE
,
9886 BGP_STATS_ASN_HIGHEST
,
9890 static const char *table_stats_strs
[] = {
9891 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9892 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9893 [BGP_STATS_RIB
] = "Total Advertisements",
9894 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9895 [BGP_STATS_MAX_AGGREGATEABLE
] =
9896 "Maximum aggregateable prefixes",
9897 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9898 [BGP_STATS_SPACE
] = "Address space advertised",
9899 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9900 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9901 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9902 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9903 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9904 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9905 [BGP_STATS_MAX
] = NULL
,
9908 struct bgp_table_stats
{
9909 struct bgp_table
*table
;
9910 unsigned long long counts
[BGP_STATS_MAX
];
9915 #define TALLY_SIGFIG 100000
9916 static unsigned long
9917 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9919 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9920 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9921 unsigned long ret
= newtot
/ count
;
9923 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9930 static int bgp_table_stats_walker(struct thread
*t
)
9932 struct bgp_node
*rn
;
9933 struct bgp_node
*top
;
9934 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9935 unsigned int space
= 0;
9937 if (!(top
= bgp_table_top(ts
->table
)))
9940 switch (top
->p
.family
) {
9942 space
= IPV4_MAX_BITLEN
;
9945 space
= IPV6_MAX_BITLEN
;
9949 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9951 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9952 struct bgp_path_info
*pi
;
9953 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9954 unsigned int pinum
= 0;
9959 if (!bgp_node_has_bgp_path_info_data(rn
))
9962 ts
->counts
[BGP_STATS_PREFIXES
]++;
9963 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9966 ts
->counts
[BGP_STATS_AVGPLEN
]
9967 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9968 ts
->counts
[BGP_STATS_AVGPLEN
],
9972 /* check if the prefix is included by any other announcements */
9973 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
9974 prn
= bgp_node_parent_nolock(prn
);
9976 if (prn
== NULL
|| prn
== top
) {
9977 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9978 /* announced address space */
9981 pow(2.0, space
- rn
->p
.prefixlen
);
9982 } else if (bgp_node_has_bgp_path_info_data(prn
))
9983 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9985 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9987 ts
->counts
[BGP_STATS_RIB
]++;
9990 && (CHECK_FLAG(pi
->attr
->flag
,
9992 BGP_ATTR_ATOMIC_AGGREGATE
))))
9993 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9996 if (pi
->attr
&& pi
->attr
->aspath
) {
9998 aspath_count_hops(pi
->attr
->aspath
);
10000 aspath_size(pi
->attr
->aspath
);
10001 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10003 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10005 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10006 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
10009 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10010 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
10013 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10014 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10016 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10017 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10018 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10020 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10021 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10022 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10025 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10026 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
10034 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10037 struct bgp_table_stats ts
;
10040 if (!bgp
->rib
[afi
][safi
]) {
10041 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10043 return CMD_WARNING
;
10046 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10048 /* labeled-unicast routes live in the unicast table */
10049 if (safi
== SAFI_LABELED_UNICAST
)
10050 safi
= SAFI_UNICAST
;
10052 memset(&ts
, 0, sizeof(ts
));
10053 ts
.table
= bgp
->rib
[afi
][safi
];
10054 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10056 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10057 if (!table_stats_strs
[i
])
10062 case BGP_STATS_ASPATH_AVGHOPS
:
10063 case BGP_STATS_ASPATH_AVGSIZE
:
10064 case BGP_STATS_AVGPLEN
:
10065 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10066 vty_out (vty
, "%12.2f",
10067 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10070 case BGP_STATS_ASPATH_TOTHOPS
:
10071 case BGP_STATS_ASPATH_TOTSIZE
:
10072 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10073 vty_out(vty
, "%12.2f",
10075 ? (float)ts
.counts
[i
]
10077 [BGP_STATS_ASPATH_COUNT
]
10080 case BGP_STATS_TOTPLEN
:
10081 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10082 vty_out(vty
, "%12.2f",
10084 ? (float)ts
.counts
[i
]
10086 [BGP_STATS_PREFIXES
]
10089 case BGP_STATS_SPACE
:
10090 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10091 vty_out(vty
, "%12g\n", ts
.total_space
);
10093 if (afi
== AFI_IP6
) {
10094 vty_out(vty
, "%30s: ", "/32 equivalent ");
10095 vty_out(vty
, "%12g\n",
10096 ts
.total_space
* pow(2.0, -128 + 32));
10097 vty_out(vty
, "%30s: ", "/48 equivalent ");
10098 vty_out(vty
, "%12g\n",
10099 ts
.total_space
* pow(2.0, -128 + 48));
10101 vty_out(vty
, "%30s: ", "% announced ");
10102 vty_out(vty
, "%12.2f\n",
10103 ts
.total_space
* 100. * pow(2.0, -32));
10104 vty_out(vty
, "%30s: ", "/8 equivalent ");
10105 vty_out(vty
, "%12.2f\n",
10106 ts
.total_space
* pow(2.0, -32 + 8));
10107 vty_out(vty
, "%30s: ", "/24 equivalent ");
10108 vty_out(vty
, "%12.2f\n",
10109 ts
.total_space
* pow(2.0, -32 + 24));
10113 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10114 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10117 vty_out(vty
, "\n");
10119 return CMD_SUCCESS
;
10131 PCOUNT_PFCNT
, /* the figure we display to users */
10135 static const char *pcount_strs
[] = {
10136 [PCOUNT_ADJ_IN
] = "Adj-in",
10137 [PCOUNT_DAMPED
] = "Damped",
10138 [PCOUNT_REMOVED
] = "Removed",
10139 [PCOUNT_HISTORY
] = "History",
10140 [PCOUNT_STALE
] = "Stale",
10141 [PCOUNT_VALID
] = "Valid",
10142 [PCOUNT_ALL
] = "All RIB",
10143 [PCOUNT_COUNTED
] = "PfxCt counted",
10144 [PCOUNT_PFCNT
] = "Useable",
10145 [PCOUNT_MAX
] = NULL
,
10148 struct peer_pcounts
{
10149 unsigned int count
[PCOUNT_MAX
];
10150 const struct peer
*peer
;
10151 const struct bgp_table
*table
;
10154 static int bgp_peer_count_walker(struct thread
*t
)
10156 struct bgp_node
*rn
;
10157 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10158 const struct peer
*peer
= pc
->peer
;
10160 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10161 struct bgp_adj_in
*ain
;
10162 struct bgp_path_info
*pi
;
10164 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10165 if (ain
->peer
== peer
)
10166 pc
->count
[PCOUNT_ADJ_IN
]++;
10168 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10170 if (pi
->peer
!= peer
)
10173 pc
->count
[PCOUNT_ALL
]++;
10175 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10176 pc
->count
[PCOUNT_DAMPED
]++;
10177 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10178 pc
->count
[PCOUNT_HISTORY
]++;
10179 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10180 pc
->count
[PCOUNT_REMOVED
]++;
10181 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10182 pc
->count
[PCOUNT_STALE
]++;
10183 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10184 pc
->count
[PCOUNT_VALID
]++;
10185 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10186 pc
->count
[PCOUNT_PFCNT
]++;
10188 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10189 pc
->count
[PCOUNT_COUNTED
]++;
10190 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10192 EC_LIB_DEVELOPMENT
,
10193 "Attempting to count but flags say it is unusable");
10195 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10197 EC_LIB_DEVELOPMENT
,
10198 "Not counted but flags say we should");
10205 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10206 safi_t safi
, bool use_json
)
10208 struct peer_pcounts pcounts
= {.peer
= peer
};
10210 json_object
*json
= NULL
;
10211 json_object
*json_loop
= NULL
;
10214 json
= json_object_new_object();
10215 json_loop
= json_object_new_object();
10218 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10219 || !peer
->bgp
->rib
[afi
][safi
]) {
10221 json_object_string_add(
10223 "No such neighbor or address family");
10224 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10225 json_object_free(json
);
10227 vty_out(vty
, "%% No such neighbor or address family\n");
10229 return CMD_WARNING
;
10232 memset(&pcounts
, 0, sizeof(pcounts
));
10233 pcounts
.peer
= peer
;
10234 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10236 /* in-place call via thread subsystem so as to record execution time
10237 * stats for the thread-walk (i.e. ensure this can't be blamed on
10238 * on just vty_read()).
10240 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10243 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10244 json_object_string_add(json
, "multiProtocol",
10245 afi_safi_print(afi
, safi
));
10246 json_object_int_add(json
, "pfxCounter",
10247 peer
->pcount
[afi
][safi
]);
10249 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10250 json_object_int_add(json_loop
, pcount_strs
[i
],
10253 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10255 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10256 json_object_string_add(json
, "pfxctDriftFor",
10258 json_object_string_add(
10259 json
, "recommended",
10260 "Please report this bug, with the above command output");
10262 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10263 json
, JSON_C_TO_STRING_PRETTY
));
10264 json_object_free(json
);
10268 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10269 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10270 peer
->hostname
, peer
->host
,
10271 afi_safi_print(afi
, safi
));
10273 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10274 afi_safi_print(afi
, safi
));
10277 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10278 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10280 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10281 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10284 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10285 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10287 "Please report this bug, with the above command output\n");
10291 return CMD_SUCCESS
;
10294 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10295 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10296 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10297 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10301 BGP_INSTANCE_HELP_STR
10304 "Detailed information on TCP and BGP neighbor connections\n"
10305 "Neighbor to display information about\n"
10306 "Neighbor to display information about\n"
10307 "Neighbor on BGP configured interface\n"
10308 "Display detailed prefix count information\n"
10311 afi_t afi
= AFI_IP6
;
10312 safi_t safi
= SAFI_UNICAST
;
10315 struct bgp
*bgp
= NULL
;
10316 bool uj
= use_json(argc
, argv
);
10321 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10324 return CMD_WARNING
;
10326 argv_find(argv
, argc
, "neighbors", &idx
);
10327 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10329 return CMD_WARNING
;
10331 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10334 #ifdef KEEP_OLD_VPN_COMMANDS
10335 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10336 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10337 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10342 "Display information about all VPNv4 NLRIs\n"
10343 "Detailed information on TCP and BGP neighbor connections\n"
10344 "Neighbor to display information about\n"
10345 "Neighbor to display information about\n"
10346 "Neighbor on BGP configured interface\n"
10347 "Display detailed prefix count information\n"
10352 bool uj
= use_json(argc
, argv
);
10354 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10356 return CMD_WARNING
;
10358 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10361 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10362 show_ip_bgp_vpn_all_route_prefix_cmd
,
10363 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10368 "Display information about all VPNv4 NLRIs\n"
10369 "Network in the BGP routing table to display\n"
10370 "Network in the BGP routing table to display\n"
10374 char *network
= NULL
;
10375 struct bgp
*bgp
= bgp_get_default();
10377 vty_out(vty
, "Can't find default instance\n");
10378 return CMD_WARNING
;
10381 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10382 network
= argv
[idx
]->arg
;
10383 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10384 network
= argv
[idx
]->arg
;
10386 vty_out(vty
, "Unable to figure out Network\n");
10387 return CMD_WARNING
;
10390 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10391 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10393 #endif /* KEEP_OLD_VPN_COMMANDS */
10395 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10396 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10397 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10403 "Display information about all EVPN NLRIs\n"
10404 "Network in the BGP routing table to display\n"
10405 "Network in the BGP routing table to display\n"
10409 char *network
= NULL
;
10411 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10412 network
= argv
[idx
]->arg
;
10413 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10414 network
= argv
[idx
]->arg
;
10416 vty_out(vty
, "Unable to figure out Network\n");
10417 return CMD_WARNING
;
10419 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10420 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10423 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10424 safi_t safi
, enum bgp_show_adj_route_type type
,
10425 const char *rmap_name
, bool use_json
,
10428 struct bgp_table
*table
;
10429 struct bgp_adj_in
*ain
;
10430 struct bgp_adj_out
*adj
;
10431 unsigned long output_count
;
10432 unsigned long filtered_count
;
10433 struct bgp_node
*rn
;
10439 struct update_subgroup
*subgrp
;
10440 json_object
*json_scode
= NULL
;
10441 json_object
*json_ocode
= NULL
;
10442 json_object
*json_ar
= NULL
;
10443 struct peer_af
*paf
;
10444 bool route_filtered
;
10447 json_scode
= json_object_new_object();
10448 json_ocode
= json_object_new_object();
10449 json_ar
= json_object_new_object();
10451 json_object_string_add(json_scode
, "suppressed", "s");
10452 json_object_string_add(json_scode
, "damped", "d");
10453 json_object_string_add(json_scode
, "history", "h");
10454 json_object_string_add(json_scode
, "valid", "*");
10455 json_object_string_add(json_scode
, "best", ">");
10456 json_object_string_add(json_scode
, "multipath", "=");
10457 json_object_string_add(json_scode
, "internal", "i");
10458 json_object_string_add(json_scode
, "ribFailure", "r");
10459 json_object_string_add(json_scode
, "stale", "S");
10460 json_object_string_add(json_scode
, "removed", "R");
10462 json_object_string_add(json_ocode
, "igp", "i");
10463 json_object_string_add(json_ocode
, "egp", "e");
10464 json_object_string_add(json_ocode
, "incomplete", "?");
10471 json_object_string_add(json
, "alert", "no BGP");
10472 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10473 json_object_free(json
);
10475 vty_out(vty
, "%% No bgp\n");
10479 table
= bgp
->rib
[afi
][safi
];
10481 output_count
= filtered_count
= 0;
10482 subgrp
= peer_subgroup(peer
, afi
, safi
);
10484 if (type
== bgp_show_adj_route_advertised
&& subgrp
10485 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10487 json_object_int_add(json
, "bgpTableVersion",
10489 json_object_string_add(json
, "bgpLocalRouterId",
10490 inet_ntoa(bgp
->router_id
));
10491 json_object_int_add(json
, "defaultLocPrf",
10492 bgp
->default_local_pref
);
10493 json_object_int_add(json
, "localAS", bgp
->as
);
10494 json_object_object_add(json
, "bgpStatusCodes",
10496 json_object_object_add(json
, "bgpOriginCodes",
10498 json_object_string_add(
10499 json
, "bgpOriginatingDefaultNetwork",
10500 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10502 vty_out(vty
, "BGP table version is %" PRIu64
10503 ", local router ID is %s, vrf id ",
10504 table
->version
, inet_ntoa(bgp
->router_id
));
10505 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10506 vty_out(vty
, "%s", VRFID_NONE_STR
);
10508 vty_out(vty
, "%u", bgp
->vrf_id
);
10509 vty_out(vty
, "\n");
10510 vty_out(vty
, "Default local pref %u, ",
10511 bgp
->default_local_pref
);
10512 vty_out(vty
, "local AS %u\n", bgp
->as
);
10513 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10514 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10515 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10517 vty_out(vty
, "Originating default network %s\n\n",
10518 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10523 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10524 if (type
== bgp_show_adj_route_received
10525 || type
== bgp_show_adj_route_filtered
) {
10526 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10527 if (ain
->peer
!= peer
|| !ain
->attr
)
10532 json_object_int_add(
10533 json
, "bgpTableVersion",
10535 json_object_string_add(
10537 "bgpLocalRouterId",
10540 json_object_int_add(json
,
10542 bgp
->default_local_pref
);
10543 json_object_int_add(json
,
10544 "localAS", bgp
->as
);
10545 json_object_object_add(
10546 json
, "bgpStatusCodes",
10548 json_object_object_add(
10549 json
, "bgpOriginCodes",
10553 "BGP table version is 0, local router ID is %s, vrf id ",
10556 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10562 vty_out(vty
, "\n");
10564 "Default local pref %u, ",
10565 bgp
->default_local_pref
);
10566 vty_out(vty
, "local AS %u\n",
10569 BGP_SHOW_SCODE_HEADER
);
10571 BGP_SHOW_NCODE_HEADER
);
10573 BGP_SHOW_OCODE_HEADER
);
10579 vty_out(vty
, BGP_SHOW_HEADER
);
10583 bgp_attr_dup(&attr
, ain
->attr
);
10584 route_filtered
= false;
10586 /* Filter prefix using distribute list,
10587 * filter list or prefix list
10589 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10590 safi
)) == FILTER_DENY
)
10591 route_filtered
= true;
10593 /* Filter prefix using route-map */
10594 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10595 afi
, safi
, rmap_name
);
10597 if (type
== bgp_show_adj_route_filtered
&&
10598 !route_filtered
&& ret
!= RMAP_DENY
) {
10599 bgp_attr_undup(&attr
, ain
->attr
);
10603 if (type
== bgp_show_adj_route_received
&&
10604 (route_filtered
|| ret
== RMAP_DENY
))
10607 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10608 use_json
, json_ar
);
10609 bgp_attr_undup(&attr
, ain
->attr
);
10612 } else if (type
== bgp_show_adj_route_advertised
) {
10613 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
10614 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10615 if (paf
->peer
!= peer
|| !adj
->attr
)
10620 json_object_int_add(
10624 json_object_string_add(
10626 "bgpLocalRouterId",
10629 json_object_int_add(
10630 json
, "defaultLocPrf",
10631 bgp
->default_local_pref
10633 json_object_int_add(
10636 json_object_object_add(
10640 json_object_object_add(
10646 "BGP table version is %" PRIu64
10647 ", local router ID is %s, vrf id ",
10660 vty_out(vty
, "\n");
10662 "Default local pref %u, ",
10663 bgp
->default_local_pref
10669 BGP_SHOW_SCODE_HEADER
);
10671 BGP_SHOW_NCODE_HEADER
);
10673 BGP_SHOW_OCODE_HEADER
);
10684 bgp_attr_dup(&attr
, adj
->attr
);
10685 ret
= bgp_output_modifier(
10686 peer
, &rn
->p
, &attr
, afi
, safi
,
10689 if (ret
!= RMAP_DENY
) {
10690 route_vty_out_tmp(vty
, &rn
->p
,
10699 bgp_attr_undup(&attr
, adj
->attr
);
10705 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10706 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10707 json_object_int_add(json
, "filteredPrefixCounter",
10710 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10711 json
, JSON_C_TO_STRING_PRETTY
));
10712 json_object_free(json
);
10713 } else if (output_count
> 0) {
10714 if (filtered_count
> 0)
10716 "\nTotal number of prefixes %ld (%ld filtered)\n",
10717 output_count
, filtered_count
);
10719 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10724 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10725 safi_t safi
, enum bgp_show_adj_route_type type
,
10726 const char *rmap_name
, bool use_json
)
10728 json_object
*json
= NULL
;
10731 json
= json_object_new_object();
10733 /* labeled-unicast routes live in the unicast table */
10734 if (safi
== SAFI_LABELED_UNICAST
)
10735 safi
= SAFI_UNICAST
;
10737 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10739 json_object_string_add(
10741 "No such neighbor or address family");
10742 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10743 json_object_free(json
);
10745 vty_out(vty
, "%% No such neighbor or address family\n");
10747 return CMD_WARNING
;
10750 if ((type
== bgp_show_adj_route_received
10751 || type
== bgp_show_adj_route_filtered
)
10752 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10753 PEER_FLAG_SOFT_RECONFIG
)) {
10755 json_object_string_add(
10757 "Inbound soft reconfiguration not enabled");
10758 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10759 json_object_free(json
);
10762 "%% Inbound soft reconfiguration not enabled\n");
10764 return CMD_WARNING
;
10767 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10769 return CMD_SUCCESS
;
10772 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10773 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10774 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10775 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10779 BGP_INSTANCE_HELP_STR
10781 BGP_SAFI_WITH_LABEL_HELP_STR
10782 "Detailed information on TCP and BGP neighbor connections\n"
10783 "Neighbor to display information about\n"
10784 "Neighbor to display information about\n"
10785 "Neighbor on BGP configured interface\n"
10786 "Display the routes advertised to a BGP neighbor\n"
10787 "Display the received routes from neighbor\n"
10788 "Display the filtered routes received from neighbor\n"
10789 "Route-map to modify the attributes\n"
10790 "Name of the route map\n"
10793 afi_t afi
= AFI_IP6
;
10794 safi_t safi
= SAFI_UNICAST
;
10795 char *rmap_name
= NULL
;
10796 char *peerstr
= NULL
;
10797 struct bgp
*bgp
= NULL
;
10799 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10801 bool uj
= use_json(argc
, argv
);
10806 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10809 return CMD_WARNING
;
10811 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10812 argv_find(argv
, argc
, "neighbors", &idx
);
10813 peerstr
= argv
[++idx
]->arg
;
10815 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10817 return CMD_WARNING
;
10819 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10820 type
= bgp_show_adj_route_advertised
;
10821 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10822 type
= bgp_show_adj_route_received
;
10823 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10824 type
= bgp_show_adj_route_filtered
;
10826 if (argv_find(argv
, argc
, "route-map", &idx
))
10827 rmap_name
= argv
[++idx
]->arg
;
10829 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10832 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10833 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10834 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10840 "Address Family modifier\n"
10841 "Detailed information on TCP and BGP neighbor connections\n"
10842 "Neighbor to display information about\n"
10843 "Neighbor to display information about\n"
10844 "Neighbor on BGP configured interface\n"
10845 "Display information received from a BGP neighbor\n"
10846 "Display the prefixlist filter\n"
10849 afi_t afi
= AFI_IP6
;
10850 safi_t safi
= SAFI_UNICAST
;
10851 char *peerstr
= NULL
;
10854 union sockunion su
;
10860 /* show [ip] bgp */
10861 if (argv_find(argv
, argc
, "ip", &idx
))
10863 /* [<ipv4|ipv6> [unicast]] */
10864 if (argv_find(argv
, argc
, "ipv4", &idx
))
10866 if (argv_find(argv
, argc
, "ipv6", &idx
))
10868 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10869 argv_find(argv
, argc
, "neighbors", &idx
);
10870 peerstr
= argv
[++idx
]->arg
;
10872 bool uj
= use_json(argc
, argv
);
10874 ret
= str2sockunion(peerstr
, &su
);
10876 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10879 vty_out(vty
, "{}\n");
10882 "%% Malformed address or name: %s\n",
10884 return CMD_WARNING
;
10887 peer
= peer_lookup(NULL
, &su
);
10890 vty_out(vty
, "{}\n");
10892 vty_out(vty
, "No peer\n");
10893 return CMD_WARNING
;
10897 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10898 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10901 vty_out(vty
, "Address Family: %s\n",
10902 afi_safi_print(afi
, safi
));
10903 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10906 vty_out(vty
, "{}\n");
10908 vty_out(vty
, "No functional output\n");
10911 return CMD_SUCCESS
;
10914 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10915 afi_t afi
, safi_t safi
,
10916 enum bgp_show_type type
, bool use_json
)
10918 /* labeled-unicast routes live in the unicast table */
10919 if (safi
== SAFI_LABELED_UNICAST
)
10920 safi
= SAFI_UNICAST
;
10922 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10924 json_object
*json_no
= NULL
;
10925 json_no
= json_object_new_object();
10926 json_object_string_add(
10927 json_no
, "warning",
10928 "No such neighbor or address family");
10929 vty_out(vty
, "%s\n",
10930 json_object_to_json_string(json_no
));
10931 json_object_free(json_no
);
10933 vty_out(vty
, "%% No such neighbor or address family\n");
10934 return CMD_WARNING
;
10937 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10940 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10941 show_ip_bgp_flowspec_routes_detailed_cmd
,
10942 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10946 BGP_INSTANCE_HELP_STR
10949 "Detailed information on flowspec entries\n"
10952 afi_t afi
= AFI_IP
;
10953 safi_t safi
= SAFI_UNICAST
;
10954 struct bgp
*bgp
= NULL
;
10956 bool uj
= use_json(argc
, argv
);
10961 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10964 return CMD_WARNING
;
10966 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
10969 DEFUN (show_ip_bgp_neighbor_routes
,
10970 show_ip_bgp_neighbor_routes_cmd
,
10971 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10972 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10976 BGP_INSTANCE_HELP_STR
10978 BGP_SAFI_WITH_LABEL_HELP_STR
10979 "Detailed information on TCP and BGP neighbor connections\n"
10980 "Neighbor to display information about\n"
10981 "Neighbor to display information about\n"
10982 "Neighbor on BGP configured interface\n"
10983 "Display flap statistics of the routes learned from neighbor\n"
10984 "Display the dampened routes received from neighbor\n"
10985 "Display routes learned from neighbor\n"
10988 char *peerstr
= NULL
;
10989 struct bgp
*bgp
= NULL
;
10990 afi_t afi
= AFI_IP6
;
10991 safi_t safi
= SAFI_UNICAST
;
10993 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10995 bool uj
= use_json(argc
, argv
);
11000 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11003 return CMD_WARNING
;
11005 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11006 argv_find(argv
, argc
, "neighbors", &idx
);
11007 peerstr
= argv
[++idx
]->arg
;
11009 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11011 return CMD_WARNING
;
11013 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11014 sh_type
= bgp_show_type_flap_neighbor
;
11015 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11016 sh_type
= bgp_show_type_damp_neighbor
;
11017 else if (argv_find(argv
, argc
, "routes", &idx
))
11018 sh_type
= bgp_show_type_neighbor
;
11020 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11023 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11025 struct bgp_distance
{
11026 /* Distance value for the IP source prefix. */
11029 /* Name of the access-list to be matched. */
11033 DEFUN (show_bgp_afi_vpn_rd_route
,
11034 show_bgp_afi_vpn_rd_route_cmd
,
11035 "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]",
11039 "Address Family modifier\n"
11040 "Display information for a route distinguisher\n"
11041 "Route Distinguisher\n"
11042 "Network in the BGP routing table to display\n"
11043 "Network in the BGP routing table to display\n"
11047 struct prefix_rd prd
;
11048 afi_t afi
= AFI_MAX
;
11051 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11052 vty_out(vty
, "%% Malformed Address Family\n");
11053 return CMD_WARNING
;
11056 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11058 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11059 return CMD_WARNING
;
11062 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11063 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11066 static struct bgp_distance
*bgp_distance_new(void)
11068 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11071 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11073 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11076 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11077 const char *ip_str
, const char *access_list_str
)
11084 struct bgp_node
*rn
;
11085 struct bgp_distance
*bdistance
;
11087 afi
= bgp_node_afi(vty
);
11088 safi
= bgp_node_safi(vty
);
11090 ret
= str2prefix(ip_str
, &p
);
11092 vty_out(vty
, "Malformed prefix\n");
11093 return CMD_WARNING_CONFIG_FAILED
;
11096 distance
= atoi(distance_str
);
11098 /* Get BGP distance node. */
11099 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11100 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11102 bgp_unlock_node(rn
);
11104 bdistance
= bgp_distance_new();
11105 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11108 /* Set distance value. */
11109 bdistance
->distance
= distance
;
11111 /* Reset access-list configuration. */
11112 if (bdistance
->access_list
) {
11113 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11114 bdistance
->access_list
= NULL
;
11116 if (access_list_str
)
11117 bdistance
->access_list
=
11118 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11120 return CMD_SUCCESS
;
11123 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11124 const char *ip_str
, const char *access_list_str
)
11131 struct bgp_node
*rn
;
11132 struct bgp_distance
*bdistance
;
11134 afi
= bgp_node_afi(vty
);
11135 safi
= bgp_node_safi(vty
);
11137 ret
= str2prefix(ip_str
, &p
);
11139 vty_out(vty
, "Malformed prefix\n");
11140 return CMD_WARNING_CONFIG_FAILED
;
11143 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11144 (struct prefix
*)&p
);
11146 vty_out(vty
, "Can't find specified prefix\n");
11147 return CMD_WARNING_CONFIG_FAILED
;
11150 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11151 distance
= atoi(distance_str
);
11153 if (bdistance
->distance
!= distance
) {
11154 vty_out(vty
, "Distance does not match configured\n");
11155 return CMD_WARNING_CONFIG_FAILED
;
11158 if (bdistance
->access_list
)
11159 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11160 bgp_distance_free(bdistance
);
11162 bgp_node_set_bgp_path_info(rn
, NULL
);
11163 bgp_unlock_node(rn
);
11164 bgp_unlock_node(rn
);
11166 return CMD_SUCCESS
;
11169 /* Apply BGP information to distance method. */
11170 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11171 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11173 struct bgp_node
*rn
;
11176 struct bgp_distance
*bdistance
;
11177 struct access_list
*alist
;
11178 struct bgp_static
*bgp_static
;
11183 peer
= pinfo
->peer
;
11185 /* Check source address. */
11186 sockunion2hostprefix(&peer
->su
, &q
);
11187 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11189 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11190 bgp_unlock_node(rn
);
11192 if (bdistance
->access_list
) {
11193 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11195 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11196 return bdistance
->distance
;
11198 return bdistance
->distance
;
11201 /* Backdoor check. */
11202 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11204 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11205 bgp_unlock_node(rn
);
11207 if (bgp_static
->backdoor
) {
11208 if (bgp
->distance_local
[afi
][safi
])
11209 return bgp
->distance_local
[afi
][safi
];
11211 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11215 if (peer
->sort
== BGP_PEER_EBGP
) {
11216 if (bgp
->distance_ebgp
[afi
][safi
])
11217 return bgp
->distance_ebgp
[afi
][safi
];
11218 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11220 if (bgp
->distance_ibgp
[afi
][safi
])
11221 return bgp
->distance_ibgp
[afi
][safi
];
11222 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11226 DEFUN (bgp_distance
,
11228 "distance bgp (1-255) (1-255) (1-255)",
11229 "Define an administrative distance\n"
11231 "Distance for routes external to the AS\n"
11232 "Distance for routes internal to the AS\n"
11233 "Distance for local routes\n")
11235 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11236 int idx_number
= 2;
11237 int idx_number_2
= 3;
11238 int idx_number_3
= 4;
11242 afi
= bgp_node_afi(vty
);
11243 safi
= bgp_node_safi(vty
);
11245 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11246 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11247 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11248 return CMD_SUCCESS
;
11251 DEFUN (no_bgp_distance
,
11252 no_bgp_distance_cmd
,
11253 "no distance bgp [(1-255) (1-255) (1-255)]",
11255 "Define an administrative distance\n"
11257 "Distance for routes external to the AS\n"
11258 "Distance for routes internal to the AS\n"
11259 "Distance for local routes\n")
11261 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11265 afi
= bgp_node_afi(vty
);
11266 safi
= bgp_node_safi(vty
);
11268 bgp
->distance_ebgp
[afi
][safi
] = 0;
11269 bgp
->distance_ibgp
[afi
][safi
] = 0;
11270 bgp
->distance_local
[afi
][safi
] = 0;
11271 return CMD_SUCCESS
;
11275 DEFUN (bgp_distance_source
,
11276 bgp_distance_source_cmd
,
11277 "distance (1-255) A.B.C.D/M",
11278 "Define an administrative distance\n"
11279 "Administrative distance\n"
11280 "IP source prefix\n")
11282 int idx_number
= 1;
11283 int idx_ipv4_prefixlen
= 2;
11284 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11285 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11286 return CMD_SUCCESS
;
11289 DEFUN (no_bgp_distance_source
,
11290 no_bgp_distance_source_cmd
,
11291 "no distance (1-255) A.B.C.D/M",
11293 "Define an administrative distance\n"
11294 "Administrative distance\n"
11295 "IP source prefix\n")
11297 int idx_number
= 2;
11298 int idx_ipv4_prefixlen
= 3;
11299 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11300 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11301 return CMD_SUCCESS
;
11304 DEFUN (bgp_distance_source_access_list
,
11305 bgp_distance_source_access_list_cmd
,
11306 "distance (1-255) A.B.C.D/M WORD",
11307 "Define an administrative distance\n"
11308 "Administrative distance\n"
11309 "IP source prefix\n"
11310 "Access list name\n")
11312 int idx_number
= 1;
11313 int idx_ipv4_prefixlen
= 2;
11315 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11316 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11317 return CMD_SUCCESS
;
11320 DEFUN (no_bgp_distance_source_access_list
,
11321 no_bgp_distance_source_access_list_cmd
,
11322 "no distance (1-255) A.B.C.D/M WORD",
11324 "Define an administrative distance\n"
11325 "Administrative distance\n"
11326 "IP source prefix\n"
11327 "Access list name\n")
11329 int idx_number
= 2;
11330 int idx_ipv4_prefixlen
= 3;
11332 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11333 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11334 return CMD_SUCCESS
;
11337 DEFUN (ipv6_bgp_distance_source
,
11338 ipv6_bgp_distance_source_cmd
,
11339 "distance (1-255) X:X::X:X/M",
11340 "Define an administrative distance\n"
11341 "Administrative distance\n"
11342 "IP source prefix\n")
11344 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11345 return CMD_SUCCESS
;
11348 DEFUN (no_ipv6_bgp_distance_source
,
11349 no_ipv6_bgp_distance_source_cmd
,
11350 "no distance (1-255) X:X::X:X/M",
11352 "Define an administrative distance\n"
11353 "Administrative distance\n"
11354 "IP source prefix\n")
11356 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11357 return CMD_SUCCESS
;
11360 DEFUN (ipv6_bgp_distance_source_access_list
,
11361 ipv6_bgp_distance_source_access_list_cmd
,
11362 "distance (1-255) X:X::X:X/M WORD",
11363 "Define an administrative distance\n"
11364 "Administrative distance\n"
11365 "IP source prefix\n"
11366 "Access list name\n")
11368 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11369 return CMD_SUCCESS
;
11372 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11373 no_ipv6_bgp_distance_source_access_list_cmd
,
11374 "no distance (1-255) X:X::X:X/M WORD",
11376 "Define an administrative distance\n"
11377 "Administrative distance\n"
11378 "IP source prefix\n"
11379 "Access list name\n")
11381 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11382 return CMD_SUCCESS
;
11385 DEFUN (bgp_damp_set
,
11387 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11388 "BGP Specific commands\n"
11389 "Enable route-flap dampening\n"
11390 "Half-life time for the penalty\n"
11391 "Value to start reusing a route\n"
11392 "Value to start suppressing a route\n"
11393 "Maximum duration to suppress a stable route\n")
11395 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11396 int idx_half_life
= 2;
11398 int idx_suppress
= 4;
11399 int idx_max_suppress
= 5;
11400 int half
= DEFAULT_HALF_LIFE
* 60;
11401 int reuse
= DEFAULT_REUSE
;
11402 int suppress
= DEFAULT_SUPPRESS
;
11403 int max
= 4 * half
;
11406 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11407 reuse
= atoi(argv
[idx_reuse
]->arg
);
11408 suppress
= atoi(argv
[idx_suppress
]->arg
);
11409 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11410 } else if (argc
== 3) {
11411 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11415 if (suppress
< reuse
) {
11417 "Suppress value cannot be less than reuse value \n");
11421 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11422 reuse
, suppress
, max
);
11425 DEFUN (bgp_damp_unset
,
11426 bgp_damp_unset_cmd
,
11427 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11429 "BGP Specific commands\n"
11430 "Enable route-flap dampening\n"
11431 "Half-life time for the penalty\n"
11432 "Value to start reusing a route\n"
11433 "Value to start suppressing a route\n"
11434 "Maximum duration to suppress a stable route\n")
11436 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11437 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11440 /* Display specified route of BGP table. */
11441 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11442 const char *ip_str
, afi_t afi
, safi_t safi
,
11443 struct prefix_rd
*prd
, int prefix_check
)
11446 struct prefix match
;
11447 struct bgp_node
*rn
;
11448 struct bgp_node
*rm
;
11449 struct bgp_path_info
*pi
;
11450 struct bgp_path_info
*pi_temp
;
11452 struct bgp_table
*table
;
11454 /* BGP structure lookup. */
11456 bgp
= bgp_lookup_by_name(view_name
);
11458 vty_out(vty
, "%% Can't find BGP instance %s\n",
11460 return CMD_WARNING
;
11463 bgp
= bgp_get_default();
11465 vty_out(vty
, "%% No BGP process is configured\n");
11466 return CMD_WARNING
;
11470 /* Check IP address argument. */
11471 ret
= str2prefix(ip_str
, &match
);
11473 vty_out(vty
, "%% address is malformed\n");
11474 return CMD_WARNING
;
11477 match
.family
= afi2family(afi
);
11479 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11480 || (safi
== SAFI_EVPN
)) {
11481 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11482 rn
= bgp_route_next(rn
)) {
11483 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11485 table
= bgp_node_get_bgp_table_info(rn
);
11488 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11492 || rm
->p
.prefixlen
== match
.prefixlen
) {
11493 pi
= bgp_node_get_bgp_path_info(rm
);
11495 if (pi
->extra
&& pi
->extra
->damp_info
) {
11496 pi_temp
= pi
->next
;
11497 bgp_damp_info_free(
11498 pi
->extra
->damp_info
,
11506 bgp_unlock_node(rm
);
11509 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11512 || rn
->p
.prefixlen
== match
.prefixlen
) {
11513 pi
= bgp_node_get_bgp_path_info(rn
);
11515 if (pi
->extra
&& pi
->extra
->damp_info
) {
11516 pi_temp
= pi
->next
;
11517 bgp_damp_info_free(
11518 pi
->extra
->damp_info
,
11526 bgp_unlock_node(rn
);
11530 return CMD_SUCCESS
;
11533 DEFUN (clear_ip_bgp_dampening
,
11534 clear_ip_bgp_dampening_cmd
,
11535 "clear ip bgp dampening",
11539 "Clear route flap dampening information\n")
11541 bgp_damp_info_clean();
11542 return CMD_SUCCESS
;
11545 DEFUN (clear_ip_bgp_dampening_prefix
,
11546 clear_ip_bgp_dampening_prefix_cmd
,
11547 "clear ip bgp dampening A.B.C.D/M",
11551 "Clear route flap dampening information\n"
11554 int idx_ipv4_prefixlen
= 4;
11555 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11556 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11559 DEFUN (clear_ip_bgp_dampening_address
,
11560 clear_ip_bgp_dampening_address_cmd
,
11561 "clear ip bgp dampening A.B.C.D",
11565 "Clear route flap dampening information\n"
11566 "Network to clear damping information\n")
11569 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11570 SAFI_UNICAST
, NULL
, 0);
11573 DEFUN (clear_ip_bgp_dampening_address_mask
,
11574 clear_ip_bgp_dampening_address_mask_cmd
,
11575 "clear ip bgp dampening A.B.C.D A.B.C.D",
11579 "Clear route flap dampening information\n"
11580 "Network to clear damping information\n"
11584 int idx_ipv4_2
= 5;
11586 char prefix_str
[BUFSIZ
];
11588 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11591 vty_out(vty
, "%% Inconsistent address and mask\n");
11592 return CMD_WARNING
;
11595 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11599 static void show_bgp_peerhash_entry(struct hash_backet
*backet
, void *arg
)
11601 struct vty
*vty
= arg
;
11602 struct peer
*peer
= backet
->data
;
11603 char buf
[SU_ADDRSTRLEN
];
11605 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
11606 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
11609 DEFUN (show_bgp_peerhash
,
11610 show_bgp_peerhash_cmd
,
11611 "show bgp peerhash",
11614 "Display information about the BGP peerhash\n")
11616 struct list
*instances
= bm
->bgp
;
11617 struct listnode
*node
;
11620 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
11621 vty_out(vty
, "BGP: %s\n", bgp
->name
);
11622 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
11626 return CMD_SUCCESS
;
11629 /* also used for encap safi */
11630 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11631 afi_t afi
, safi_t safi
)
11633 struct bgp_node
*prn
;
11634 struct bgp_node
*rn
;
11635 struct bgp_table
*table
;
11637 struct prefix_rd
*prd
;
11638 struct bgp_static
*bgp_static
;
11639 mpls_label_t label
;
11640 char buf
[SU_ADDRSTRLEN
];
11641 char rdbuf
[RD_ADDRSTRLEN
];
11643 /* Network configuration. */
11644 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11645 prn
= bgp_route_next(prn
)) {
11646 table
= bgp_node_get_bgp_table_info(prn
);
11650 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11651 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11652 if (bgp_static
== NULL
)
11656 prd
= (struct prefix_rd
*)&prn
->p
;
11658 /* "network" configuration display. */
11659 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11660 label
= decode_label(&bgp_static
->label
);
11662 vty_out(vty
, " network %s/%d rd %s",
11663 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11665 p
->prefixlen
, rdbuf
);
11666 if (safi
== SAFI_MPLS_VPN
)
11667 vty_out(vty
, " label %u", label
);
11669 if (bgp_static
->rmap
.name
)
11670 vty_out(vty
, " route-map %s",
11671 bgp_static
->rmap
.name
);
11673 if (bgp_static
->backdoor
)
11674 vty_out(vty
, " backdoor");
11676 vty_out(vty
, "\n");
11681 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11682 afi_t afi
, safi_t safi
)
11684 struct bgp_node
*prn
;
11685 struct bgp_node
*rn
;
11686 struct bgp_table
*table
;
11688 struct prefix_rd
*prd
;
11689 struct bgp_static
*bgp_static
;
11690 char buf
[PREFIX_STRLEN
* 2];
11691 char buf2
[SU_ADDRSTRLEN
];
11692 char rdbuf
[RD_ADDRSTRLEN
];
11694 /* Network configuration. */
11695 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11696 prn
= bgp_route_next(prn
)) {
11697 table
= bgp_node_get_bgp_table_info(prn
);
11701 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11702 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11703 if (bgp_static
== NULL
)
11706 char *macrouter
= NULL
;
11709 if (bgp_static
->router_mac
)
11710 macrouter
= prefix_mac2str(
11711 bgp_static
->router_mac
, NULL
, 0);
11712 if (bgp_static
->eth_s_id
)
11713 esi
= esi2str(bgp_static
->eth_s_id
);
11715 prd
= (struct prefix_rd
*)&prn
->p
;
11717 /* "network" configuration display. */
11718 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11719 if (p
->u
.prefix_evpn
.route_type
== 5) {
11720 char local_buf
[PREFIX_STRLEN
];
11721 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11722 struct prefix_evpn
*)p
)
11726 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11727 local_buf
, PREFIX_STRLEN
);
11728 sprintf(buf
, "%s/%u", local_buf
,
11729 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11731 prefix2str(p
, buf
, sizeof(buf
));
11734 if (bgp_static
->gatewayIp
.family
== AF_INET
11735 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11736 inet_ntop(bgp_static
->gatewayIp
.family
,
11737 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11740 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11742 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11743 decode_label(&bgp_static
->label
), esi
, buf2
,
11747 XFREE(MTYPE_TMP
, macrouter
);
11749 XFREE(MTYPE_TMP
, esi
);
11754 /* Configuration of static route announcement and aggregate
11756 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11759 struct bgp_node
*rn
;
11761 struct bgp_static
*bgp_static
;
11762 struct bgp_aggregate
*bgp_aggregate
;
11763 char buf
[SU_ADDRSTRLEN
];
11765 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11766 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11770 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11771 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11775 /* Network configuration. */
11776 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11777 rn
= bgp_route_next(rn
)) {
11778 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11779 if (bgp_static
== NULL
)
11784 /* "network" configuration display. */
11785 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11786 uint32_t destination
;
11787 struct in_addr netmask
;
11789 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11790 masklen2ip(p
->prefixlen
, &netmask
);
11791 vty_out(vty
, " network %s",
11792 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11795 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11796 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11797 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11798 || p
->u
.prefix4
.s_addr
== 0) {
11799 /* Natural mask is not display. */
11801 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11803 vty_out(vty
, " network %s/%d",
11804 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11809 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11810 vty_out(vty
, " label-index %u",
11811 bgp_static
->label_index
);
11813 if (bgp_static
->rmap
.name
)
11814 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11816 if (bgp_static
->backdoor
)
11817 vty_out(vty
, " backdoor");
11819 vty_out(vty
, "\n");
11822 /* Aggregate-address configuration. */
11823 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11824 rn
= bgp_route_next(rn
)) {
11825 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
11826 if (bgp_aggregate
== NULL
)
11831 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11832 struct in_addr netmask
;
11834 masklen2ip(p
->prefixlen
, &netmask
);
11835 vty_out(vty
, " aggregate-address %s %s",
11836 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11838 inet_ntoa(netmask
));
11840 vty_out(vty
, " aggregate-address %s/%d",
11841 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11846 if (bgp_aggregate
->as_set
)
11847 vty_out(vty
, " as-set");
11849 if (bgp_aggregate
->summary_only
)
11850 vty_out(vty
, " summary-only");
11852 vty_out(vty
, "\n");
11856 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11859 struct bgp_node
*rn
;
11860 struct bgp_distance
*bdistance
;
11862 /* Distance configuration. */
11863 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11864 && bgp
->distance_local
[afi
][safi
]
11865 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11866 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11867 || bgp
->distance_local
[afi
][safi
]
11868 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11869 vty_out(vty
, " distance bgp %d %d %d\n",
11870 bgp
->distance_ebgp
[afi
][safi
],
11871 bgp
->distance_ibgp
[afi
][safi
],
11872 bgp
->distance_local
[afi
][safi
]);
11875 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11876 rn
= bgp_route_next(rn
)) {
11877 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11878 if (bdistance
!= NULL
) {
11879 char buf
[PREFIX_STRLEN
];
11881 vty_out(vty
, " distance %d %s %s\n",
11882 bdistance
->distance
,
11883 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11884 bdistance
->access_list
? bdistance
->access_list
11890 /* Allocate routing table structure and install commands. */
11891 void bgp_route_init(void)
11896 /* Init BGP distance table. */
11897 FOREACH_AFI_SAFI (afi
, safi
)
11898 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11900 /* IPv4 BGP commands. */
11901 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11902 install_element(BGP_NODE
, &bgp_network_cmd
);
11903 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11905 install_element(BGP_NODE
, &aggregate_address_cmd
);
11906 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11907 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11908 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11910 /* IPv4 unicast configuration. */
11911 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11912 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11913 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11915 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11916 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11917 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11918 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11920 /* IPv4 multicast configuration. */
11921 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11922 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11923 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11924 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11925 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11926 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11927 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11929 /* IPv4 labeled-unicast configuration. */
11930 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11931 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11932 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11933 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11934 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11936 install_element(VIEW_NODE
,
11937 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11938 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11939 install_element(VIEW_NODE
,
11940 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11941 #ifdef KEEP_OLD_VPN_COMMANDS
11942 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11943 #endif /* KEEP_OLD_VPN_COMMANDS */
11944 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11945 install_element(VIEW_NODE
,
11946 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11948 /* BGP dampening clear commands */
11949 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11950 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11952 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11953 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11956 install_element(ENABLE_NODE
,
11957 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11958 #ifdef KEEP_OLD_VPN_COMMANDS
11959 install_element(ENABLE_NODE
,
11960 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11961 #endif /* KEEP_OLD_VPN_COMMANDS */
11963 /* New config IPv6 BGP commands. */
11964 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11965 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11966 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11968 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11969 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11971 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11973 install_element(BGP_NODE
, &bgp_distance_cmd
);
11974 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11975 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11976 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11977 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11978 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11979 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11980 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11981 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11982 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11983 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11984 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11985 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11986 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11987 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11988 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11989 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11990 install_element(BGP_IPV4M_NODE
,
11991 &no_bgp_distance_source_access_list_cmd
);
11992 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11993 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11994 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11995 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11996 install_element(BGP_IPV6_NODE
,
11997 &ipv6_bgp_distance_source_access_list_cmd
);
11998 install_element(BGP_IPV6_NODE
,
11999 &no_ipv6_bgp_distance_source_access_list_cmd
);
12000 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12001 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12002 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12003 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12004 install_element(BGP_IPV6M_NODE
,
12005 &ipv6_bgp_distance_source_access_list_cmd
);
12006 install_element(BGP_IPV6M_NODE
,
12007 &no_ipv6_bgp_distance_source_access_list_cmd
);
12009 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12010 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12011 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12012 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12014 /* IPv4 Multicast Mode */
12015 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12016 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12018 /* Large Communities */
12019 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12020 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12022 /* show bgp ipv4 flowspec detailed */
12023 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12025 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12028 void bgp_route_finish(void)
12033 FOREACH_AFI_SAFI (afi
, safi
) {
12034 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12035 bgp_distance_table
[afi
][safi
] = NULL
;