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"
69 #include "bgpd/bgp_mac.h"
72 #include "bgpd/rfapi/rfapi_backend.h"
73 #include "bgpd/rfapi/vnc_import_bgp.h"
74 #include "bgpd/rfapi/vnc_export_bgp.h"
76 #include "bgpd/bgp_encap_types.h"
77 #include "bgpd/bgp_encap_tlv.h"
78 #include "bgpd/bgp_evpn.h"
79 #include "bgpd/bgp_evpn_vty.h"
80 #include "bgpd/bgp_flowspec.h"
81 #include "bgpd/bgp_flowspec_util.h"
82 #include "bgpd/bgp_pbr.h"
84 #ifndef VTYSH_EXTRACT_PL
85 #include "bgpd/bgp_route_clippy.c"
88 /* Extern from bgp_dump.c */
89 extern const char *bgp_origin_str
[];
90 extern const char *bgp_origin_long_str
[];
93 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
94 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
95 static const struct message bgp_pmsi_tnltype_str
[] = {
96 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
97 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
98 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
99 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
100 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
101 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
102 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
103 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
107 #define VRFID_NONE_STR "-"
109 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
110 safi_t safi
, struct prefix
*p
,
111 struct prefix_rd
*prd
)
114 struct bgp_node
*prn
= NULL
;
120 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
121 || (safi
== SAFI_EVPN
)) {
122 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
124 if (!bgp_node_has_bgp_path_info_data(prn
))
125 bgp_node_set_bgp_table_info(
126 prn
, bgp_table_init(table
->bgp
, afi
, safi
));
128 bgp_unlock_node(prn
);
129 table
= bgp_node_get_bgp_table_info(prn
);
132 rn
= bgp_node_get(table
, p
);
134 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
135 || (safi
== SAFI_EVPN
))
141 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
142 safi_t safi
, struct prefix
*p
,
143 struct prefix_rd
*prd
)
146 struct bgp_node
*prn
= NULL
;
151 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
152 || (safi
== SAFI_EVPN
)) {
153 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
157 if (!bgp_node_has_bgp_path_info_data(prn
)) {
158 bgp_unlock_node(prn
);
162 table
= bgp_node_get_bgp_table_info(prn
);
165 rn
= bgp_node_lookup(table
, p
);
170 /* Allocate bgp_path_info_extra */
171 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
173 struct bgp_path_info_extra
*new;
174 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
175 sizeof(struct bgp_path_info_extra
));
176 new->label
[0] = MPLS_INVALID_LABEL
;
178 new->bgp_fs_pbr
= list_new();
179 new->bgp_fs_iprule
= list_new();
183 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
185 struct bgp_path_info_extra
*e
;
187 if (!extra
|| !*extra
)
192 bgp_damp_info_free(e
->damp_info
, 0);
196 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
199 /* FIXME: since multiple e may have the same e->parent
200 * and e->parent->net is holding a refcount for each
201 * of them, we need to do some fudging here.
203 * WARNING: if bpi->net->lock drops to 0, bpi may be
204 * freed as well (because bpi->net was holding the
205 * last reference to bpi) => write after free!
209 bpi
= bgp_path_info_lock(bpi
);
210 refcount
= bpi
->net
->lock
- 1;
211 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
214 bgp_path_info_unlock(bpi
);
216 bgp_path_info_unlock(e
->parent
);
221 bgp_unlock(e
->bgp_orig
);
223 if ((*extra
)->bgp_fs_iprule
)
224 list_delete(&((*extra
)->bgp_fs_iprule
));
225 if ((*extra
)->bgp_fs_pbr
)
226 list_delete(&((*extra
)->bgp_fs_pbr
));
227 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
232 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
233 * allocated if required.
235 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
238 pi
->extra
= bgp_path_info_extra_new();
242 /* Allocate new bgp info structure. */
243 struct bgp_path_info
*bgp_path_info_new(void)
245 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
248 /* Free bgp route information. */
249 static void bgp_path_info_free(struct bgp_path_info
*path
)
252 bgp_attr_unintern(&path
->attr
);
254 bgp_unlink_nexthop(path
);
255 bgp_path_info_extra_free(&path
->extra
);
256 bgp_path_info_mpath_free(&path
->mpath
);
258 bgp_addpath_free_info_data(&path
->tx_addpath
,
259 &path
->net
->tx_addpath
);
261 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
263 XFREE(MTYPE_BGP_ROUTE
, path
);
266 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
272 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
274 assert(path
&& path
->lock
> 0);
277 if (path
->lock
== 0) {
279 zlog_debug ("%s: unlocked and freeing", __func__
);
280 zlog_backtrace (LOG_DEBUG
);
282 bgp_path_info_free(path
);
289 zlog_debug ("%s: unlocked to 1", __func__
);
290 zlog_backtrace (LOG_DEBUG
);
297 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
299 struct bgp_path_info
*top
;
301 top
= bgp_node_get_bgp_path_info(rn
);
307 bgp_node_set_bgp_path_info(rn
, pi
);
309 bgp_path_info_lock(pi
);
311 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
314 /* Do the actual removal of info from RIB, for use by bgp_process
315 completion callback *only* */
316 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
319 pi
->next
->prev
= pi
->prev
;
321 pi
->prev
->next
= pi
->next
;
323 bgp_node_set_bgp_path_info(rn
, pi
->next
);
325 bgp_path_info_mpath_dequeue(pi
);
326 bgp_path_info_unlock(pi
);
330 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
332 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
333 /* set of previous already took care of pcount */
334 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
337 /* undo the effects of a previous call to bgp_path_info_delete; typically
338 called when a route is deleted and then quickly re-added before the
339 deletion has been processed */
340 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
342 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
343 /* unset of previous already took care of pcount */
344 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
347 /* Adjust pcount as required */
348 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
350 struct bgp_table
*table
;
352 assert(rn
&& bgp_node_table(rn
));
353 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
355 table
= bgp_node_table(rn
);
357 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
360 if (!BGP_PATH_COUNTABLE(pi
)
361 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
363 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
365 /* slight hack, but more robust against errors. */
366 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
367 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
369 flog_err(EC_LIB_DEVELOPMENT
,
370 "Asked to decrement 0 prefix count for peer");
371 } else if (BGP_PATH_COUNTABLE(pi
)
372 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
373 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
374 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
378 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
379 struct bgp_path_info
*pi2
)
381 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
384 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
385 * This is here primarily to keep prefix-count in check.
387 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
390 SET_FLAG(pi
->flags
, flag
);
392 /* early bath if we know it's not a flag that changes countability state
394 if (!CHECK_FLAG(flag
,
395 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
398 bgp_pcount_adjust(rn
, pi
);
401 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
404 UNSET_FLAG(pi
->flags
, flag
);
406 /* early bath if we know it's not a flag that changes countability state
408 if (!CHECK_FLAG(flag
,
409 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
412 bgp_pcount_adjust(rn
, pi
);
415 /* Get MED value. If MED value is missing and "bgp bestpath
416 missing-as-worst" is specified, treat it as the worst value. */
417 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
419 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
422 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
429 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
431 if (pi
->addpath_rx_id
)
432 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
435 sprintf(buf
, "path %s", pi
->peer
->host
);
438 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
440 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
441 struct bgp_path_info
*exist
, int *paths_eq
,
442 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
443 char *pfx_buf
, afi_t afi
, safi_t safi
)
445 struct attr
*newattr
, *existattr
;
446 bgp_peer_sort_t new_sort
;
447 bgp_peer_sort_t exist_sort
;
453 uint32_t exist_weight
;
454 uint32_t newm
, existm
;
455 struct in_addr new_id
;
456 struct in_addr exist_id
;
459 int internal_as_route
;
462 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
463 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
465 uint32_t exist_mm_seq
;
473 zlog_debug("%s: new is NULL", pfx_buf
);
478 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
482 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
488 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
489 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
490 pfx_buf
, new_buf
, new->flags
, exist_buf
,
495 existattr
= exist
->attr
;
497 /* For EVPN routes, we cannot just go by local vs remote, we have to
498 * look at the MAC mobility sequence number, if present.
500 if (safi
== SAFI_EVPN
) {
501 /* This is an error condition described in RFC 7432 Section
503 * states that in this scenario "the PE MUST alert the operator"
505 * does not state what other action to take. In order to provide
507 * consistency in this scenario we are going to prefer the path
511 if (newattr
->sticky
!= existattr
->sticky
) {
513 prefix2str(&new->net
->p
, pfx_buf
,
515 * PREFIX2STR_BUFFER
);
516 bgp_path_info_path_with_addpath_rx_str(new,
518 bgp_path_info_path_with_addpath_rx_str(
522 if (newattr
->sticky
&& !existattr
->sticky
) {
525 "%s: %s wins over %s due to sticky MAC flag",
526 pfx_buf
, new_buf
, exist_buf
);
530 if (!newattr
->sticky
&& existattr
->sticky
) {
533 "%s: %s loses to %s due to sticky MAC flag",
534 pfx_buf
, new_buf
, exist_buf
);
539 new_mm_seq
= mac_mobility_seqnum(newattr
);
540 exist_mm_seq
= mac_mobility_seqnum(existattr
);
542 if (new_mm_seq
> exist_mm_seq
) {
545 "%s: %s wins over %s due to MM seq %u > %u",
546 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
551 if (new_mm_seq
< exist_mm_seq
) {
554 "%s: %s loses to %s due to MM seq %u < %u",
555 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
561 * if sequence numbers are the same path with the lowest IP
564 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
568 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
569 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
570 inet_ntoa(new->attr
->nexthop
));
576 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
577 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
578 inet_ntoa(new->attr
->nexthop
));
583 /* 1. Weight check. */
584 new_weight
= newattr
->weight
;
585 exist_weight
= existattr
->weight
;
587 if (new_weight
> exist_weight
) {
589 zlog_debug("%s: %s wins over %s due to weight %d > %d",
590 pfx_buf
, new_buf
, exist_buf
, new_weight
,
595 if (new_weight
< exist_weight
) {
597 zlog_debug("%s: %s loses to %s due to weight %d < %d",
598 pfx_buf
, new_buf
, exist_buf
, new_weight
,
603 /* 2. Local preference check. */
604 new_pref
= exist_pref
= bgp
->default_local_pref
;
606 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
607 new_pref
= newattr
->local_pref
;
608 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
609 exist_pref
= existattr
->local_pref
;
611 if (new_pref
> exist_pref
) {
614 "%s: %s wins over %s due to localpref %d > %d",
615 pfx_buf
, new_buf
, exist_buf
, new_pref
,
620 if (new_pref
< exist_pref
) {
623 "%s: %s loses to %s due to localpref %d < %d",
624 pfx_buf
, new_buf
, exist_buf
, new_pref
,
629 /* 3. Local route check. We prefer:
631 * - BGP_ROUTE_AGGREGATE
632 * - BGP_ROUTE_REDISTRIBUTE
634 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
635 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
638 "%s: %s wins over %s due to preferred BGP_ROUTE type",
639 pfx_buf
, new_buf
, exist_buf
);
643 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
644 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
647 "%s: %s loses to %s due to preferred BGP_ROUTE type",
648 pfx_buf
, new_buf
, exist_buf
);
652 /* 4. AS path length check. */
653 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
654 int exist_hops
= aspath_count_hops(existattr
->aspath
);
655 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
657 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
660 aspath_hops
= aspath_count_hops(newattr
->aspath
);
661 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
663 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
666 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
667 pfx_buf
, new_buf
, exist_buf
,
669 (exist_hops
+ exist_confeds
));
673 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
676 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
677 pfx_buf
, new_buf
, exist_buf
,
679 (exist_hops
+ exist_confeds
));
683 int newhops
= aspath_count_hops(newattr
->aspath
);
685 if (newhops
< exist_hops
) {
688 "%s: %s wins over %s due to aspath hopcount %d < %d",
689 pfx_buf
, new_buf
, exist_buf
,
690 newhops
, exist_hops
);
694 if (newhops
> exist_hops
) {
697 "%s: %s loses to %s due to aspath hopcount %d > %d",
698 pfx_buf
, new_buf
, exist_buf
,
699 newhops
, exist_hops
);
705 /* 5. Origin check. */
706 if (newattr
->origin
< existattr
->origin
) {
708 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
709 pfx_buf
, new_buf
, exist_buf
,
710 bgp_origin_long_str
[newattr
->origin
],
711 bgp_origin_long_str
[existattr
->origin
]);
715 if (newattr
->origin
> existattr
->origin
) {
717 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
718 pfx_buf
, new_buf
, exist_buf
,
719 bgp_origin_long_str
[newattr
->origin
],
720 bgp_origin_long_str
[existattr
->origin
]);
725 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
726 && aspath_count_hops(existattr
->aspath
) == 0);
727 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
728 && aspath_count_confeds(existattr
->aspath
) > 0
729 && aspath_count_hops(newattr
->aspath
) == 0
730 && aspath_count_hops(existattr
->aspath
) == 0);
732 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
733 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
734 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
735 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
736 || internal_as_route
) {
737 new_med
= bgp_med_value(new->attr
, bgp
);
738 exist_med
= bgp_med_value(exist
->attr
, bgp
);
740 if (new_med
< exist_med
) {
743 "%s: %s wins over %s due to MED %d < %d",
744 pfx_buf
, new_buf
, exist_buf
, new_med
,
749 if (new_med
> exist_med
) {
752 "%s: %s loses to %s due to MED %d > %d",
753 pfx_buf
, new_buf
, exist_buf
, new_med
,
759 /* 7. Peer type check. */
760 new_sort
= new->peer
->sort
;
761 exist_sort
= exist
->peer
->sort
;
763 if (new_sort
== BGP_PEER_EBGP
764 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
767 "%s: %s wins over %s due to eBGP peer > iBGP peer",
768 pfx_buf
, new_buf
, exist_buf
);
772 if (exist_sort
== BGP_PEER_EBGP
773 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
776 "%s: %s loses to %s due to iBGP peer < eBGP peer",
777 pfx_buf
, new_buf
, exist_buf
);
781 /* 8. IGP metric check. */
785 newm
= new->extra
->igpmetric
;
787 existm
= exist
->extra
->igpmetric
;
792 "%s: %s wins over %s due to IGP metric %d < %d",
793 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
800 "%s: %s loses to %s due to IGP metric %d > %d",
801 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
805 /* 9. Same IGP metric. Compare the cluster list length as
806 representative of IGP hops metric. Rewrite the metric value
807 pair (newm, existm) with the cluster list length. Prefer the
808 path with smaller cluster list length. */
809 if (newm
== existm
) {
810 if (peer_sort(new->peer
) == BGP_PEER_IBGP
811 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
812 && (mpath_cfg
== NULL
814 mpath_cfg
->ibgp_flags
,
815 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
816 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
817 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
822 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
823 pfx_buf
, new_buf
, exist_buf
,
831 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
832 pfx_buf
, new_buf
, exist_buf
,
839 /* 10. confed-external vs. confed-internal */
840 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
841 if (new_sort
== BGP_PEER_CONFED
842 && exist_sort
== BGP_PEER_IBGP
) {
845 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
846 pfx_buf
, new_buf
, exist_buf
);
850 if (exist_sort
== BGP_PEER_CONFED
851 && new_sort
== BGP_PEER_IBGP
) {
854 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
855 pfx_buf
, new_buf
, exist_buf
);
860 /* 11. Maximum path check. */
861 if (newm
== existm
) {
862 /* If one path has a label but the other does not, do not treat
863 * them as equals for multipath
865 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
867 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
870 "%s: %s and %s cannot be multipath, one has a label while the other does not",
871 pfx_buf
, new_buf
, exist_buf
);
872 } else if (bgp_flag_check(bgp
,
873 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
876 * For the two paths, all comparison steps till IGP
878 * have succeeded - including AS_PATH hop count. Since
880 * bestpath as-path multipath-relax' knob is on, we
882 * an exact match of AS_PATH. Thus, mark the paths are
884 * That will trigger both these paths to get into the
892 "%s: %s and %s are equal via multipath-relax",
893 pfx_buf
, new_buf
, exist_buf
);
894 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
895 if (aspath_cmp(new->attr
->aspath
,
896 exist
->attr
->aspath
)) {
901 "%s: %s and %s are equal via matching aspaths",
902 pfx_buf
, new_buf
, exist_buf
);
904 } else if (new->peer
->as
== exist
->peer
->as
) {
909 "%s: %s and %s are equal via same remote-as",
910 pfx_buf
, new_buf
, exist_buf
);
914 * TODO: If unequal cost ibgp multipath is enabled we can
915 * mark the paths as equal here instead of returning
920 "%s: %s wins over %s after IGP metric comparison",
921 pfx_buf
, new_buf
, exist_buf
);
924 "%s: %s loses to %s after IGP metric comparison",
925 pfx_buf
, new_buf
, exist_buf
);
930 /* 12. If both paths are external, prefer the path that was received
931 first (the oldest one). This step minimizes route-flap, since a
932 newer path won't displace an older one, even if it was the
933 preferred route based on the additional decision criteria below. */
934 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
935 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
936 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
939 "%s: %s wins over %s due to oldest external",
940 pfx_buf
, new_buf
, exist_buf
);
944 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
947 "%s: %s loses to %s due to oldest external",
948 pfx_buf
, new_buf
, exist_buf
);
953 /* 13. Router-ID comparision. */
954 /* If one of the paths is "stale", the corresponding peer router-id will
955 * be 0 and would always win over the other path. If originator id is
956 * used for the comparision, it will decide which path is better.
958 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
959 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
961 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
962 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
963 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
965 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
967 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
970 "%s: %s wins over %s due to Router-ID comparison",
971 pfx_buf
, new_buf
, exist_buf
);
975 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
978 "%s: %s loses to %s due to Router-ID comparison",
979 pfx_buf
, new_buf
, exist_buf
);
983 /* 14. Cluster length comparision. */
984 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
985 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
987 if (new_cluster
< exist_cluster
) {
990 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
991 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
996 if (new_cluster
> exist_cluster
) {
999 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1000 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1005 /* 15. Neighbor address comparision. */
1006 /* Do this only if neither path is "stale" as stale paths do not have
1007 * valid peer information (as the connection may or may not be up).
1009 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1012 "%s: %s wins over %s due to latter path being STALE",
1013 pfx_buf
, new_buf
, exist_buf
);
1017 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1020 "%s: %s loses to %s due to former path being STALE",
1021 pfx_buf
, new_buf
, exist_buf
);
1025 /* locally configured routes to advertise do not have su_remote */
1026 if (new->peer
->su_remote
== NULL
)
1028 if (exist
->peer
->su_remote
== NULL
)
1031 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1036 "%s: %s loses to %s due to Neighor IP comparison",
1037 pfx_buf
, new_buf
, exist_buf
);
1044 "%s: %s wins over %s due to Neighor IP comparison",
1045 pfx_buf
, new_buf
, exist_buf
);
1050 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1051 pfx_buf
, new_buf
, exist_buf
);
1056 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1057 * is preferred, or 0 if they are the same (usually will only occur if
1058 * multipath is enabled
1059 * This version is compatible with */
1060 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1061 struct bgp_path_info
*exist
, char *pfx_buf
,
1062 afi_t afi
, safi_t safi
)
1066 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1080 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1081 struct attr
*attr
, afi_t afi
,
1084 struct bgp_filter
*filter
;
1086 filter
= &peer
->filter
[afi
][safi
];
1088 #define FILTER_EXIST_WARN(F, f, filter) \
1089 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1090 zlog_debug("%s: Could not find configured input %s-list %s!", \
1091 peer->host, #f, F##_IN_NAME(filter));
1093 if (DISTRIBUTE_IN_NAME(filter
)) {
1094 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1096 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1100 if (PREFIX_LIST_IN_NAME(filter
)) {
1101 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1103 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1107 if (FILTER_LIST_IN_NAME(filter
)) {
1108 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1110 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1115 return FILTER_PERMIT
;
1116 #undef FILTER_EXIST_WARN
1119 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1120 struct attr
*attr
, afi_t afi
,
1123 struct bgp_filter
*filter
;
1125 filter
= &peer
->filter
[afi
][safi
];
1127 #define FILTER_EXIST_WARN(F, f, filter) \
1128 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1129 zlog_debug("%s: Could not find configured output %s-list %s!", \
1130 peer->host, #f, F##_OUT_NAME(filter));
1132 if (DISTRIBUTE_OUT_NAME(filter
)) {
1133 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1135 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1139 if (PREFIX_LIST_OUT_NAME(filter
)) {
1140 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1142 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1147 if (FILTER_LIST_OUT_NAME(filter
)) {
1148 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1150 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1155 return FILTER_PERMIT
;
1156 #undef FILTER_EXIST_WARN
1159 /* If community attribute includes no_export then return 1. */
1160 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1162 if (attr
->community
) {
1163 /* NO_ADVERTISE check. */
1164 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1167 /* NO_EXPORT check. */
1168 if (peer
->sort
== BGP_PEER_EBGP
1169 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1172 /* NO_EXPORT_SUBCONFED check. */
1173 if (peer
->sort
== BGP_PEER_EBGP
1174 || peer
->sort
== BGP_PEER_CONFED
)
1175 if (community_include(attr
->community
,
1176 COMMUNITY_NO_EXPORT_SUBCONFED
))
1182 /* Route reflection loop check. */
1183 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1185 struct in_addr cluster_id
;
1187 if (attr
->cluster
) {
1188 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1189 cluster_id
= peer
->bgp
->cluster_id
;
1191 cluster_id
= peer
->bgp
->router_id
;
1193 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1199 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1200 struct attr
*attr
, afi_t afi
, safi_t safi
,
1201 const char *rmap_name
)
1203 struct bgp_filter
*filter
;
1204 struct bgp_path_info rmap_path
;
1205 route_map_result_t ret
;
1206 struct route_map
*rmap
= NULL
;
1208 filter
= &peer
->filter
[afi
][safi
];
1210 /* Apply default weight value. */
1211 if (peer
->weight
[afi
][safi
])
1212 attr
->weight
= peer
->weight
[afi
][safi
];
1215 rmap
= route_map_lookup_by_name(rmap_name
);
1220 if (ROUTE_MAP_IN_NAME(filter
)) {
1221 rmap
= ROUTE_MAP_IN(filter
);
1228 /* RFC 8212 to prevent route leaks.
1229 * This specification intends to improve this situation by requiring the
1230 * explicit configuration of both BGP Import and Export Policies for any
1231 * External BGP (EBGP) session such as customers, peers, or
1232 * confederation boundaries for all enabled address families. Through
1233 * codification of the aforementioned requirement, operators will
1234 * benefit from consistent behavior across different BGP
1237 if (peer
->bgp
->ebgp_requires_policy
1238 == DEFAULT_EBGP_POLICY_ENABLED
)
1239 if (!bgp_inbound_policy_exists(peer
, filter
))
1242 /* Route map apply. */
1244 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1245 /* Duplicate current value to new strucutre for modification. */
1246 rmap_path
.peer
= peer
;
1247 rmap_path
.attr
= attr
;
1249 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1251 /* Apply BGP route map to the attribute. */
1252 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1254 peer
->rmap_type
= 0;
1256 if (ret
== RMAP_DENYMATCH
)
1262 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1263 struct attr
*attr
, afi_t afi
, safi_t safi
,
1264 const char *rmap_name
)
1266 struct bgp_path_info rmap_path
;
1267 route_map_result_t ret
;
1268 struct route_map
*rmap
= NULL
;
1272 * So if we get to this point and have no rmap_name
1273 * we want to just show the output as it currently
1279 /* Apply default weight value. */
1280 if (peer
->weight
[afi
][safi
])
1281 attr
->weight
= peer
->weight
[afi
][safi
];
1283 rmap
= route_map_lookup_by_name(rmap_name
);
1286 * If we have a route map name and we do not find
1287 * the routemap that means we have an implicit
1293 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1294 /* Route map apply. */
1295 /* Duplicate current value to new strucutre for modification. */
1296 rmap_path
.peer
= peer
;
1297 rmap_path
.attr
= attr
;
1299 rmap_type
= peer
->rmap_type
;
1300 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1302 /* Apply BGP route map to the attribute. */
1303 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1305 peer
->rmap_type
= rmap_type
;
1307 if (ret
== RMAP_DENYMATCH
)
1309 * caller has multiple error paths with bgp_attr_flush()
1316 /* If this is an EBGP peer with remove-private-AS */
1317 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1318 struct peer
*peer
, struct attr
*attr
)
1320 if (peer
->sort
== BGP_PEER_EBGP
1321 && (peer_af_flag_check(peer
, afi
, safi
,
1322 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1323 || peer_af_flag_check(peer
, afi
, safi
,
1324 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1325 || peer_af_flag_check(peer
, afi
, safi
,
1326 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1327 || peer_af_flag_check(peer
, afi
, safi
,
1328 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1329 // Take action on the entire aspath
1330 if (peer_af_flag_check(peer
, afi
, safi
,
1331 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1332 || peer_af_flag_check(peer
, afi
, safi
,
1333 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1334 if (peer_af_flag_check(
1336 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1337 attr
->aspath
= aspath_replace_private_asns(
1338 attr
->aspath
, bgp
->as
);
1340 // The entire aspath consists of private ASNs so create
1342 else if (aspath_private_as_check(attr
->aspath
))
1343 attr
->aspath
= aspath_empty_get();
1345 // There are some public and some private ASNs, remove
1348 attr
->aspath
= aspath_remove_private_asns(
1352 // 'all' was not specified so the entire aspath must be private
1354 // for us to do anything
1355 else if (aspath_private_as_check(attr
->aspath
)) {
1356 if (peer_af_flag_check(
1358 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1359 attr
->aspath
= aspath_replace_private_asns(
1360 attr
->aspath
, bgp
->as
);
1362 attr
->aspath
= aspath_empty_get();
1367 /* If this is an EBGP peer with as-override */
1368 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1369 struct peer
*peer
, struct attr
*attr
)
1371 if (peer
->sort
== BGP_PEER_EBGP
1372 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1373 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1374 attr
->aspath
= aspath_replace_specific_asn(
1375 attr
->aspath
, peer
->as
, bgp
->as
);
1379 void bgp_attr_add_gshut_community(struct attr
*attr
)
1381 struct community
*old
;
1382 struct community
*new;
1383 struct community
*merge
;
1384 struct community
*gshut
;
1386 old
= attr
->community
;
1387 gshut
= community_str2com("graceful-shutdown");
1392 merge
= community_merge(community_dup(old
), gshut
);
1394 if (old
->refcnt
== 0)
1395 community_free(&old
);
1397 new = community_uniq_sort(merge
);
1398 community_free(&merge
);
1400 new = community_dup(gshut
);
1403 community_free(&gshut
);
1404 attr
->community
= new;
1405 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1407 /* When we add the graceful-shutdown community we must also
1408 * lower the local-preference */
1409 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1410 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1414 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1416 if (family
== AF_INET
) {
1417 attr
->nexthop
.s_addr
= 0;
1418 attr
->mp_nexthop_global_in
.s_addr
= 0;
1420 if (family
== AF_INET6
)
1421 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1422 if (family
== AF_EVPN
)
1423 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1426 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1427 struct update_subgroup
*subgrp
, struct prefix
*p
,
1430 struct bgp_filter
*filter
;
1433 struct peer
*onlypeer
;
1435 struct attr
*piattr
;
1436 char buf
[PREFIX_STRLEN
];
1442 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1444 if (DISABLE_BGP_ANNOUNCE
)
1447 afi
= SUBGRP_AFI(subgrp
);
1448 safi
= SUBGRP_SAFI(subgrp
);
1449 peer
= SUBGRP_PEER(subgrp
);
1451 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1452 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1455 filter
= &peer
->filter
[afi
][safi
];
1456 bgp
= SUBGRP_INST(subgrp
);
1457 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1461 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1462 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1463 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1466 * direct and direct_ext type routes originate internally even
1467 * though they can have peer pointers that reference other
1470 prefix2str(p
, buf
, PREFIX_STRLEN
);
1471 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1477 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1478 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1479 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1480 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1482 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1487 /* With addpath we may be asked to TX all kinds of paths so make sure
1489 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1490 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1491 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1495 /* If this is not the bestpath then check to see if there is an enabled
1497 * feature that requires us to advertise it */
1498 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1499 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1504 /* Aggregate-address suppress check. */
1505 if (pi
->extra
&& pi
->extra
->suppress
)
1506 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1511 * If we are doing VRF 2 VRF leaking via the import
1512 * statement, we want to prevent the route going
1513 * off box as that the RT and RD created are localy
1514 * significant and globaly useless.
1516 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1517 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1520 /* If it's labeled safi, make sure the route has a valid label. */
1521 if (safi
== SAFI_LABELED_UNICAST
) {
1522 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1523 if (!bgp_is_valid_label(&label
)) {
1524 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1525 zlog_debug("u%" PRIu64
":s%" PRIu64
1526 " %s/%d is filtered - no label (%p)",
1527 subgrp
->update_group
->id
, subgrp
->id
,
1528 inet_ntop(p
->family
, &p
->u
.prefix
,
1529 buf
, SU_ADDRSTRLEN
),
1530 p
->prefixlen
, &label
);
1535 /* Do not send back route to sender. */
1536 if (onlypeer
&& from
== onlypeer
) {
1540 /* Do not send the default route in the BGP table if the neighbor is
1541 * configured for default-originate */
1542 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1543 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1544 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1546 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1550 /* Transparency check. */
1551 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1552 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1557 /* If community is not disabled check the no-export and local. */
1558 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1559 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1561 "subgrpannouncecheck: community filter check fail");
1565 /* If the attribute has originator-id and it is same as remote
1567 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1568 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1569 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1571 "%s [Update:SEND] %s originator-id is same as "
1574 prefix2str(p
, buf
, sizeof(buf
)));
1578 /* ORF prefix-list filter check */
1579 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1580 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1581 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1582 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1583 if (peer
->orf_plist
[afi
][safi
]) {
1584 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1586 if (bgp_debug_update(NULL
, p
,
1587 subgrp
->update_group
, 0))
1589 "%s [Update:SEND] %s is filtered via ORF",
1597 /* Output filter check. */
1598 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1599 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1600 zlog_debug("%s [Update:SEND] %s is filtered",
1601 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1605 #ifdef BGP_SEND_ASPATH_CHECK
1606 /* AS path loop check. */
1607 if (onlypeer
&& aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1608 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1610 "%s [Update:SEND] suppress announcement to peer AS %u "
1611 "that is part of AS path.",
1612 onlypeer
->host
, onlypeer
->as
);
1615 #endif /* BGP_SEND_ASPATH_CHECK */
1617 /* If we're a CONFED we need to loop check the CONFED ID too */
1618 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1619 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1620 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1622 "%s [Update:SEND] suppress announcement to peer AS %u"
1624 peer
->host
, bgp
->confed_id
);
1629 /* Route-Reflect check. */
1630 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1635 /* IBGP reflection check. */
1636 if (reflect
&& !samepeer_safe
) {
1637 /* A route from a Client peer. */
1638 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1639 PEER_FLAG_REFLECTOR_CLIENT
)) {
1640 /* Reflect to all the Non-Client peers and also to the
1641 Client peers other than the originator. Originator
1643 is already done. So there is noting to do. */
1644 /* no bgp client-to-client reflection check. */
1645 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1646 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1647 PEER_FLAG_REFLECTOR_CLIENT
))
1650 /* A route from a Non-client peer. Reflect to all other
1652 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1653 PEER_FLAG_REFLECTOR_CLIENT
))
1658 /* For modify attribute, copy it to temporary structure. */
1659 bgp_attr_dup(attr
, piattr
);
1661 /* If local-preference is not set. */
1662 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1663 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1664 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1665 attr
->local_pref
= bgp
->default_local_pref
;
1668 /* If originator-id is not set and the route is to be reflected,
1669 set the originator id */
1671 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1672 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1673 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1676 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1678 if (peer
->sort
== BGP_PEER_EBGP
1679 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1680 if (from
!= bgp
->peer_self
&& !transparent
1681 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1682 PEER_FLAG_MED_UNCHANGED
))
1684 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1687 /* Since the nexthop attribute can vary per peer, it is not explicitly
1689 * in announce check, only certain flags and length (or number of
1691 * -- for IPv6/MP_REACH) are set here in order to guide the update
1693 * code in setting the nexthop(s) on a per peer basis in
1695 * Typically, the source nexthop in the attribute is preserved but in
1697 * scenarios where we know it will always be overwritten, we reset the
1698 * nexthop to "0" in an attempt to achieve better Update packing. An
1699 * example of this is when a prefix from each of 2 IBGP peers needs to
1701 * announced to an EBGP peer (and they have the same attributes barring
1705 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1707 #define NEXTHOP_IS_V6 \
1708 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1709 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1710 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1711 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1713 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1715 * the peer (group) is configured to receive link-local nexthop
1717 * and it is available in the prefix OR we're not reflecting the route
1719 * the peer (group) to whom we're going to announce is on a shared
1721 * and this is either a self-originated route or the peer is EBGP.
1723 if (NEXTHOP_IS_V6
) {
1724 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1725 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1726 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1727 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1728 || (!reflect
&& peer
->shared_network
1729 && (from
== bgp
->peer_self
1730 || peer
->sort
== BGP_PEER_EBGP
))) {
1731 attr
->mp_nexthop_len
=
1732 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1735 /* Clear off link-local nexthop in source, whenever it is not
1737 * ensure more prefixes share the same attribute for
1740 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1741 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1742 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1745 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1746 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1748 /* Route map & unsuppress-map apply. */
1749 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1750 struct bgp_path_info rmap_path
;
1751 struct bgp_path_info_extra dummy_rmap_path_extra
;
1752 struct attr dummy_attr
;
1754 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1755 rmap_path
.peer
= peer
;
1756 rmap_path
.attr
= attr
;
1759 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1760 sizeof(struct bgp_path_info_extra
));
1761 rmap_path
.extra
= &dummy_rmap_path_extra
;
1764 /* don't confuse inbound and outbound setting */
1765 RESET_FLAG(attr
->rmap_change_flags
);
1768 * The route reflector is not allowed to modify the attributes
1769 * of the reflected IBGP routes unless explicitly allowed.
1771 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1772 && !bgp_flag_check(bgp
,
1773 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1774 bgp_attr_dup(&dummy_attr
, attr
);
1775 rmap_path
.attr
= &dummy_attr
;
1778 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1780 if (pi
->extra
&& pi
->extra
->suppress
)
1781 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1782 RMAP_BGP
, &rmap_path
);
1784 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1785 RMAP_BGP
, &rmap_path
);
1787 peer
->rmap_type
= 0;
1789 if (ret
== RMAP_DENYMATCH
) {
1790 bgp_attr_flush(attr
);
1795 /* RFC 8212 to prevent route leaks.
1796 * This specification intends to improve this situation by requiring the
1797 * explicit configuration of both BGP Import and Export Policies for any
1798 * External BGP (EBGP) session such as customers, peers, or
1799 * confederation boundaries for all enabled address families. Through
1800 * codification of the aforementioned requirement, operators will
1801 * benefit from consistent behavior across different BGP
1804 if (peer
->bgp
->ebgp_requires_policy
1805 == DEFAULT_EBGP_POLICY_ENABLED
)
1806 if (!bgp_outbound_policy_exists(peer
, filter
))
1809 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1810 if (peer
->sort
== BGP_PEER_IBGP
1811 || peer
->sort
== BGP_PEER_CONFED
) {
1812 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1813 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1815 bgp_attr_add_gshut_community(attr
);
1819 /* After route-map has been applied, we check to see if the nexthop to
1820 * be carried in the attribute (that is used for the announcement) can
1821 * be cleared off or not. We do this in all cases where we would be
1822 * setting the nexthop to "ourselves". For IPv6, we only need to
1824 * the global nexthop here; the link-local nexthop would have been
1826 * already, and if not, it is required by the update formation code.
1827 * Also see earlier comments in this function.
1830 * If route-map has performed some operation on the nexthop or the peer
1831 * configuration says to pass it unchanged, we cannot reset the nexthop
1832 * here, so only attempt to do it if these aren't true. Note that the
1833 * route-map handler itself might have cleared the nexthop, if for
1835 * it is configured as 'peer-address'.
1837 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1838 piattr
->rmap_change_flags
)
1840 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1841 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1842 /* We can reset the nexthop, if setting (or forcing) it to
1844 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1845 PEER_FLAG_NEXTHOP_SELF
)
1846 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1847 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1849 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1850 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1851 subgroup_announce_reset_nhop(
1852 (peer_cap_enhe(peer
, afi
, safi
)
1856 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1857 /* Can also reset the nexthop if announcing to EBGP, but
1859 * no peer in the subgroup is on a shared subnet.
1860 * Note: 3rd party nexthop currently implemented for
1863 if (!bgp_subgrp_multiaccess_check_v4(piattr
->nexthop
,
1865 subgroup_announce_reset_nhop(
1866 (peer_cap_enhe(peer
, afi
, safi
)
1870 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1872 * This flag is used for leaked vpn-vrf routes
1874 int family
= p
->family
;
1876 if (peer_cap_enhe(peer
, afi
, safi
))
1879 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1881 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1882 __func__
, family2str(family
));
1883 subgroup_announce_reset_nhop(family
, attr
);
1886 /* If IPv6/MP and nexthop does not have any override and happens
1888 * be a link-local address, reset it so that we don't pass along
1890 * source's link-local IPv6 address to recipients who may not be
1892 * the same interface.
1894 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1895 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1896 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1903 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1904 struct bgp_maxpaths_cfg
*mpath_cfg
,
1905 struct bgp_path_info_pair
*result
, afi_t afi
,
1908 struct bgp_path_info
*new_select
;
1909 struct bgp_path_info
*old_select
;
1910 struct bgp_path_info
*pi
;
1911 struct bgp_path_info
*pi1
;
1912 struct bgp_path_info
*pi2
;
1913 struct bgp_path_info
*nextpi
= NULL
;
1914 int paths_eq
, do_mpath
, debug
;
1915 struct list mp_list
;
1916 char pfx_buf
[PREFIX2STR_BUFFER
];
1917 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1919 bgp_mp_list_init(&mp_list
);
1921 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1923 debug
= bgp_debug_bestpath(&rn
->p
);
1926 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1928 /* bgp deterministic-med */
1930 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1932 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1933 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1935 bgp_path_info_unset_flag(rn
, pi1
,
1936 BGP_PATH_DMED_SELECTED
);
1938 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1940 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1942 if (BGP_PATH_HOLDDOWN(pi1
))
1944 if (pi1
->peer
&& pi1
->peer
!= bgp
->peer_self
)
1945 if (pi1
->peer
->status
!= Established
)
1950 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
1951 if (CHECK_FLAG(pi2
->flags
,
1952 BGP_PATH_DMED_CHECK
))
1954 if (BGP_PATH_HOLDDOWN(pi2
))
1957 && pi2
->peer
!= bgp
->peer_self
1960 PEER_STATUS_NSF_WAIT
))
1961 if (pi2
->peer
->status
1965 if (!aspath_cmp_left(pi1
->attr
->aspath
,
1967 && !aspath_cmp_left_confed(
1972 if (bgp_path_info_cmp(
1973 bgp
, pi2
, new_select
,
1974 &paths_eq
, mpath_cfg
, debug
,
1975 pfx_buf
, afi
, safi
)) {
1976 bgp_path_info_unset_flag(
1978 BGP_PATH_DMED_SELECTED
);
1982 bgp_path_info_set_flag(
1983 rn
, pi2
, BGP_PATH_DMED_CHECK
);
1986 bgp_path_info_set_flag(rn
, new_select
,
1987 BGP_PATH_DMED_CHECK
);
1988 bgp_path_info_set_flag(rn
, new_select
,
1989 BGP_PATH_DMED_SELECTED
);
1992 bgp_path_info_path_with_addpath_rx_str(
1993 new_select
, path_buf
);
1994 zlog_debug("%s: %s is the bestpath from AS %u",
1996 aspath_get_first_as(
1997 new_select
->attr
->aspath
));
2002 /* Check old selected route and new selected route. */
2005 for (pi
= bgp_node_get_bgp_path_info(rn
);
2006 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2007 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2010 if (BGP_PATH_HOLDDOWN(pi
)) {
2011 /* reap REMOVED routes, if needs be
2012 * selected route must stay for a while longer though
2014 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2015 && (pi
!= old_select
))
2016 bgp_path_info_reap(rn
, pi
);
2019 zlog_debug("%s: pi %p in holddown", __func__
,
2025 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2026 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2027 if (pi
->peer
->status
!= Established
) {
2031 "%s: pi %p non self peer %s not estab state",
2032 __func__
, pi
, pi
->peer
->host
);
2037 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2038 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2039 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2041 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2045 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2047 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2048 debug
, pfx_buf
, afi
, safi
)) {
2053 /* Now that we know which path is the bestpath see if any of the other
2055 * qualify as multipaths
2059 bgp_path_info_path_with_addpath_rx_str(new_select
,
2062 sprintf(path_buf
, "NONE");
2064 "%s: After path selection, newbest is %s oldbest was %s",
2066 old_select
? old_select
->peer
->host
: "NONE");
2069 if (do_mpath
&& new_select
) {
2070 for (pi
= bgp_node_get_bgp_path_info(rn
);
2071 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2074 bgp_path_info_path_with_addpath_rx_str(
2077 if (pi
== new_select
) {
2080 "%s: %s is the bestpath, add to the multipath list",
2082 bgp_mp_list_add(&mp_list
, pi
);
2086 if (BGP_PATH_HOLDDOWN(pi
))
2089 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2090 && !CHECK_FLAG(pi
->peer
->sflags
,
2091 PEER_STATUS_NSF_WAIT
))
2092 if (pi
->peer
->status
!= Established
)
2095 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2098 "%s: %s has the same nexthop as the bestpath, skip it",
2103 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2104 mpath_cfg
, debug
, pfx_buf
, afi
, safi
);
2109 "%s: %s is equivalent to the bestpath, add to the multipath list",
2111 bgp_mp_list_add(&mp_list
, pi
);
2116 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2118 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2119 bgp_mp_list_clear(&mp_list
);
2121 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2123 result
->old
= old_select
;
2124 result
->new = new_select
;
2130 * A new route/change in bestpath of an existing route. Evaluate the path
2131 * for advertisement to the subgroup.
2133 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2134 struct bgp_path_info
*selected
,
2135 struct bgp_node
*rn
,
2136 uint32_t addpath_tx_id
)
2139 struct peer
*onlypeer
;
2145 afi
= SUBGRP_AFI(subgrp
);
2146 safi
= SUBGRP_SAFI(subgrp
);
2147 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2150 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2151 char buf_prefix
[PREFIX_STRLEN
];
2152 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2153 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2157 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2158 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2159 PEER_STATUS_ORF_WAIT_REFRESH
))
2162 memset(&attr
, 0, sizeof(struct attr
));
2163 /* It's initialized in bgp_announce_check() */
2165 /* Announcement to the subgroup. If the route is filtered withdraw it.
2168 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2169 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2171 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2175 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2177 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2184 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2185 * This is called at the end of route processing.
2187 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2189 struct bgp_path_info
*pi
;
2191 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2192 if (BGP_PATH_HOLDDOWN(pi
))
2194 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2195 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2200 * Has the route changed from the RIB's perspective? This is invoked only
2201 * if the route selection returns the same best route as earlier - to
2202 * determine if we need to update zebra or not.
2204 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2205 struct bgp_path_info
*selected
)
2207 struct bgp_path_info
*mpinfo
;
2209 /* If this is multipath, check all selected paths for any nexthop
2210 * change or attribute change. Some attribute changes (e.g., community)
2211 * aren't of relevance to the RIB, but we'll update zebra to ensure
2212 * we handle the case of BGP nexthop change. This is the behavior
2213 * when the best path has an attribute change anyway.
2215 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2216 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2220 * If this is multipath, check all selected paths for any nexthop change
2222 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2223 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2224 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2225 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2229 /* Nothing has changed from the RIB's perspective. */
2233 struct bgp_process_queue
{
2235 STAILQ_HEAD(, bgp_node
) pqueue
;
2236 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2238 unsigned int queued
;
2242 * old_select = The old best path
2243 * new_select = the new best path
2245 * if (!old_select && new_select)
2246 * We are sending new information on.
2248 * if (old_select && new_select) {
2249 * if (new_select != old_select)
2250 * We have a new best path send a change
2252 * We've received a update with new attributes that needs
2256 * if (old_select && !new_select)
2257 * We have no eligible route that we can announce or the rn
2260 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2261 afi_t afi
, safi_t safi
)
2263 struct bgp_path_info
*new_select
;
2264 struct bgp_path_info
*old_select
;
2265 struct bgp_path_info_pair old_and_new
;
2266 char pfx_buf
[PREFIX2STR_BUFFER
];
2269 /* Is it end of initial update? (after startup) */
2271 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2272 sizeof(bgp
->update_delay_zebra_resume_time
));
2274 bgp
->main_zebra_update_hold
= 0;
2275 FOREACH_AFI_SAFI (afi
, safi
) {
2276 if (bgp_fibupd_safi(safi
))
2277 bgp_zebra_announce_table(bgp
, afi
, safi
);
2279 bgp
->main_peers_update_hold
= 0;
2281 bgp_start_routeadv(bgp
);
2285 struct prefix
*p
= &rn
->p
;
2287 debug
= bgp_debug_bestpath(&rn
->p
);
2289 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2290 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2291 afi2str(afi
), safi2str(safi
));
2294 /* Best path selection. */
2295 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2297 old_select
= old_and_new
.old
;
2298 new_select
= old_and_new
.new;
2300 /* Do we need to allocate or free labels?
2301 * Right now, since we only deal with per-prefix labels, it is not
2302 * necessary to do this upon changes to best path. Exceptions:
2303 * - label index has changed -> recalculate resulting label
2304 * - path_info sub_type changed -> switch to/from implicit-null
2305 * - no valid label (due to removed static label binding) -> get new one
2307 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2310 || bgp_label_index_differs(new_select
, old_select
)
2311 || new_select
->sub_type
!= old_select
->sub_type
2312 || !bgp_is_valid_label(&rn
->local_label
)) {
2313 /* Enforced penultimate hop popping:
2314 * implicit-null for local routes, aggregate
2315 * and redistributed routes
2317 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2318 || new_select
->sub_type
2319 == BGP_ROUTE_AGGREGATE
2320 || new_select
->sub_type
2321 == BGP_ROUTE_REDISTRIBUTE
) {
2324 BGP_NODE_REGISTERED_FOR_LABEL
))
2325 bgp_unregister_for_label(rn
);
2326 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2328 bgp_set_valid_label(&rn
->local_label
);
2330 bgp_register_for_label(rn
, new_select
);
2332 } else if (CHECK_FLAG(rn
->flags
,
2333 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2334 bgp_unregister_for_label(rn
);
2336 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2337 bgp_unregister_for_label(rn
);
2341 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2343 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2344 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2345 old_select
, new_select
);
2348 /* If best route remains the same and this is not due to user-initiated
2349 * clear, see exactly what needs to be done.
2351 if (old_select
&& old_select
== new_select
2352 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2353 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2354 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2355 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2357 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2358 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2360 if (bgp_fibupd_safi(safi
)
2361 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2363 if (new_select
->type
== ZEBRA_ROUTE_BGP
2364 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2365 || new_select
->sub_type
2366 == BGP_ROUTE_IMPORTED
))
2368 bgp_zebra_announce(rn
, p
, old_select
,
2372 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2373 bgp_zebra_clear_route_change_flags(rn
);
2375 /* If there is a change of interest to peers, reannounce the
2377 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2378 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2379 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2381 /* unicast routes must also be annouced to
2382 * labeled-unicast update-groups */
2383 if (safi
== SAFI_UNICAST
)
2384 group_announce_route(bgp
, afi
,
2385 SAFI_LABELED_UNICAST
, rn
,
2388 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2389 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2392 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2396 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2398 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2400 /* bestpath has changed; bump version */
2401 if (old_select
|| new_select
) {
2402 bgp_bump_version(rn
);
2404 if (!bgp
->t_rmap_def_originate_eval
) {
2408 update_group_refresh_default_originate_route_map
,
2409 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2410 &bgp
->t_rmap_def_originate_eval
);
2415 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2418 zlog_debug("%s: setting SELECTED flag", __func__
);
2419 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2420 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2421 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2425 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2426 if (old_select
!= new_select
) {
2428 vnc_import_bgp_exterior_del_route(bgp
, p
,
2430 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2433 vnc_import_bgp_exterior_add_route(bgp
, p
,
2435 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2441 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2443 /* unicast routes must also be annouced to labeled-unicast update-groups
2445 if (safi
== SAFI_UNICAST
)
2446 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2450 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2451 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2452 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2453 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2454 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2455 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2457 /* if this is an evpn imported type-5 prefix,
2458 * we need to withdraw the route first to clear
2459 * the nh neigh and the RMAC entry.
2462 is_route_parent_evpn(old_select
))
2463 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2465 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2467 /* Withdraw the route from the kernel. */
2468 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2469 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2470 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2471 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2473 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2477 /* advertise/withdraw type-5 routes */
2478 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2479 if (advertise_type5_routes(bgp
, afi
) &&
2481 is_route_injectable_into_evpn(new_select
)) {
2483 /* apply the route-map */
2484 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2487 ret
= route_map_apply(
2488 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2489 &rn
->p
, RMAP_BGP
, new_select
);
2490 if (ret
== RMAP_MATCH
)
2491 bgp_evpn_advertise_type5_route(
2492 bgp
, &rn
->p
, new_select
->attr
,
2495 bgp_evpn_withdraw_type5_route(
2496 bgp
, &rn
->p
, afi
, safi
);
2498 bgp_evpn_advertise_type5_route(bgp
,
2504 } else if (advertise_type5_routes(bgp
, afi
) &&
2506 is_route_injectable_into_evpn(old_select
))
2507 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2510 /* Clear any route change flags. */
2511 bgp_zebra_clear_route_change_flags(rn
);
2513 /* Reap old select bgp_path_info, if it has been removed */
2514 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2515 bgp_path_info_reap(rn
, old_select
);
2517 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2521 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2523 struct bgp_process_queue
*pqnode
= data
;
2524 struct bgp
*bgp
= pqnode
->bgp
;
2525 struct bgp_table
*table
;
2526 struct bgp_node
*rn
;
2529 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2530 bgp_process_main_one(bgp
, NULL
, 0, 0);
2531 /* should always have dedicated wq call */
2532 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2536 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2537 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2538 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2539 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2540 table
= bgp_node_table(rn
);
2541 /* note, new RNs may be added as part of processing */
2542 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2544 bgp_unlock_node(rn
);
2545 bgp_table_unlock(table
);
2551 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2553 struct bgp_process_queue
*pqnode
= data
;
2555 bgp_unlock(pqnode
->bgp
);
2557 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2560 void bgp_process_queue_init(void)
2562 if (!bm
->process_main_queue
)
2563 bm
->process_main_queue
=
2564 work_queue_new(bm
->master
, "process_main_queue");
2566 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2567 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2568 bm
->process_main_queue
->spec
.max_retries
= 0;
2569 bm
->process_main_queue
->spec
.hold
= 50;
2570 /* Use a higher yield value of 50ms for main queue processing */
2571 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2574 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2576 struct bgp_process_queue
*pqnode
;
2578 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2579 sizeof(struct bgp_process_queue
));
2581 /* unlocked in bgp_processq_del */
2582 pqnode
->bgp
= bgp_lock(bgp
);
2583 STAILQ_INIT(&pqnode
->pqueue
);
2588 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2590 #define ARBITRARY_PROCESS_QLEN 10000
2591 struct work_queue
*wq
= bm
->process_main_queue
;
2592 struct bgp_process_queue
*pqnode
;
2593 int pqnode_reuse
= 0;
2595 /* already scheduled for processing? */
2596 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2602 /* Add route nodes to an existing work queue item until reaching the
2603 limit only if is from the same BGP view and it's not an EOIU marker
2605 if (work_queue_item_count(wq
)) {
2606 struct work_queue_item
*item
= work_queue_last_item(wq
);
2607 pqnode
= item
->data
;
2609 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2610 || pqnode
->bgp
!= bgp
2611 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2612 pqnode
= bgp_processq_alloc(bgp
);
2616 pqnode
= bgp_processq_alloc(bgp
);
2617 /* all unlocked in bgp_process_wq */
2618 bgp_table_lock(bgp_node_table(rn
));
2620 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2623 /* can't be enqueued twice */
2624 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2625 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2629 work_queue_add(wq
, pqnode
);
2634 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2636 struct bgp_process_queue
*pqnode
;
2638 if (bm
->process_main_queue
== NULL
)
2641 pqnode
= bgp_processq_alloc(bgp
);
2643 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2644 work_queue_add(bm
->process_main_queue
, pqnode
);
2647 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2651 peer
= THREAD_ARG(thread
);
2652 peer
->t_pmax_restart
= NULL
;
2654 if (bgp_debug_neighbor_events(peer
))
2656 "%s Maximum-prefix restart timer expired, restore peering",
2659 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2660 zlog_debug("%s: %s peer_clear failed",
2661 __PRETTY_FUNCTION__
, peer
->host
);
2666 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2670 iana_safi_t pkt_safi
;
2672 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2675 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2676 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2677 PEER_STATUS_PREFIX_LIMIT
)
2682 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2684 afi_safi_print(afi
, safi
), peer
->host
,
2685 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2686 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2688 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2689 PEER_FLAG_MAX_PREFIX_WARNING
))
2692 /* Convert AFI, SAFI to values for packet. */
2693 pkt_afi
= afi_int2iana(afi
);
2694 pkt_safi
= safi_int2iana(safi
);
2698 ndata
[0] = (pkt_afi
>> 8);
2700 ndata
[2] = pkt_safi
;
2701 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2702 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2703 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2704 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2706 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2707 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2708 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2712 /* Dynamic peers will just close their connection. */
2713 if (peer_dynamic_neighbor(peer
))
2716 /* restart timer start */
2717 if (peer
->pmax_restart
[afi
][safi
]) {
2718 peer
->v_pmax_restart
=
2719 peer
->pmax_restart
[afi
][safi
] * 60;
2721 if (bgp_debug_neighbor_events(peer
))
2723 "%s Maximum-prefix restart timer started for %d secs",
2724 peer
->host
, peer
->v_pmax_restart
);
2726 BGP_TIMER_ON(peer
->t_pmax_restart
,
2727 bgp_maximum_prefix_restart_timer
,
2728 peer
->v_pmax_restart
);
2733 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2734 PEER_STATUS_PREFIX_LIMIT
);
2736 if (peer
->pcount
[afi
][safi
]
2737 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2738 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2739 PEER_STATUS_PREFIX_THRESHOLD
)
2744 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2745 afi_safi_print(afi
, safi
), peer
->host
,
2746 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2747 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2748 PEER_STATUS_PREFIX_THRESHOLD
);
2750 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2751 PEER_STATUS_PREFIX_THRESHOLD
);
2755 /* Unconditionally remove the route from the RIB, without taking
2756 * damping into consideration (eg, because the session went down)
2758 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2759 struct peer
*peer
, afi_t afi
, safi_t safi
)
2761 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2763 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2764 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2766 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2769 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2770 struct peer
*peer
, afi_t afi
, safi_t safi
,
2771 struct prefix_rd
*prd
)
2773 /* apply dampening, if result is suppressed, we'll be retaining
2774 * the bgp_path_info in the RIB for historical reference.
2776 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2777 && peer
->sort
== BGP_PEER_EBGP
)
2778 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2779 == BGP_DAMP_SUPPRESSED
) {
2780 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2786 if (safi
== SAFI_MPLS_VPN
) {
2787 struct bgp_node
*prn
= NULL
;
2788 struct bgp_table
*table
= NULL
;
2790 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2791 (struct prefix
*)prd
);
2792 if (bgp_node_has_bgp_path_info_data(prn
)) {
2793 table
= bgp_node_get_bgp_table_info(prn
);
2795 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2796 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2798 bgp_unlock_node(prn
);
2800 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2801 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2803 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2804 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2810 /* If this is an EVPN route, process for un-import. */
2811 if (safi
== SAFI_EVPN
)
2812 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2814 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2817 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2818 struct peer
*peer
, struct attr
*attr
,
2819 struct bgp_node
*rn
)
2821 struct bgp_path_info
*new;
2823 /* Make new BGP info. */
2824 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2826 new->instance
= instance
;
2827 new->sub_type
= sub_type
;
2830 new->uptime
= bgp_clock();
2835 static void overlay_index_update(struct attr
*attr
,
2836 struct eth_segment_id
*eth_s_id
,
2837 union gw_addr
*gw_ip
)
2842 if (eth_s_id
== NULL
) {
2843 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2844 sizeof(struct eth_segment_id
));
2846 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2847 sizeof(struct eth_segment_id
));
2849 if (gw_ip
== NULL
) {
2850 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2852 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2853 sizeof(union gw_addr
));
2857 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2858 struct eth_segment_id
*eth_s_id
,
2859 union gw_addr
*gw_ip
)
2861 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2862 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2864 struct eth_segment_id esi
;
2868 if (afi
!= AFI_L2VPN
)
2871 memset(&temp
, 0, sizeof(temp
));
2872 path_eth_s_id
= &temp
.esi
;
2873 path_gw_ip
= &temp
.ip
;
2875 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2878 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2879 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2882 if (gw_ip
== NULL
) {
2883 memset(&temp
, 0, sizeof(temp
));
2884 path_gw_ip_remote
= &temp
.ip
;
2886 path_gw_ip_remote
= gw_ip
;
2888 if (eth_s_id
== NULL
) {
2889 memset(&temp
, 0, sizeof(temp
));
2890 path_eth_s_id_remote
= &temp
.esi
;
2892 path_eth_s_id_remote
= eth_s_id
;
2894 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2897 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2898 sizeof(struct eth_segment_id
));
2901 /* Check if received nexthop is valid or not. */
2902 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2907 /* Only validated for unicast and multicast currently. */
2908 /* Also valid for EVPN where the nexthop is an IP address. */
2909 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2912 /* If NEXT_HOP is present, validate it. */
2913 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2914 if (attr
->nexthop
.s_addr
== 0
2915 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2916 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2920 /* If MP_NEXTHOP is present, validate it. */
2921 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2922 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2923 * it is not an IPv6 link-local address.
2925 if (attr
->mp_nexthop_len
) {
2926 switch (attr
->mp_nexthop_len
) {
2927 case BGP_ATTR_NHLEN_IPV4
:
2928 case BGP_ATTR_NHLEN_VPNV4
:
2929 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2930 || IPV4_CLASS_DE(ntohl(
2931 attr
->mp_nexthop_global_in
.s_addr
))
2932 || bgp_nexthop_self(bgp
,
2933 attr
->mp_nexthop_global_in
));
2936 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2937 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2938 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2939 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2940 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2941 || IN6_IS_ADDR_MULTICAST(
2942 &attr
->mp_nexthop_global
));
2954 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2955 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2956 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2957 uint32_t num_labels
, int soft_reconfig
,
2958 struct bgp_route_evpn
*evpn
)
2961 int aspath_loop_count
= 0;
2962 struct bgp_node
*rn
;
2964 struct attr new_attr
;
2965 struct attr
*attr_new
;
2966 struct bgp_path_info
*pi
;
2967 struct bgp_path_info
*new;
2968 struct bgp_path_info_extra
*extra
;
2970 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2972 int do_loop_check
= 1;
2973 int has_valid_label
= 0;
2975 int vnc_implicit_withdraw
= 0;
2979 memset(&new_attr
, 0, sizeof(struct attr
));
2980 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2981 new_attr
.label
= MPLS_INVALID_LABEL
;
2984 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2985 /* TODO: Check to see if we can get rid of "is_valid_label" */
2986 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2987 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2989 has_valid_label
= bgp_is_valid_label(label
);
2991 /* When peer's soft reconfiguration enabled. Record input packet in
2994 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2995 && peer
!= bgp
->peer_self
)
2996 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2998 /* Check previously received route. */
2999 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3000 if (pi
->peer
== peer
&& pi
->type
== type
3001 && pi
->sub_type
== sub_type
3002 && pi
->addpath_rx_id
== addpath_id
)
3005 /* AS path local-as loop check. */
3006 if (peer
->change_local_as
) {
3007 if (peer
->allowas_in
[afi
][safi
])
3008 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3009 else if (!CHECK_FLAG(peer
->flags
,
3010 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3011 aspath_loop_count
= 1;
3013 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3014 > aspath_loop_count
) {
3015 reason
= "as-path contains our own AS;";
3020 /* If the peer is configured for "allowas-in origin" and the last ASN in
3022 * as-path is our ASN then we do not need to call aspath_loop_check
3024 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3025 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3028 /* AS path loop check. */
3029 if (do_loop_check
) {
3030 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3031 > peer
->allowas_in
[afi
][safi
]
3032 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3033 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3034 > peer
->allowas_in
[afi
][safi
])) {
3035 reason
= "as-path contains our own AS;";
3040 /* Route reflector originator ID check. */
3041 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3042 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3043 reason
= "originator is us;";
3047 /* Route reflector cluster ID check. */
3048 if (bgp_cluster_filter(peer
, attr
)) {
3049 reason
= "reflected from the same cluster;";
3053 /* Apply incoming filter. */
3054 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3059 bgp_attr_dup(&new_attr
, attr
);
3061 /* Apply incoming route-map.
3062 * NB: new_attr may now contain newly allocated values from route-map
3064 * commands, so we need bgp_attr_flush in the error paths, until we
3066 * the attr (which takes over the memory references) */
3067 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3069 reason
= "route-map;";
3070 bgp_attr_flush(&new_attr
);
3074 if (peer
->sort
== BGP_PEER_EBGP
) {
3076 /* If we receive the graceful-shutdown community from an eBGP
3077 * peer we must lower local-preference */
3078 if (new_attr
.community
3079 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3080 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3081 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3083 /* If graceful-shutdown is configured then add the GSHUT
3084 * community to all paths received from eBGP peers */
3085 } else if (bgp_flag_check(peer
->bgp
,
3086 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3087 bgp_attr_add_gshut_community(&new_attr
);
3091 /* next hop check. */
3092 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3093 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3094 reason
= "martian or self next-hop;";
3095 bgp_attr_flush(&new_attr
);
3099 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3100 reason
= "self mac;";
3104 attr_new
= bgp_attr_intern(&new_attr
);
3106 /* If the update is implicit withdraw. */
3108 pi
->uptime
= bgp_clock();
3109 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3111 /* Same attribute comes in. */
3112 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3113 && attrhash_cmp(pi
->attr
, attr_new
)
3114 && (!has_valid_label
3115 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3116 num_labels
* sizeof(mpls_label_t
))
3118 && (overlay_index_equal(
3119 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3120 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3121 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3122 BGP_CONFIG_DAMPENING
)
3123 && peer
->sort
== BGP_PEER_EBGP
3124 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3125 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3126 bgp_debug_rdpfxpath2str(
3127 afi
, safi
, prd
, p
, label
,
3128 num_labels
, addpath_id
? 1 : 0,
3129 addpath_id
, pfx_buf
,
3131 zlog_debug("%s rcvd %s", peer
->host
,
3135 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3136 != BGP_DAMP_SUPPRESSED
) {
3137 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3139 bgp_process(bgp
, rn
, afi
, safi
);
3141 } else /* Duplicate - odd */
3143 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3144 if (!peer
->rcvd_attr_printed
) {
3146 "%s rcvd UPDATE w/ attr: %s",
3148 peer
->rcvd_attr_str
);
3149 peer
->rcvd_attr_printed
= 1;
3152 bgp_debug_rdpfxpath2str(
3153 afi
, safi
, prd
, p
, label
,
3154 num_labels
, addpath_id
? 1 : 0,
3155 addpath_id
, pfx_buf
,
3158 "%s rcvd %s...duplicate ignored",
3159 peer
->host
, pfx_buf
);
3162 /* graceful restart STALE flag unset. */
3163 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3164 bgp_path_info_unset_flag(
3165 rn
, pi
, BGP_PATH_STALE
);
3166 bgp_process(bgp
, rn
, afi
, safi
);
3170 bgp_unlock_node(rn
);
3171 bgp_attr_unintern(&attr_new
);
3176 /* Withdraw/Announce before we fully processed the withdraw */
3177 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3178 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3179 bgp_debug_rdpfxpath2str(
3180 afi
, safi
, prd
, p
, label
, num_labels
,
3181 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3184 "%s rcvd %s, flapped quicker than processing",
3185 peer
->host
, pfx_buf
);
3188 bgp_path_info_restore(rn
, pi
);
3191 /* Received Logging. */
3192 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3193 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3194 num_labels
, addpath_id
? 1 : 0,
3195 addpath_id
, pfx_buf
,
3197 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3200 /* graceful restart STALE flag unset. */
3201 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3202 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3204 /* The attribute is changed. */
3205 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3207 /* implicit withdraw, decrement aggregate and pcount here.
3208 * only if update is accepted, they'll increment below.
3210 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3212 /* Update bgp route dampening information. */
3213 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3214 && peer
->sort
== BGP_PEER_EBGP
) {
3215 /* This is implicit withdraw so we should update
3218 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3219 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3222 if (safi
== SAFI_MPLS_VPN
) {
3223 struct bgp_node
*prn
= NULL
;
3224 struct bgp_table
*table
= NULL
;
3226 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3227 (struct prefix
*)prd
);
3228 if (bgp_node_has_bgp_path_info_data(prn
)) {
3229 table
= bgp_node_get_bgp_table_info(prn
);
3231 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3232 bgp
, prd
, table
, p
, pi
);
3234 bgp_unlock_node(prn
);
3236 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3237 && (safi
== SAFI_UNICAST
)) {
3238 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3240 * Implicit withdraw case.
3242 ++vnc_implicit_withdraw
;
3243 vnc_import_bgp_del_route(bgp
, p
, pi
);
3244 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3249 /* Special handling for EVPN update of an existing route. If the
3250 * extended community attribute has changed, we need to
3252 * the route using its existing extended community. It will be
3253 * subsequently processed for import with the new extended
3256 if (safi
== SAFI_EVPN
&& !same_attr
) {
3258 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3260 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3263 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3264 attr_new
->ecommunity
);
3266 if (bgp_debug_update(peer
, p
, NULL
, 1))
3268 "Change in EXT-COMM, existing %s new %s",
3270 pi
->attr
->ecommunity
),
3272 attr_new
->ecommunity
));
3273 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3279 /* Update to new attribute. */
3280 bgp_attr_unintern(&pi
->attr
);
3281 pi
->attr
= attr_new
;
3283 /* Update MPLS label */
3284 if (has_valid_label
) {
3285 extra
= bgp_path_info_extra_get(pi
);
3286 if (extra
->label
!= label
) {
3287 memcpy(&extra
->label
, label
,
3288 num_labels
* sizeof(mpls_label_t
));
3289 extra
->num_labels
= num_labels
;
3291 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3292 bgp_set_valid_label(&extra
->label
[0]);
3296 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3297 && (safi
== SAFI_UNICAST
)) {
3298 if (vnc_implicit_withdraw
) {
3300 * Add back the route with its new attributes
3302 * The route is still selected, until the route
3304 * queued by bgp_process actually runs. We have
3306 * update to the VNC side immediately to avoid
3308 * configuration changes (e.g., route-map
3310 * trigger re-importation of the entire RIB.
3312 vnc_import_bgp_add_route(bgp
, p
, pi
);
3313 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3317 /* Update Overlay Index */
3318 if (afi
== AFI_L2VPN
) {
3319 overlay_index_update(
3320 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3321 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3324 /* Update bgp route dampening information. */
3325 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3326 && peer
->sort
== BGP_PEER_EBGP
) {
3327 /* Now we do normal update dampening. */
3328 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3329 if (ret
== BGP_DAMP_SUPPRESSED
) {
3330 bgp_unlock_node(rn
);
3335 /* Nexthop reachability check - for unicast and
3336 * labeled-unicast.. */
3337 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3338 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3339 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3340 && !CHECK_FLAG(peer
->flags
,
3341 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3343 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3348 struct bgp
*bgp_nexthop
= bgp
;
3350 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3351 bgp_nexthop
= pi
->extra
->bgp_orig
;
3353 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3355 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3356 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3358 if (BGP_DEBUG(nht
, NHT
)) {
3359 char buf1
[INET6_ADDRSTRLEN
];
3361 (const void *)&attr_new
3363 buf1
, INET6_ADDRSTRLEN
);
3364 zlog_debug("%s(%s): NH unresolved",
3365 __FUNCTION__
, buf1
);
3367 bgp_path_info_unset_flag(rn
, pi
,
3371 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3374 if (safi
== SAFI_MPLS_VPN
) {
3375 struct bgp_node
*prn
= NULL
;
3376 struct bgp_table
*table
= NULL
;
3378 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3379 (struct prefix
*)prd
);
3380 if (bgp_node_has_bgp_path_info_data(prn
)) {
3381 table
= bgp_node_get_bgp_table_info(prn
);
3383 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3384 bgp
, prd
, table
, p
, pi
);
3386 bgp_unlock_node(prn
);
3390 /* If this is an EVPN route and some attribute has changed,
3392 * route for import. If the extended community has changed, we
3394 * have done the un-import earlier and the import would result
3396 * route getting injected into appropriate L2 VNIs. If it is
3398 * some other attribute change, the import will result in
3400 * the attributes for the route in the VNI(s).
3402 if (safi
== SAFI_EVPN
&& !same_attr
)
3403 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3405 /* Process change. */
3406 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3408 bgp_process(bgp
, rn
, afi
, safi
);
3409 bgp_unlock_node(rn
);
3411 if (SAFI_UNICAST
== safi
3412 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3413 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3415 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3417 if ((SAFI_MPLS_VPN
== safi
)
3418 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3420 vpn_leak_to_vrf_update(bgp
, pi
);
3424 if (SAFI_MPLS_VPN
== safi
) {
3425 mpls_label_t label_decoded
= decode_label(label
);
3427 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3428 type
, sub_type
, &label_decoded
);
3430 if (SAFI_ENCAP
== safi
) {
3431 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3432 type
, sub_type
, NULL
);
3437 } // End of implicit withdraw
3439 /* Received Logging. */
3440 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3441 if (!peer
->rcvd_attr_printed
) {
3442 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3443 peer
->rcvd_attr_str
);
3444 peer
->rcvd_attr_printed
= 1;
3447 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3448 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3450 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3453 /* Make new BGP info. */
3454 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3456 /* Update MPLS label */
3457 if (has_valid_label
) {
3458 extra
= bgp_path_info_extra_get(new);
3459 if (extra
->label
!= label
) {
3460 memcpy(&extra
->label
, label
,
3461 num_labels
* sizeof(mpls_label_t
));
3462 extra
->num_labels
= num_labels
;
3464 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3465 bgp_set_valid_label(&extra
->label
[0]);
3468 /* Update Overlay Index */
3469 if (afi
== AFI_L2VPN
) {
3470 overlay_index_update(new->attr
,
3471 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3472 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3474 /* Nexthop reachability check. */
3475 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3476 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3477 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3478 && !CHECK_FLAG(peer
->flags
,
3479 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3480 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3485 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3486 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3487 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3489 if (BGP_DEBUG(nht
, NHT
)) {
3490 char buf1
[INET6_ADDRSTRLEN
];
3492 (const void *)&attr_new
->nexthop
,
3493 buf1
, INET6_ADDRSTRLEN
);
3494 zlog_debug("%s(%s): NH unresolved",
3495 __FUNCTION__
, buf1
);
3497 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3500 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3503 new->addpath_rx_id
= addpath_id
;
3505 /* Increment prefix */
3506 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3508 /* Register new BGP information. */
3509 bgp_path_info_add(rn
, new);
3511 /* route_node_get lock */
3512 bgp_unlock_node(rn
);
3515 if (safi
== SAFI_MPLS_VPN
) {
3516 struct bgp_node
*prn
= NULL
;
3517 struct bgp_table
*table
= NULL
;
3519 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3520 if (bgp_node_has_bgp_path_info_data(prn
)) {
3521 table
= bgp_node_get_bgp_table_info(prn
);
3523 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3524 bgp
, prd
, table
, p
, new);
3526 bgp_unlock_node(prn
);
3530 /* If maximum prefix count is configured and current prefix
3532 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3535 /* If this is an EVPN route, process for import. */
3536 if (safi
== SAFI_EVPN
)
3537 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3539 /* Process change. */
3540 bgp_process(bgp
, rn
, afi
, safi
);
3542 if (SAFI_UNICAST
== safi
3543 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3544 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3545 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3547 if ((SAFI_MPLS_VPN
== safi
)
3548 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3550 vpn_leak_to_vrf_update(bgp
, new);
3553 if (SAFI_MPLS_VPN
== safi
) {
3554 mpls_label_t label_decoded
= decode_label(label
);
3556 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3557 sub_type
, &label_decoded
);
3559 if (SAFI_ENCAP
== safi
) {
3560 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3567 /* This BGP update is filtered. Log the reason then update BGP
3570 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3571 if (!peer
->rcvd_attr_printed
) {
3572 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3573 peer
->rcvd_attr_str
);
3574 peer
->rcvd_attr_printed
= 1;
3577 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3578 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3580 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3581 peer
->host
, pfx_buf
, reason
);
3585 /* If this is an EVPN route, un-import it as it is now filtered.
3587 if (safi
== SAFI_EVPN
)
3588 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3590 if (SAFI_UNICAST
== safi
3591 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3592 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3594 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3596 if ((SAFI_MPLS_VPN
== safi
)
3597 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3599 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3602 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3605 bgp_unlock_node(rn
);
3609 * Filtered update is treated as an implicit withdrawal (see
3611 * a few lines above)
3613 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3614 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3622 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3623 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3624 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3625 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3628 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3629 struct bgp_node
*rn
;
3630 struct bgp_path_info
*pi
;
3633 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3634 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3642 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3644 /* If peer is soft reconfiguration enabled. Record input packet for
3645 * further calculation.
3647 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3648 * routes that are filtered. This tanks out Quagga RS pretty badly due
3650 * the iteration over all RS clients.
3651 * Since we need to remove the entry from adj_in anyway, do that first
3653 * if there was no entry, we don't need to do anything more.
3655 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3656 && peer
!= bgp
->peer_self
)
3657 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3658 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3659 bgp_debug_rdpfxpath2str(
3660 afi
, safi
, prd
, p
, label
, num_labels
,
3661 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3664 "%s withdrawing route %s not in adj-in",
3665 peer
->host
, pfx_buf
);
3667 bgp_unlock_node(rn
);
3671 /* Lookup withdrawn route. */
3672 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3673 if (pi
->peer
== peer
&& pi
->type
== type
3674 && pi
->sub_type
== sub_type
3675 && pi
->addpath_rx_id
== addpath_id
)
3679 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3680 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3681 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3683 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3687 /* Withdraw specified route from routing table. */
3688 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3689 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3690 if (SAFI_UNICAST
== safi
3691 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3692 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3693 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3695 if ((SAFI_MPLS_VPN
== safi
)
3696 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3698 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3700 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3701 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3702 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3704 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3707 /* Unlock bgp_node_get() lock. */
3708 bgp_unlock_node(rn
);
3713 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3716 struct update_subgroup
*subgrp
;
3717 subgrp
= peer_subgroup(peer
, afi
, safi
);
3718 subgroup_default_originate(subgrp
, withdraw
);
3723 * bgp_stop_announce_route_timer
3725 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3727 if (!paf
->t_announce_route
)
3730 THREAD_TIMER_OFF(paf
->t_announce_route
);
3734 * bgp_announce_route_timer_expired
3736 * Callback that is invoked when the route announcement timer for a
3739 static int bgp_announce_route_timer_expired(struct thread
*t
)
3741 struct peer_af
*paf
;
3744 paf
= THREAD_ARG(t
);
3747 if (peer
->status
!= Established
)
3750 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3753 peer_af_announce_route(paf
, 1);
3758 * bgp_announce_route
3760 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3762 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3764 struct peer_af
*paf
;
3765 struct update_subgroup
*subgrp
;
3767 paf
= peer_af_find(peer
, afi
, safi
);
3770 subgrp
= PAF_SUBGRP(paf
);
3773 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3774 * or a refresh has already been triggered.
3776 if (!subgrp
|| paf
->t_announce_route
)
3780 * Start a timer to stagger/delay the announce. This serves
3781 * two purposes - announcement can potentially be combined for
3782 * multiple peers and the announcement doesn't happen in the
3785 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3786 (subgrp
->peer_count
== 1)
3787 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3788 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3789 &paf
->t_announce_route
);
3793 * Announce routes from all AF tables to a peer.
3795 * This should ONLY be called when there is a need to refresh the
3796 * routes to the peer based on a policy change for this peer alone
3797 * or a route refresh request received from the peer.
3798 * The operation will result in splitting the peer from its existing
3799 * subgroups and putting it in new subgroups.
3801 void bgp_announce_route_all(struct peer
*peer
)
3806 FOREACH_AFI_SAFI (afi
, safi
)
3807 bgp_announce_route(peer
, afi
, safi
);
3810 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3811 struct bgp_table
*table
,
3812 struct prefix_rd
*prd
)
3815 struct bgp_node
*rn
;
3816 struct bgp_adj_in
*ain
;
3819 table
= peer
->bgp
->rib
[afi
][safi
];
3821 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3822 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3823 if (ain
->peer
!= peer
)
3826 struct bgp_path_info
*pi
=
3827 bgp_node_get_bgp_path_info(rn
);
3828 uint32_t num_labels
= 0;
3829 mpls_label_t
*label_pnt
= NULL
;
3830 struct bgp_route_evpn evpn
;
3832 if (pi
&& pi
->extra
)
3833 num_labels
= pi
->extra
->num_labels
;
3835 label_pnt
= &pi
->extra
->label
[0];
3837 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3840 memset(&evpn
, 0, sizeof(evpn
));
3842 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3843 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3844 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3845 num_labels
, 1, &evpn
);
3848 bgp_unlock_node(rn
);
3854 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3856 struct bgp_node
*rn
;
3857 struct bgp_table
*table
;
3859 if (peer
->status
!= Established
)
3862 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3863 && (safi
!= SAFI_EVPN
))
3864 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3866 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3867 rn
= bgp_route_next(rn
)) {
3868 table
= bgp_node_get_bgp_table_info(rn
);
3869 if (table
!= NULL
) {
3870 struct prefix_rd prd
;
3872 prd
.family
= AF_UNSPEC
;
3874 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3876 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3883 struct bgp_clear_node_queue
{
3884 struct bgp_node
*rn
;
3887 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3889 struct bgp_clear_node_queue
*cnq
= data
;
3890 struct bgp_node
*rn
= cnq
->rn
;
3891 struct peer
*peer
= wq
->spec
.data
;
3892 struct bgp_path_info
*pi
;
3894 afi_t afi
= bgp_node_table(rn
)->afi
;
3895 safi_t safi
= bgp_node_table(rn
)->safi
;
3900 /* It is possible that we have multiple paths for a prefix from a peer
3901 * if that peer is using AddPath.
3903 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3904 if (pi
->peer
!= peer
)
3907 /* graceful restart STALE flag set. */
3908 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3909 && peer
->nsf
[afi
][safi
]
3910 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3911 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3912 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3914 /* If this is an EVPN route, process for
3916 if (safi
== SAFI_EVPN
)
3917 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3919 /* Handle withdraw for VRF route-leaking and L3VPN */
3920 if (SAFI_UNICAST
== safi
3921 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3922 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3923 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3926 if (SAFI_MPLS_VPN
== safi
&&
3927 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3928 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3931 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3937 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3939 struct bgp_clear_node_queue
*cnq
= data
;
3940 struct bgp_node
*rn
= cnq
->rn
;
3941 struct bgp_table
*table
= bgp_node_table(rn
);
3943 bgp_unlock_node(rn
);
3944 bgp_table_unlock(table
);
3945 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3948 static void bgp_clear_node_complete(struct work_queue
*wq
)
3950 struct peer
*peer
= wq
->spec
.data
;
3952 /* Tickle FSM to start moving again */
3953 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3955 peer_unlock(peer
); /* bgp_clear_route */
3958 static void bgp_clear_node_queue_init(struct peer
*peer
)
3960 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3962 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3963 #undef CLEAR_QUEUE_NAME_LEN
3965 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3966 peer
->clear_node_queue
->spec
.hold
= 10;
3967 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3968 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3969 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3970 peer
->clear_node_queue
->spec
.max_retries
= 0;
3972 /* we only 'lock' this peer reference when the queue is actually active
3974 peer
->clear_node_queue
->spec
.data
= peer
;
3977 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3978 struct bgp_table
*table
)
3980 struct bgp_node
*rn
;
3981 int force
= bm
->process_main_queue
? 0 : 1;
3984 table
= peer
->bgp
->rib
[afi
][safi
];
3986 /* If still no table => afi/safi isn't configured at all or smth. */
3990 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3991 struct bgp_path_info
*pi
, *next
;
3992 struct bgp_adj_in
*ain
;
3993 struct bgp_adj_in
*ain_next
;
3995 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3996 * queued for every clearing peer, regardless of whether it is
3997 * relevant to the peer at hand.
3999 * Overview: There are 3 different indices which need to be
4000 * scrubbed, potentially, when a peer is removed:
4002 * 1 peer's routes visible via the RIB (ie accepted routes)
4003 * 2 peer's routes visible by the (optional) peer's adj-in index
4004 * 3 other routes visible by the peer's adj-out index
4006 * 3 there is no hurry in scrubbing, once the struct peer is
4007 * removed from bgp->peer, we could just GC such deleted peer's
4008 * adj-outs at our leisure.
4010 * 1 and 2 must be 'scrubbed' in some way, at least made
4011 * invisible via RIB index before peer session is allowed to be
4012 * brought back up. So one needs to know when such a 'search' is
4017 * - there'd be a single global queue or a single RIB walker
4018 * - rather than tracking which route_nodes still need to be
4019 * examined on a peer basis, we'd track which peers still
4022 * Given that our per-peer prefix-counts now should be reliable,
4023 * this may actually be achievable. It doesn't seem to be a huge
4024 * problem at this time,
4026 * It is possible that we have multiple paths for a prefix from
4028 * if that peer is using AddPath.
4032 ain_next
= ain
->next
;
4034 if (ain
->peer
== peer
) {
4035 bgp_adj_in_remove(rn
, ain
);
4036 bgp_unlock_node(rn
);
4042 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4044 if (pi
->peer
!= peer
)
4048 bgp_path_info_reap(rn
, pi
);
4050 struct bgp_clear_node_queue
*cnq
;
4052 /* both unlocked in bgp_clear_node_queue_del */
4053 bgp_table_lock(bgp_node_table(rn
));
4056 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4057 sizeof(struct bgp_clear_node_queue
));
4059 work_queue_add(peer
->clear_node_queue
, cnq
);
4067 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4069 struct bgp_node
*rn
;
4070 struct bgp_table
*table
;
4072 if (peer
->clear_node_queue
== NULL
)
4073 bgp_clear_node_queue_init(peer
);
4075 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4076 * Idle until it receives a Clearing_Completed event. This protects
4077 * against peers which flap faster than we can we clear, which could
4080 * a) race with routes from the new session being installed before
4081 * clear_route_node visits the node (to delete the route of that
4083 * b) resource exhaustion, clear_route_node likely leads to an entry
4084 * on the process_main queue. Fast-flapping could cause that queue
4088 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4089 * the unlock will happen upon work-queue completion; other wise, the
4090 * unlock happens at the end of this function.
4092 if (!peer
->clear_node_queue
->thread
)
4095 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4096 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4098 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4099 rn
= bgp_route_next(rn
)) {
4100 table
= bgp_node_get_bgp_table_info(rn
);
4104 bgp_clear_route_table(peer
, afi
, safi
, table
);
4107 /* unlock if no nodes got added to the clear-node-queue. */
4108 if (!peer
->clear_node_queue
->thread
)
4112 void bgp_clear_route_all(struct peer
*peer
)
4117 FOREACH_AFI_SAFI (afi
, safi
)
4118 bgp_clear_route(peer
, afi
, safi
);
4121 rfapiProcessPeerDown(peer
);
4125 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4127 struct bgp_table
*table
;
4128 struct bgp_node
*rn
;
4129 struct bgp_adj_in
*ain
;
4130 struct bgp_adj_in
*ain_next
;
4132 table
= peer
->bgp
->rib
[afi
][safi
];
4134 /* It is possible that we have multiple paths for a prefix from a peer
4135 * if that peer is using AddPath.
4137 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4141 ain_next
= ain
->next
;
4143 if (ain
->peer
== peer
) {
4144 bgp_adj_in_remove(rn
, ain
);
4145 bgp_unlock_node(rn
);
4153 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4155 struct bgp_node
*rn
;
4156 struct bgp_path_info
*pi
;
4157 struct bgp_table
*table
;
4159 if (safi
== SAFI_MPLS_VPN
) {
4160 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4161 rn
= bgp_route_next(rn
)) {
4162 struct bgp_node
*rm
;
4164 /* look for neighbor in tables */
4165 table
= bgp_node_get_bgp_table_info(rn
);
4169 for (rm
= bgp_table_top(table
); rm
;
4170 rm
= bgp_route_next(rm
))
4171 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4173 if (pi
->peer
!= peer
)
4175 if (!CHECK_FLAG(pi
->flags
,
4179 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4184 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4185 rn
= bgp_route_next(rn
))
4186 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4188 if (pi
->peer
!= peer
)
4190 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4192 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4198 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4200 if (peer
->sort
== BGP_PEER_EBGP
4201 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4202 || FILTER_LIST_OUT_NAME(filter
)
4203 || DISTRIBUTE_OUT_NAME(filter
)))
4208 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4210 if (peer
->sort
== BGP_PEER_EBGP
4211 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4212 || FILTER_LIST_IN_NAME(filter
)
4213 || DISTRIBUTE_IN_NAME(filter
)))
4218 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4221 struct bgp_node
*rn
;
4222 struct bgp_path_info
*pi
;
4223 struct bgp_path_info
*next
;
4225 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4226 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4228 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4229 && pi
->type
== ZEBRA_ROUTE_BGP
4230 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4231 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4232 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4234 if (bgp_fibupd_safi(safi
))
4235 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4237 bgp_path_info_reap(rn
, pi
);
4242 /* Delete all kernel routes. */
4243 void bgp_cleanup_routes(struct bgp
*bgp
)
4246 struct bgp_node
*rn
;
4247 struct bgp_table
*table
;
4249 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4250 if (afi
== AFI_L2VPN
)
4252 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4255 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4257 if (afi
!= AFI_L2VPN
) {
4259 safi
= SAFI_MPLS_VPN
;
4260 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4261 rn
= bgp_route_next(rn
)) {
4262 table
= bgp_node_get_bgp_table_info(rn
);
4263 if (table
!= NULL
) {
4264 bgp_cleanup_table(bgp
, table
, safi
);
4265 bgp_table_finish(&table
);
4266 bgp_node_set_bgp_table_info(rn
, NULL
);
4267 bgp_unlock_node(rn
);
4271 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4272 rn
= bgp_route_next(rn
)) {
4273 table
= bgp_node_get_bgp_table_info(rn
);
4274 if (table
!= NULL
) {
4275 bgp_cleanup_table(bgp
, table
, safi
);
4276 bgp_table_finish(&table
);
4277 bgp_node_set_bgp_table_info(rn
, NULL
);
4278 bgp_unlock_node(rn
);
4283 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4284 rn
= bgp_route_next(rn
)) {
4285 table
= bgp_node_get_bgp_table_info(rn
);
4286 if (table
!= NULL
) {
4287 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4288 bgp_table_finish(&table
);
4289 bgp_node_set_bgp_table_info(rn
, NULL
);
4290 bgp_unlock_node(rn
);
4295 void bgp_reset(void)
4298 bgp_zclient_reset();
4299 access_list_reset();
4300 prefix_list_reset();
4303 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4305 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4306 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4307 PEER_CAP_ADDPATH_AF_TX_RCV
));
4310 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4312 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4313 struct bgp_nlri
*packet
)
4322 int addpath_encoded
;
4323 uint32_t addpath_id
;
4326 lim
= pnt
+ packet
->length
;
4328 safi
= packet
->safi
;
4330 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4332 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4333 syntactic validity. If the field is syntactically incorrect,
4334 then the Error Subcode is set to Invalid Network Field. */
4335 for (; pnt
< lim
; pnt
+= psize
) {
4336 /* Clear prefix structure. */
4337 memset(&p
, 0, sizeof(struct prefix
));
4339 if (addpath_encoded
) {
4341 /* When packet overflow occurs return immediately. */
4342 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4345 addpath_id
= ntohl(*((uint32_t *)pnt
));
4346 pnt
+= BGP_ADDPATH_ID_LEN
;
4349 /* Fetch prefix length. */
4350 p
.prefixlen
= *pnt
++;
4351 /* afi/safi validity already verified by caller,
4352 * bgp_update_receive */
4353 p
.family
= afi2family(afi
);
4355 /* Prefix length check. */
4356 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4359 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4360 peer
->host
, p
.prefixlen
, packet
->afi
);
4364 /* Packet size overflow check. */
4365 psize
= PSIZE(p
.prefixlen
);
4367 /* When packet overflow occur return immediately. */
4368 if (pnt
+ psize
> lim
) {
4371 "%s [Error] Update packet error (prefix length %d overflows packet)",
4372 peer
->host
, p
.prefixlen
);
4376 /* Defensive coding, double-check the psize fits in a struct
4378 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4381 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4382 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4386 /* Fetch prefix from NLRI packet. */
4387 memcpy(p
.u
.val
, pnt
, psize
);
4389 /* Check address. */
4390 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4391 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4392 /* From RFC4271 Section 6.3:
4394 * If a prefix in the NLRI field is semantically
4396 * (e.g., an unexpected multicast IP address),
4398 * be logged locally, and the prefix SHOULD be
4403 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4404 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4409 /* Check address. */
4410 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4411 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4416 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4418 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4423 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4428 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4430 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4437 /* Normal process. */
4439 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4440 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4441 NULL
, NULL
, 0, 0, NULL
);
4443 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4444 safi
, ZEBRA_ROUTE_BGP
,
4445 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4448 /* Address family configuration mismatch or maximum-prefix count
4454 /* Packet length consistency check. */
4458 "%s [Error] Update packet error (prefix length mismatch with total length)",
4466 static struct bgp_static
*bgp_static_new(void)
4468 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4471 static void bgp_static_free(struct bgp_static
*bgp_static
)
4473 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4474 route_map_counter_decrement(bgp_static
->rmap
.map
);
4476 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4477 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4480 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4481 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4483 struct bgp_node
*rn
;
4484 struct bgp_path_info
*pi
;
4485 struct bgp_path_info
*new;
4486 struct bgp_path_info rmap_path
;
4488 struct attr
*attr_new
;
4491 int vnc_implicit_withdraw
= 0;
4498 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4500 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4502 attr
.nexthop
= bgp_static
->igpnexthop
;
4503 attr
.med
= bgp_static
->igpmetric
;
4504 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4506 if (bgp_static
->atomic
)
4507 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4509 /* Store label index, if required. */
4510 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4511 attr
.label_index
= bgp_static
->label_index
;
4512 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4515 /* Apply route-map. */
4516 if (bgp_static
->rmap
.name
) {
4517 struct attr attr_tmp
= attr
;
4519 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4520 rmap_path
.peer
= bgp
->peer_self
;
4521 rmap_path
.attr
= &attr_tmp
;
4523 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4525 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4528 bgp
->peer_self
->rmap_type
= 0;
4530 if (ret
== RMAP_DENYMATCH
) {
4531 /* Free uninterned attribute. */
4532 bgp_attr_flush(&attr_tmp
);
4534 /* Unintern original. */
4535 aspath_unintern(&attr
.aspath
);
4536 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4540 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4541 bgp_attr_add_gshut_community(&attr_tmp
);
4543 attr_new
= bgp_attr_intern(&attr_tmp
);
4546 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4547 bgp_attr_add_gshut_community(&attr
);
4549 attr_new
= bgp_attr_intern(&attr
);
4552 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4553 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4554 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4558 if (attrhash_cmp(pi
->attr
, attr_new
)
4559 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4560 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4561 bgp_unlock_node(rn
);
4562 bgp_attr_unintern(&attr_new
);
4563 aspath_unintern(&attr
.aspath
);
4566 /* The attribute is changed. */
4567 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4569 /* Rewrite BGP route information. */
4570 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4571 bgp_path_info_restore(rn
, pi
);
4573 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4575 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4576 && (safi
== SAFI_UNICAST
)) {
4577 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4579 * Implicit withdraw case.
4580 * We have to do this before pi is
4583 ++vnc_implicit_withdraw
;
4584 vnc_import_bgp_del_route(bgp
, p
, pi
);
4585 vnc_import_bgp_exterior_del_route(
4590 bgp_attr_unintern(&pi
->attr
);
4591 pi
->attr
= attr_new
;
4592 pi
->uptime
= bgp_clock();
4594 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4595 && (safi
== SAFI_UNICAST
)) {
4596 if (vnc_implicit_withdraw
) {
4597 vnc_import_bgp_add_route(bgp
, p
, pi
);
4598 vnc_import_bgp_exterior_add_route(
4604 /* Nexthop reachability check. */
4605 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4606 && (safi
== SAFI_UNICAST
4607 || safi
== SAFI_LABELED_UNICAST
)) {
4609 struct bgp
*bgp_nexthop
= bgp
;
4611 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4612 bgp_nexthop
= pi
->extra
->bgp_orig
;
4614 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4616 bgp_path_info_set_flag(rn
, pi
,
4619 if (BGP_DEBUG(nht
, NHT
)) {
4620 char buf1
[INET6_ADDRSTRLEN
];
4621 inet_ntop(p
->family
,
4625 "%s(%s): Route not in table, not advertising",
4626 __FUNCTION__
, buf1
);
4628 bgp_path_info_unset_flag(
4629 rn
, pi
, BGP_PATH_VALID
);
4632 /* Delete the NHT structure if any, if we're
4634 * enabling/disabling import check. We
4635 * deregister the route
4636 * from NHT to avoid overloading NHT and the
4637 * process interaction
4639 bgp_unlink_nexthop(pi
);
4640 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4642 /* Process change. */
4643 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4644 bgp_process(bgp
, rn
, afi
, safi
);
4646 if (SAFI_UNICAST
== safi
4647 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4649 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4650 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4654 bgp_unlock_node(rn
);
4655 aspath_unintern(&attr
.aspath
);
4660 /* Make new BGP info. */
4661 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4663 /* Nexthop reachability check. */
4664 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4665 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4666 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4667 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4669 if (BGP_DEBUG(nht
, NHT
)) {
4670 char buf1
[INET6_ADDRSTRLEN
];
4671 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4674 "%s(%s): Route not in table, not advertising",
4675 __FUNCTION__
, buf1
);
4677 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4680 /* Delete the NHT structure if any, if we're toggling between
4681 * enabling/disabling import check. We deregister the route
4682 * from NHT to avoid overloading NHT and the process interaction
4684 bgp_unlink_nexthop(new);
4686 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4689 /* Aggregate address increment. */
4690 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4692 /* Register new BGP information. */
4693 bgp_path_info_add(rn
, new);
4695 /* route_node_get lock */
4696 bgp_unlock_node(rn
);
4698 /* Process change. */
4699 bgp_process(bgp
, rn
, afi
, safi
);
4701 if (SAFI_UNICAST
== safi
4702 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4703 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4704 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4707 /* Unintern original. */
4708 aspath_unintern(&attr
.aspath
);
4711 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4714 struct bgp_node
*rn
;
4715 struct bgp_path_info
*pi
;
4717 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4719 /* Check selected route and self inserted route. */
4720 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4721 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4722 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4725 /* Withdraw static BGP route from routing table. */
4727 if (SAFI_UNICAST
== safi
4728 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4729 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4730 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4732 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4733 bgp_unlink_nexthop(pi
);
4734 bgp_path_info_delete(rn
, pi
);
4735 bgp_process(bgp
, rn
, afi
, safi
);
4738 /* Unlock bgp_node_lookup. */
4739 bgp_unlock_node(rn
);
4743 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4745 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4746 afi_t afi
, safi_t safi
,
4747 struct prefix_rd
*prd
)
4749 struct bgp_node
*rn
;
4750 struct bgp_path_info
*pi
;
4752 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4754 /* Check selected route and self inserted route. */
4755 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4756 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4757 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4760 /* Withdraw static BGP route from routing table. */
4763 rfapiProcessWithdraw(
4764 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4765 1); /* Kill, since it is an administrative change */
4767 if (SAFI_MPLS_VPN
== safi
4768 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4769 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4771 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4772 bgp_path_info_delete(rn
, pi
);
4773 bgp_process(bgp
, rn
, afi
, safi
);
4776 /* Unlock bgp_node_lookup. */
4777 bgp_unlock_node(rn
);
4780 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4781 struct bgp_static
*bgp_static
, afi_t afi
,
4784 struct bgp_node
*rn
;
4785 struct bgp_path_info
*new;
4786 struct attr
*attr_new
;
4787 struct attr attr
= {0};
4788 struct bgp_path_info
*pi
;
4790 mpls_label_t label
= 0;
4792 uint32_t num_labels
= 0;
4797 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4799 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4802 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4804 attr
.nexthop
= bgp_static
->igpnexthop
;
4805 attr
.med
= bgp_static
->igpmetric
;
4806 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4808 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4809 || (safi
== SAFI_ENCAP
)) {
4810 if (afi
== AFI_IP
) {
4811 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4812 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4815 if (afi
== AFI_L2VPN
) {
4816 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4818 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4819 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4820 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4821 sizeof(struct in6_addr
));
4822 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4823 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4824 struct bgp_encap_type_vxlan bet
;
4825 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4826 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4827 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4829 if (bgp_static
->router_mac
) {
4830 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4833 /* Apply route-map. */
4834 if (bgp_static
->rmap
.name
) {
4835 struct attr attr_tmp
= attr
;
4836 struct bgp_path_info rmap_path
;
4839 rmap_path
.peer
= bgp
->peer_self
;
4840 rmap_path
.attr
= &attr_tmp
;
4842 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4844 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4847 bgp
->peer_self
->rmap_type
= 0;
4849 if (ret
== RMAP_DENYMATCH
) {
4850 /* Free uninterned attribute. */
4851 bgp_attr_flush(&attr_tmp
);
4853 /* Unintern original. */
4854 aspath_unintern(&attr
.aspath
);
4855 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4860 attr_new
= bgp_attr_intern(&attr_tmp
);
4862 attr_new
= bgp_attr_intern(&attr
);
4865 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4866 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4867 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4871 memset(&add
, 0, sizeof(union gw_addr
));
4872 if (attrhash_cmp(pi
->attr
, attr_new
)
4873 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4874 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4875 bgp_unlock_node(rn
);
4876 bgp_attr_unintern(&attr_new
);
4877 aspath_unintern(&attr
.aspath
);
4880 /* The attribute is changed. */
4881 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4883 /* Rewrite BGP route information. */
4884 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4885 bgp_path_info_restore(rn
, pi
);
4887 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4888 bgp_attr_unintern(&pi
->attr
);
4889 pi
->attr
= attr_new
;
4890 pi
->uptime
= bgp_clock();
4893 label
= decode_label(&pi
->extra
->label
[0]);
4896 /* Process change. */
4897 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4898 bgp_process(bgp
, rn
, afi
, safi
);
4900 if (SAFI_MPLS_VPN
== safi
4901 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4902 vpn_leak_to_vrf_update(bgp
, pi
);
4905 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4906 pi
->attr
, afi
, safi
, pi
->type
,
4907 pi
->sub_type
, &label
);
4909 bgp_unlock_node(rn
);
4910 aspath_unintern(&attr
.aspath
);
4916 /* Make new BGP info. */
4917 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4919 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4920 new->extra
= bgp_path_info_extra_new();
4922 new->extra
->label
[0] = bgp_static
->label
;
4923 new->extra
->num_labels
= num_labels
;
4926 label
= decode_label(&bgp_static
->label
);
4929 /* Aggregate address increment. */
4930 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4932 /* Register new BGP information. */
4933 bgp_path_info_add(rn
, new);
4934 /* route_node_get lock */
4935 bgp_unlock_node(rn
);
4937 /* Process change. */
4938 bgp_process(bgp
, rn
, afi
, safi
);
4940 if (SAFI_MPLS_VPN
== safi
4941 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4942 vpn_leak_to_vrf_update(bgp
, new);
4945 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4946 safi
, new->type
, new->sub_type
, &label
);
4949 /* Unintern original. */
4950 aspath_unintern(&attr
.aspath
);
4953 /* Configure static BGP network. When user don't run zebra, static
4954 route should be installed as valid. */
4955 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4956 const char *ip_str
, afi_t afi
, safi_t safi
,
4957 const char *rmap
, int backdoor
, uint32_t label_index
)
4959 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4962 struct bgp_static
*bgp_static
;
4963 struct bgp_node
*rn
;
4964 uint8_t need_update
= 0;
4966 /* Convert IP prefix string to struct prefix. */
4967 ret
= str2prefix(ip_str
, &p
);
4969 vty_out(vty
, "%% Malformed prefix\n");
4970 return CMD_WARNING_CONFIG_FAILED
;
4972 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4973 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4974 return CMD_WARNING_CONFIG_FAILED
;
4981 /* Set BGP static route configuration. */
4982 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4985 vty_out(vty
, "%% Can't find static route specified\n");
4986 return CMD_WARNING_CONFIG_FAILED
;
4989 bgp_static
= bgp_node_get_bgp_static_info(rn
);
4991 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4992 && (label_index
!= bgp_static
->label_index
)) {
4994 "%% label-index doesn't match static route\n");
4995 return CMD_WARNING_CONFIG_FAILED
;
4998 if ((rmap
&& bgp_static
->rmap
.name
)
4999 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5001 "%% route-map name doesn't match static route\n");
5002 return CMD_WARNING_CONFIG_FAILED
;
5005 /* Update BGP RIB. */
5006 if (!bgp_static
->backdoor
)
5007 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5009 /* Clear configuration. */
5010 bgp_static_free(bgp_static
);
5011 bgp_node_set_bgp_static_info(rn
, NULL
);
5012 bgp_unlock_node(rn
);
5013 bgp_unlock_node(rn
);
5016 /* Set BGP static route configuration. */
5017 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5019 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5021 /* Configuration change. */
5022 /* Label index cannot be changed. */
5023 if (bgp_static
->label_index
!= label_index
) {
5024 vty_out(vty
, "%% cannot change label-index\n");
5025 return CMD_WARNING_CONFIG_FAILED
;
5028 /* Check previous routes are installed into BGP. */
5029 if (bgp_static
->valid
5030 && bgp_static
->backdoor
!= backdoor
)
5033 bgp_static
->backdoor
= backdoor
;
5036 XFREE(MTYPE_ROUTE_MAP_NAME
,
5037 bgp_static
->rmap
.name
);
5038 route_map_counter_decrement(
5039 bgp_static
->rmap
.map
);
5040 bgp_static
->rmap
.name
=
5041 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5042 bgp_static
->rmap
.map
=
5043 route_map_lookup_by_name(rmap
);
5044 route_map_counter_increment(
5045 bgp_static
->rmap
.map
);
5047 XFREE(MTYPE_ROUTE_MAP_NAME
,
5048 bgp_static
->rmap
.name
);
5049 route_map_counter_decrement(
5050 bgp_static
->rmap
.map
);
5051 bgp_static
->rmap
.name
= NULL
;
5052 bgp_static
->rmap
.map
= NULL
;
5053 bgp_static
->valid
= 0;
5055 bgp_unlock_node(rn
);
5057 /* New configuration. */
5058 bgp_static
= bgp_static_new();
5059 bgp_static
->backdoor
= backdoor
;
5060 bgp_static
->valid
= 0;
5061 bgp_static
->igpmetric
= 0;
5062 bgp_static
->igpnexthop
.s_addr
= 0;
5063 bgp_static
->label_index
= label_index
;
5066 XFREE(MTYPE_ROUTE_MAP_NAME
,
5067 bgp_static
->rmap
.name
);
5068 route_map_counter_decrement(
5069 bgp_static
->rmap
.map
);
5070 bgp_static
->rmap
.name
=
5071 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5072 bgp_static
->rmap
.map
=
5073 route_map_lookup_by_name(rmap
);
5074 route_map_counter_increment(
5075 bgp_static
->rmap
.map
);
5077 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5080 bgp_static
->valid
= 1;
5082 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5084 if (!bgp_static
->backdoor
)
5085 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5091 void bgp_static_add(struct bgp
*bgp
)
5095 struct bgp_node
*rn
;
5096 struct bgp_node
*rm
;
5097 struct bgp_table
*table
;
5098 struct bgp_static
*bgp_static
;
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
,
5122 bgp_node_get_bgp_static_info(rn
), afi
,
5128 /* Called from bgp_delete(). Delete all static routes from the BGP
5130 void bgp_static_delete(struct bgp
*bgp
)
5134 struct bgp_node
*rn
;
5135 struct bgp_node
*rm
;
5136 struct bgp_table
*table
;
5137 struct bgp_static
*bgp_static
;
5139 FOREACH_AFI_SAFI (afi
, safi
)
5140 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5141 rn
= bgp_route_next(rn
)) {
5142 if (!bgp_node_has_bgp_path_info_data(rn
))
5145 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5146 || (safi
== SAFI_EVPN
)) {
5147 table
= bgp_node_get_bgp_table_info(rn
);
5149 for (rm
= bgp_table_top(table
); rm
;
5150 rm
= bgp_route_next(rm
)) {
5152 bgp_node_get_bgp_static_info(
5157 bgp_static_withdraw_safi(
5158 bgp
, &rm
->p
, AFI_IP
, safi
,
5159 (struct prefix_rd
*)&rn
->p
);
5160 bgp_static_free(bgp_static
);
5161 bgp_node_set_bgp_static_info(rn
, NULL
);
5162 bgp_unlock_node(rn
);
5165 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5166 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5167 bgp_static_free(bgp_static
);
5168 bgp_node_set_bgp_static_info(rn
, NULL
);
5169 bgp_unlock_node(rn
);
5174 void bgp_static_redo_import_check(struct bgp
*bgp
)
5178 struct bgp_node
*rn
;
5179 struct bgp_node
*rm
;
5180 struct bgp_table
*table
;
5181 struct bgp_static
*bgp_static
;
5183 /* Use this flag to force reprocessing of the route */
5184 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5185 FOREACH_AFI_SAFI (afi
, safi
) {
5186 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5187 rn
= bgp_route_next(rn
)) {
5188 if (!bgp_node_has_bgp_path_info_data(rn
))
5191 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5192 || (safi
== SAFI_EVPN
)) {
5193 table
= bgp_node_get_bgp_table_info(rn
);
5195 for (rm
= bgp_table_top(table
); rm
;
5196 rm
= bgp_route_next(rm
)) {
5198 bgp_node_get_bgp_static_info(
5200 bgp_static_update_safi(bgp
, &rm
->p
,
5205 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5206 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5211 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5214 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5217 struct bgp_table
*table
;
5218 struct bgp_node
*rn
;
5219 struct bgp_path_info
*pi
;
5221 table
= bgp
->rib
[afi
][safi
];
5222 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5223 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5224 if (pi
->peer
== bgp
->peer_self
5225 && ((pi
->type
== ZEBRA_ROUTE_BGP
5226 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5227 || (pi
->type
!= ZEBRA_ROUTE_BGP
5229 == BGP_ROUTE_REDISTRIBUTE
))) {
5230 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5232 bgp_unlink_nexthop(pi
);
5233 bgp_path_info_delete(rn
, pi
);
5234 bgp_process(bgp
, rn
, afi
, safi
);
5241 * Purge all networks and redistributed routes from routing table.
5242 * Invoked upon the instance going down.
5244 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5249 FOREACH_AFI_SAFI (afi
, safi
)
5250 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5255 * Currently this is used to set static routes for VPN and ENCAP.
5256 * I think it can probably be factored with bgp_static_set.
5258 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5259 const char *ip_str
, const char *rd_str
,
5260 const char *label_str
, const char *rmap_str
,
5261 int evpn_type
, const char *esi
, const char *gwip
,
5262 const char *ethtag
, const char *routermac
)
5264 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5267 struct prefix_rd prd
;
5268 struct bgp_node
*prn
;
5269 struct bgp_node
*rn
;
5270 struct bgp_table
*table
;
5271 struct bgp_static
*bgp_static
;
5272 mpls_label_t label
= MPLS_INVALID_LABEL
;
5273 struct prefix gw_ip
;
5275 /* validate ip prefix */
5276 ret
= str2prefix(ip_str
, &p
);
5278 vty_out(vty
, "%% Malformed prefix\n");
5279 return CMD_WARNING_CONFIG_FAILED
;
5282 if ((afi
== AFI_L2VPN
)
5283 && (bgp_build_evpn_prefix(evpn_type
,
5284 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5285 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5286 return CMD_WARNING_CONFIG_FAILED
;
5289 ret
= str2prefix_rd(rd_str
, &prd
);
5291 vty_out(vty
, "%% Malformed rd\n");
5292 return CMD_WARNING_CONFIG_FAILED
;
5296 unsigned long label_val
;
5297 label_val
= strtoul(label_str
, NULL
, 10);
5298 encode_label(label_val
, &label
);
5301 if (safi
== SAFI_EVPN
) {
5302 if (esi
&& str2esi(esi
, NULL
) == 0) {
5303 vty_out(vty
, "%% Malformed ESI\n");
5304 return CMD_WARNING_CONFIG_FAILED
;
5306 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5307 vty_out(vty
, "%% Malformed Router MAC\n");
5308 return CMD_WARNING_CONFIG_FAILED
;
5311 memset(&gw_ip
, 0, sizeof(struct prefix
));
5312 ret
= str2prefix(gwip
, &gw_ip
);
5314 vty_out(vty
, "%% Malformed GatewayIp\n");
5315 return CMD_WARNING_CONFIG_FAILED
;
5317 if ((gw_ip
.family
== AF_INET
5318 && is_evpn_prefix_ipaddr_v6(
5319 (struct prefix_evpn
*)&p
))
5320 || (gw_ip
.family
== AF_INET6
5321 && is_evpn_prefix_ipaddr_v4(
5322 (struct prefix_evpn
*)&p
))) {
5324 "%% GatewayIp family differs with IP prefix\n");
5325 return CMD_WARNING_CONFIG_FAILED
;
5329 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5330 if (!bgp_node_has_bgp_path_info_data(prn
))
5331 bgp_node_set_bgp_table_info(prn
,
5332 bgp_table_init(bgp
, afi
, safi
));
5333 table
= bgp_node_get_bgp_table_info(prn
);
5335 rn
= bgp_node_get(table
, &p
);
5337 if (bgp_node_has_bgp_path_info_data(rn
)) {
5338 vty_out(vty
, "%% Same network configuration exists\n");
5339 bgp_unlock_node(rn
);
5341 /* New configuration. */
5342 bgp_static
= bgp_static_new();
5343 bgp_static
->backdoor
= 0;
5344 bgp_static
->valid
= 0;
5345 bgp_static
->igpmetric
= 0;
5346 bgp_static
->igpnexthop
.s_addr
= 0;
5347 bgp_static
->label
= label
;
5348 bgp_static
->prd
= prd
;
5351 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5352 route_map_counter_decrement(bgp_static
->rmap
.map
);
5353 bgp_static
->rmap
.name
=
5354 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5355 bgp_static
->rmap
.map
=
5356 route_map_lookup_by_name(rmap_str
);
5357 route_map_counter_increment(bgp_static
->rmap
.map
);
5360 if (safi
== SAFI_EVPN
) {
5362 bgp_static
->eth_s_id
=
5364 sizeof(struct eth_segment_id
));
5365 str2esi(esi
, bgp_static
->eth_s_id
);
5368 bgp_static
->router_mac
=
5369 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5370 (void)prefix_str2mac(routermac
,
5371 bgp_static
->router_mac
);
5374 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5376 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5378 bgp_static
->valid
= 1;
5379 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5385 /* Configure static BGP network. */
5386 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5387 const char *ip_str
, const char *rd_str
,
5388 const char *label_str
, int evpn_type
, const char *esi
,
5389 const char *gwip
, const char *ethtag
)
5391 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5394 struct prefix_rd prd
;
5395 struct bgp_node
*prn
;
5396 struct bgp_node
*rn
;
5397 struct bgp_table
*table
;
5398 struct bgp_static
*bgp_static
;
5399 mpls_label_t label
= MPLS_INVALID_LABEL
;
5401 /* Convert IP prefix string to struct prefix. */
5402 ret
= str2prefix(ip_str
, &p
);
5404 vty_out(vty
, "%% Malformed prefix\n");
5405 return CMD_WARNING_CONFIG_FAILED
;
5408 if ((afi
== AFI_L2VPN
)
5409 && (bgp_build_evpn_prefix(evpn_type
,
5410 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5411 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5412 return CMD_WARNING_CONFIG_FAILED
;
5414 ret
= str2prefix_rd(rd_str
, &prd
);
5416 vty_out(vty
, "%% Malformed rd\n");
5417 return CMD_WARNING_CONFIG_FAILED
;
5421 unsigned long label_val
;
5422 label_val
= strtoul(label_str
, NULL
, 10);
5423 encode_label(label_val
, &label
);
5426 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5427 if (!bgp_node_has_bgp_path_info_data(prn
))
5428 bgp_node_set_bgp_table_info(prn
,
5429 bgp_table_init(bgp
, afi
, safi
));
5431 bgp_unlock_node(prn
);
5432 table
= bgp_node_get_bgp_table_info(prn
);
5434 rn
= bgp_node_lookup(table
, &p
);
5437 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5439 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5440 bgp_static_free(bgp_static
);
5441 bgp_node_set_bgp_static_info(rn
, NULL
);
5442 bgp_unlock_node(rn
);
5443 bgp_unlock_node(rn
);
5445 vty_out(vty
, "%% Can't find the route\n");
5450 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5451 const char *rmap_name
)
5453 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5454 struct bgp_rmap
*rmap
;
5456 rmap
= &bgp
->table_map
[afi
][safi
];
5458 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5459 route_map_counter_decrement(rmap
->map
);
5460 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5461 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5462 route_map_counter_increment(rmap
->map
);
5464 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5465 route_map_counter_decrement(rmap
->map
);
5470 if (bgp_fibupd_safi(safi
))
5471 bgp_zebra_announce_table(bgp
, afi
, safi
);
5476 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5477 const char *rmap_name
)
5479 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5480 struct bgp_rmap
*rmap
;
5482 rmap
= &bgp
->table_map
[afi
][safi
];
5483 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5484 route_map_counter_decrement(rmap
->map
);
5488 if (bgp_fibupd_safi(safi
))
5489 bgp_zebra_announce_table(bgp
, afi
, safi
);
5494 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5497 if (bgp
->table_map
[afi
][safi
].name
) {
5498 vty_out(vty
, " table-map %s\n",
5499 bgp
->table_map
[afi
][safi
].name
);
5503 DEFUN (bgp_table_map
,
5506 "BGP table to RIB route download filter\n"
5507 "Name of the route map\n")
5510 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5511 argv
[idx_word
]->arg
);
5513 DEFUN (no_bgp_table_map
,
5514 no_bgp_table_map_cmd
,
5515 "no table-map WORD",
5517 "BGP table to RIB route download filter\n"
5518 "Name of the route map\n")
5521 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5522 argv
[idx_word
]->arg
);
5528 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5529 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5530 backdoor$backdoor}]",
5532 "Specify a network to announce via BGP\n"
5537 "Route-map to modify the attributes\n"
5538 "Name of the route map\n"
5539 "Label index to associate with the prefix\n"
5540 "Label index value\n"
5541 "Specify a BGP backdoor route\n")
5543 char addr_prefix_str
[BUFSIZ
];
5548 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5551 vty_out(vty
, "%% Inconsistent address and mask\n");
5552 return CMD_WARNING_CONFIG_FAILED
;
5556 return bgp_static_set(
5557 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5558 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5559 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5562 DEFPY(ipv6_bgp_network
,
5563 ipv6_bgp_network_cmd
,
5564 "[no] network X:X::X:X/M$prefix \
5565 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5567 "Specify a network to announce via BGP\n"
5569 "Route-map to modify the attributes\n"
5570 "Name of the route map\n"
5571 "Label index to associate with the prefix\n"
5572 "Label index value\n")
5574 return bgp_static_set(
5575 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5576 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5579 static struct bgp_aggregate
*bgp_aggregate_new(void)
5581 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5584 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5586 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5589 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5590 struct aspath
*aspath
,
5591 struct community
*comm
,
5592 struct ecommunity
*ecomm
,
5593 struct lcommunity
*lcomm
)
5595 static struct aspath
*ae
= NULL
;
5598 ae
= aspath_empty();
5603 if (origin
!= pi
->attr
->origin
)
5606 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5609 if (!community_cmp(pi
->attr
->community
, comm
))
5612 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5615 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5618 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5624 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5625 struct prefix
*p
, uint8_t origin
,
5626 struct aspath
*aspath
,
5627 struct community
*community
,
5628 struct ecommunity
*ecommunity
,
5629 struct lcommunity
*lcommunity
,
5630 uint8_t atomic_aggregate
,
5631 struct bgp_aggregate
*aggregate
)
5633 struct bgp_node
*rn
;
5634 struct bgp_table
*table
;
5635 struct bgp_path_info
*pi
, *orig
, *new;
5637 table
= bgp
->rib
[afi
][safi
];
5639 rn
= bgp_node_get(table
, p
);
5641 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5642 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5643 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5646 if (aggregate
->count
> 0) {
5648 * If the aggregate information has not changed
5649 * no need to re-install it again.
5651 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5652 ecommunity
, lcommunity
)) {
5653 bgp_unlock_node(rn
);
5656 aspath_free(aspath
);
5658 community_free(&community
);
5660 ecommunity_free(&ecommunity
);
5662 lcommunity_free(&lcommunity
);
5668 * Mark the old as unusable
5671 bgp_path_info_delete(rn
, pi
);
5673 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5675 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5676 community
, ecommunity
,
5681 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5683 bgp_path_info_add(rn
, new);
5684 bgp_process(bgp
, rn
, afi
, safi
);
5686 for (pi
= orig
; pi
; pi
= pi
->next
)
5687 if (pi
->peer
== bgp
->peer_self
5688 && pi
->type
== ZEBRA_ROUTE_BGP
5689 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5692 /* Withdraw static BGP route from routing table. */
5694 bgp_path_info_delete(rn
, pi
);
5695 bgp_process(bgp
, rn
, afi
, safi
);
5699 bgp_unlock_node(rn
);
5702 /* Update an aggregate as routes are added/removed from the BGP table */
5703 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5704 afi_t afi
, safi_t safi
,
5705 struct bgp_aggregate
*aggregate
)
5707 struct bgp_table
*table
;
5708 struct bgp_node
*top
;
5709 struct bgp_node
*rn
;
5711 struct aspath
*aspath
= NULL
;
5712 struct community
*community
= NULL
;
5713 struct ecommunity
*ecommunity
= NULL
;
5714 struct lcommunity
*lcommunity
= NULL
;
5715 struct bgp_path_info
*pi
;
5716 unsigned long match
= 0;
5717 uint8_t atomic_aggregate
= 0;
5719 /* ORIGIN attribute: If at least one route among routes that are
5720 aggregated has ORIGIN with the value INCOMPLETE, then the
5721 aggregated route must have the ORIGIN attribute with the value
5722 INCOMPLETE. Otherwise, if at least one route among routes that
5723 are aggregated has ORIGIN with the value EGP, then the aggregated
5724 route must have the origin attribute with the value EGP. In all
5725 other case the value of the ORIGIN attribute of the aggregated
5726 route is INTERNAL. */
5727 origin
= BGP_ORIGIN_IGP
;
5729 table
= bgp
->rib
[afi
][safi
];
5731 top
= bgp_node_get(table
, p
);
5732 for (rn
= bgp_node_get(table
, p
); rn
;
5733 rn
= bgp_route_next_until(rn
, top
)) {
5734 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5739 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5740 if (BGP_PATH_HOLDDOWN(pi
))
5744 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5745 atomic_aggregate
= 1;
5747 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5751 * summary-only aggregate route suppress
5752 * aggregated route announcements.
5754 if (aggregate
->summary_only
) {
5755 (bgp_path_info_extra_get(pi
))->suppress
++;
5756 bgp_path_info_set_flag(rn
, pi
,
5757 BGP_PATH_ATTR_CHANGED
);
5764 * If at least one route among routes that are
5765 * aggregated has ORIGIN with the value INCOMPLETE,
5766 * then the aggregated route MUST have the ORIGIN
5767 * attribute with the value INCOMPLETE. Otherwise, if
5768 * at least one route among routes that are aggregated
5769 * has ORIGIN with the value EGP, then the aggregated
5770 * route MUST have the ORIGIN attribute with the value
5773 switch (pi
->attr
->origin
) {
5774 case BGP_ORIGIN_INCOMPLETE
:
5775 aggregate
->incomplete_origin_count
++;
5777 case BGP_ORIGIN_EGP
:
5778 aggregate
->egp_origin_count
++;
5786 if (!aggregate
->as_set
)
5790 * as-set aggregate route generate origin, as path,
5791 * and community aggregation.
5793 /* Compute aggregate route's as-path.
5795 bgp_compute_aggregate_aspath(aggregate
,
5798 /* Compute aggregate route's community.
5800 if (pi
->attr
->community
)
5801 bgp_compute_aggregate_community(
5803 pi
->attr
->community
);
5805 /* Compute aggregate route's extended community.
5807 if (pi
->attr
->ecommunity
)
5808 bgp_compute_aggregate_ecommunity(
5810 pi
->attr
->ecommunity
);
5812 /* Compute aggregate route's large community.
5814 if (pi
->attr
->lcommunity
)
5815 bgp_compute_aggregate_lcommunity(
5817 pi
->attr
->lcommunity
);
5820 bgp_process(bgp
, rn
, afi
, safi
);
5822 bgp_unlock_node(top
);
5825 if (aggregate
->incomplete_origin_count
> 0)
5826 origin
= BGP_ORIGIN_INCOMPLETE
;
5827 else if (aggregate
->egp_origin_count
> 0)
5828 origin
= BGP_ORIGIN_EGP
;
5830 if (aggregate
->as_set
) {
5831 if (aggregate
->aspath
)
5832 /* Retrieve aggregate route's as-path.
5834 aspath
= aspath_dup(aggregate
->aspath
);
5836 if (aggregate
->community
)
5837 /* Retrieve aggregate route's community.
5839 community
= community_dup(aggregate
->community
);
5841 if (aggregate
->ecommunity
)
5842 /* Retrieve aggregate route's ecommunity.
5844 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
5846 if (aggregate
->lcommunity
)
5847 /* Retrieve aggregate route's lcommunity.
5849 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
5852 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5853 ecommunity
, lcommunity
, atomic_aggregate
,
5857 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5858 safi_t safi
, struct bgp_aggregate
*aggregate
)
5860 struct bgp_table
*table
;
5861 struct bgp_node
*top
;
5862 struct bgp_node
*rn
;
5863 struct bgp_path_info
*pi
;
5864 unsigned long match
;
5866 table
= bgp
->rib
[afi
][safi
];
5868 /* If routes exists below this node, generate aggregate routes. */
5869 top
= bgp_node_get(table
, p
);
5870 for (rn
= bgp_node_get(table
, p
); rn
;
5871 rn
= bgp_route_next_until(rn
, top
)) {
5872 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5876 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5877 if (BGP_PATH_HOLDDOWN(pi
))
5880 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5883 if (aggregate
->summary_only
&& pi
->extra
) {
5884 pi
->extra
->suppress
--;
5886 if (pi
->extra
->suppress
== 0) {
5887 bgp_path_info_set_flag(
5888 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5894 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
5895 aggregate
->incomplete_origin_count
--;
5896 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
5897 aggregate
->egp_origin_count
--;
5899 if (aggregate
->as_set
) {
5900 /* Remove as-path from aggregate.
5902 bgp_remove_aspath_from_aggregate(
5906 if (pi
->attr
->community
)
5907 /* Remove community from aggregate.
5909 bgp_remove_community_from_aggregate(
5911 pi
->attr
->community
);
5913 if (pi
->attr
->ecommunity
)
5914 /* Remove ecommunity from aggregate.
5916 bgp_remove_ecommunity_from_aggregate(
5918 pi
->attr
->ecommunity
);
5920 if (pi
->attr
->lcommunity
)
5921 /* Remove lcommunity from aggregate.
5923 bgp_remove_lcommunity_from_aggregate(
5925 pi
->attr
->lcommunity
);
5930 /* If this node was suppressed, process the change. */
5932 bgp_process(bgp
, rn
, afi
, safi
);
5934 bgp_unlock_node(top
);
5937 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
5938 struct bgp_path_info
*pinew
, afi_t afi
,
5940 struct bgp_aggregate
*aggregate
)
5943 struct aspath
*aspath
= NULL
;
5944 uint8_t atomic_aggregate
= 0;
5945 struct community
*community
= NULL
;
5946 struct ecommunity
*ecommunity
= NULL
;
5947 struct lcommunity
*lcommunity
= NULL
;
5949 /* ORIGIN attribute: If at least one route among routes that are
5950 * aggregated has ORIGIN with the value INCOMPLETE, then the
5951 * aggregated route must have the ORIGIN attribute with the value
5952 * INCOMPLETE. Otherwise, if at least one route among routes that
5953 * are aggregated has ORIGIN with the value EGP, then the aggregated
5954 * route must have the origin attribute with the value EGP. In all
5955 * other case the value of the ORIGIN attribute of the aggregated
5956 * route is INTERNAL.
5958 origin
= BGP_ORIGIN_IGP
;
5962 if (aggregate
->summary_only
)
5963 (bgp_path_info_extra_get(pinew
))->suppress
++;
5965 switch (pinew
->attr
->origin
) {
5966 case BGP_ORIGIN_INCOMPLETE
:
5967 aggregate
->incomplete_origin_count
++;
5969 case BGP_ORIGIN_EGP
:
5970 aggregate
->egp_origin_count
++;
5978 if (aggregate
->incomplete_origin_count
> 0)
5979 origin
= BGP_ORIGIN_INCOMPLETE
;
5980 else if (aggregate
->egp_origin_count
> 0)
5981 origin
= BGP_ORIGIN_EGP
;
5983 if (aggregate
->as_set
) {
5984 /* Compute aggregate route's as-path.
5986 bgp_compute_aggregate_aspath(aggregate
,
5987 pinew
->attr
->aspath
);
5989 /* Compute aggregate route's community.
5991 if (pinew
->attr
->community
)
5992 bgp_compute_aggregate_community(
5994 pinew
->attr
->community
);
5996 /* Compute aggregate route's extended community.
5998 if (pinew
->attr
->ecommunity
)
5999 bgp_compute_aggregate_ecommunity(
6001 pinew
->attr
->ecommunity
);
6003 /* Compute aggregate route's large community.
6005 if (pinew
->attr
->lcommunity
)
6006 bgp_compute_aggregate_lcommunity(
6008 pinew
->attr
->lcommunity
);
6010 /* Retrieve aggregate route's as-path.
6012 if (aggregate
->aspath
)
6013 aspath
= aspath_dup(aggregate
->aspath
);
6015 /* Retrieve aggregate route's community.
6017 if (aggregate
->community
)
6018 community
= community_dup(aggregate
->community
);
6020 /* Retrieve aggregate route's ecommunity.
6022 if (aggregate
->ecommunity
)
6023 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6025 /* Retrieve aggregate route's lcommunity.
6027 if (aggregate
->lcommunity
)
6028 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6031 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6032 aspath
, community
, ecommunity
,
6033 lcommunity
, atomic_aggregate
, aggregate
);
6036 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6038 struct bgp_path_info
*pi
,
6039 struct bgp_aggregate
*aggregate
,
6040 struct prefix
*aggr_p
)
6043 struct aspath
*aspath
= NULL
;
6044 uint8_t atomic_aggregate
= 0;
6045 struct community
*community
= NULL
;
6046 struct ecommunity
*ecommunity
= NULL
;
6047 struct lcommunity
*lcommunity
= NULL
;
6048 unsigned long match
= 0;
6050 if (BGP_PATH_HOLDDOWN(pi
))
6053 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6056 if (aggregate
->summary_only
6058 && pi
->extra
->suppress
> 0) {
6059 pi
->extra
->suppress
--;
6061 if (pi
->extra
->suppress
== 0) {
6062 bgp_path_info_set_flag(pi
->net
, pi
,
6063 BGP_PATH_ATTR_CHANGED
);
6068 if (aggregate
->count
> 0)
6071 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6072 aggregate
->incomplete_origin_count
--;
6073 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6074 aggregate
->egp_origin_count
--;
6076 if (aggregate
->as_set
) {
6077 /* Remove as-path from aggregate.
6079 bgp_remove_aspath_from_aggregate(aggregate
,
6082 if (pi
->attr
->community
)
6083 /* Remove community from aggregate.
6085 bgp_remove_community_from_aggregate(
6087 pi
->attr
->community
);
6089 if (pi
->attr
->ecommunity
)
6090 /* Remove ecommunity from aggregate.
6092 bgp_remove_ecommunity_from_aggregate(
6094 pi
->attr
->ecommunity
);
6096 if (pi
->attr
->lcommunity
)
6097 /* Remove lcommunity from aggregate.
6099 bgp_remove_lcommunity_from_aggregate(
6101 pi
->attr
->lcommunity
);
6104 /* If this node was suppressed, process the change. */
6106 bgp_process(bgp
, pi
->net
, afi
, safi
);
6108 origin
= BGP_ORIGIN_IGP
;
6109 if (aggregate
->incomplete_origin_count
> 0)
6110 origin
= BGP_ORIGIN_INCOMPLETE
;
6111 else if (aggregate
->egp_origin_count
> 0)
6112 origin
= BGP_ORIGIN_EGP
;
6114 if (aggregate
->as_set
) {
6115 /* Retrieve aggregate route's as-path.
6117 if (aggregate
->aspath
)
6118 aspath
= aspath_dup(aggregate
->aspath
);
6120 /* Retrieve aggregate route's community.
6122 if (aggregate
->community
)
6123 community
= community_dup(aggregate
->community
);
6125 /* Retrieve aggregate route's ecommunity.
6127 if (aggregate
->ecommunity
)
6128 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6130 /* Retrieve aggregate route's lcommunity.
6132 if (aggregate
->lcommunity
)
6133 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6136 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6137 aspath
, community
, ecommunity
,
6138 lcommunity
, atomic_aggregate
, aggregate
);
6141 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6142 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6144 struct bgp_node
*child
;
6145 struct bgp_node
*rn
;
6146 struct bgp_aggregate
*aggregate
;
6147 struct bgp_table
*table
;
6149 table
= bgp
->aggregate
[afi
][safi
];
6151 /* No aggregates configured. */
6152 if (bgp_table_top_nolock(table
) == NULL
)
6155 if (p
->prefixlen
== 0)
6158 if (BGP_PATH_HOLDDOWN(pi
))
6161 child
= bgp_node_get(table
, p
);
6163 /* Aggregate address configuration check. */
6164 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6165 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6166 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6167 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6171 bgp_unlock_node(child
);
6174 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6175 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6177 struct bgp_node
*child
;
6178 struct bgp_node
*rn
;
6179 struct bgp_aggregate
*aggregate
;
6180 struct bgp_table
*table
;
6182 table
= bgp
->aggregate
[afi
][safi
];
6184 /* No aggregates configured. */
6185 if (bgp_table_top_nolock(table
) == NULL
)
6188 if (p
->prefixlen
== 0)
6191 child
= bgp_node_get(table
, p
);
6193 /* Aggregate address configuration check. */
6194 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6195 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6196 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6197 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6198 del
, aggregate
, &rn
->p
);
6201 bgp_unlock_node(child
);
6204 /* Aggregate route attribute. */
6205 #define AGGREGATE_SUMMARY_ONLY 1
6206 #define AGGREGATE_AS_SET 1
6208 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6209 afi_t afi
, safi_t safi
)
6211 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6214 struct bgp_node
*rn
;
6215 struct bgp_aggregate
*aggregate
;
6217 /* Convert string to prefix structure. */
6218 ret
= str2prefix(prefix_str
, &p
);
6220 vty_out(vty
, "Malformed prefix\n");
6221 return CMD_WARNING_CONFIG_FAILED
;
6225 /* Old configuration check. */
6226 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6229 "%% There is no aggregate-address configuration.\n");
6230 return CMD_WARNING_CONFIG_FAILED
;
6233 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6234 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6235 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6236 NULL
, NULL
, 0, aggregate
);
6238 /* Unlock aggregate address configuration. */
6239 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6241 if (aggregate
->community
)
6242 community_free(&aggregate
->community
);
6244 if (aggregate
->community_hash
) {
6245 /* Delete all communities in the hash.
6247 hash_clean(aggregate
->community_hash
,
6248 bgp_aggr_community_remove
);
6249 /* Free up the community_hash.
6251 hash_free(aggregate
->community_hash
);
6254 if (aggregate
->ecommunity
)
6255 ecommunity_free(&aggregate
->ecommunity
);
6257 if (aggregate
->ecommunity_hash
) {
6258 /* Delete all ecommunities in the hash.
6260 hash_clean(aggregate
->ecommunity_hash
,
6261 bgp_aggr_ecommunity_remove
);
6262 /* Free up the ecommunity_hash.
6264 hash_free(aggregate
->ecommunity_hash
);
6267 if (aggregate
->lcommunity
)
6268 lcommunity_free(&aggregate
->lcommunity
);
6270 if (aggregate
->lcommunity_hash
) {
6271 /* Delete all lcommunities in the hash.
6273 hash_clean(aggregate
->lcommunity_hash
,
6274 bgp_aggr_lcommunity_remove
);
6275 /* Free up the lcommunity_hash.
6277 hash_free(aggregate
->lcommunity_hash
);
6280 if (aggregate
->aspath
)
6281 aspath_free(aggregate
->aspath
);
6283 if (aggregate
->aspath_hash
) {
6284 /* Delete all as-paths in the hash.
6286 hash_clean(aggregate
->aspath_hash
,
6287 bgp_aggr_aspath_remove
);
6288 /* Free up the aspath_hash.
6290 hash_free(aggregate
->aspath_hash
);
6293 bgp_aggregate_free(aggregate
);
6294 bgp_unlock_node(rn
);
6295 bgp_unlock_node(rn
);
6300 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6301 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6303 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6306 struct bgp_node
*rn
;
6307 struct bgp_aggregate
*aggregate
;
6309 /* Convert string to prefix structure. */
6310 ret
= str2prefix(prefix_str
, &p
);
6312 vty_out(vty
, "Malformed prefix\n");
6313 return CMD_WARNING_CONFIG_FAILED
;
6317 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6318 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6319 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6321 return CMD_WARNING_CONFIG_FAILED
;
6324 /* Old configuration check. */
6325 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6327 if (bgp_node_has_bgp_path_info_data(rn
)) {
6328 vty_out(vty
, "There is already same aggregate network.\n");
6329 /* try to remove the old entry */
6330 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6332 vty_out(vty
, "Error deleting aggregate.\n");
6333 bgp_unlock_node(rn
);
6334 return CMD_WARNING_CONFIG_FAILED
;
6338 /* Make aggregate address structure. */
6339 aggregate
= bgp_aggregate_new();
6340 aggregate
->summary_only
= summary_only
;
6341 aggregate
->as_set
= as_set
;
6342 aggregate
->safi
= safi
;
6343 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6345 /* Aggregate address insert into BGP routing table. */
6346 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6351 DEFUN (aggregate_address
,
6352 aggregate_address_cmd
,
6353 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6354 "Configure BGP aggregate entries\n"
6355 "Aggregate prefix\n"
6356 "Generate AS set path information\n"
6357 "Filter more specific routes from updates\n"
6358 "Filter more specific routes from updates\n"
6359 "Generate AS set path information\n")
6362 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6363 char *prefix
= argv
[idx
]->arg
;
6365 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6367 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6368 ? AGGREGATE_SUMMARY_ONLY
6371 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6372 summary_only
, as_set
);
6375 DEFUN (aggregate_address_mask
,
6376 aggregate_address_mask_cmd
,
6377 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6378 "Configure BGP aggregate entries\n"
6379 "Aggregate address\n"
6381 "Generate AS set path information\n"
6382 "Filter more specific routes from updates\n"
6383 "Filter more specific routes from updates\n"
6384 "Generate AS set path information\n")
6387 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6388 char *prefix
= argv
[idx
]->arg
;
6389 char *mask
= argv
[idx
+ 1]->arg
;
6391 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6393 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6394 ? AGGREGATE_SUMMARY_ONLY
6397 char prefix_str
[BUFSIZ
];
6398 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6401 vty_out(vty
, "%% Inconsistent address and mask\n");
6402 return CMD_WARNING_CONFIG_FAILED
;
6405 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6406 summary_only
, as_set
);
6409 DEFUN (no_aggregate_address
,
6410 no_aggregate_address_cmd
,
6411 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6413 "Configure BGP aggregate entries\n"
6414 "Aggregate prefix\n"
6415 "Generate AS set path information\n"
6416 "Filter more specific routes from updates\n"
6417 "Filter more specific routes from updates\n"
6418 "Generate AS set path information\n")
6421 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6422 char *prefix
= argv
[idx
]->arg
;
6423 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6426 DEFUN (no_aggregate_address_mask
,
6427 no_aggregate_address_mask_cmd
,
6428 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6430 "Configure BGP aggregate entries\n"
6431 "Aggregate address\n"
6433 "Generate AS set path information\n"
6434 "Filter more specific routes from updates\n"
6435 "Filter more specific routes from updates\n"
6436 "Generate AS set path information\n")
6439 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6440 char *prefix
= argv
[idx
]->arg
;
6441 char *mask
= argv
[idx
+ 1]->arg
;
6443 char prefix_str
[BUFSIZ
];
6444 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6447 vty_out(vty
, "%% Inconsistent address and mask\n");
6448 return CMD_WARNING_CONFIG_FAILED
;
6451 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6454 DEFUN (ipv6_aggregate_address
,
6455 ipv6_aggregate_address_cmd
,
6456 "aggregate-address X:X::X:X/M [summary-only]",
6457 "Configure BGP aggregate entries\n"
6458 "Aggregate prefix\n"
6459 "Filter more specific routes from updates\n")
6462 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6463 char *prefix
= argv
[idx
]->arg
;
6464 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6465 ? AGGREGATE_SUMMARY_ONLY
6467 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6471 DEFUN (no_ipv6_aggregate_address
,
6472 no_ipv6_aggregate_address_cmd
,
6473 "no aggregate-address X:X::X:X/M [summary-only]",
6475 "Configure BGP aggregate entries\n"
6476 "Aggregate prefix\n"
6477 "Filter more specific routes from updates\n")
6480 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6481 char *prefix
= argv
[idx
]->arg
;
6482 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6485 /* Redistribute route treatment. */
6486 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6487 const union g_addr
*nexthop
, ifindex_t ifindex
,
6488 enum nexthop_types_t nhtype
, uint32_t metric
,
6489 uint8_t type
, unsigned short instance
,
6492 struct bgp_path_info
*new;
6493 struct bgp_path_info
*bpi
;
6494 struct bgp_path_info rmap_path
;
6495 struct bgp_node
*bn
;
6497 struct attr
*new_attr
;
6500 struct bgp_redist
*red
;
6502 /* Make default attribute. */
6503 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6506 case NEXTHOP_TYPE_IFINDEX
:
6508 case NEXTHOP_TYPE_IPV4
:
6509 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6510 attr
.nexthop
= nexthop
->ipv4
;
6512 case NEXTHOP_TYPE_IPV6
:
6513 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6514 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6515 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6517 case NEXTHOP_TYPE_BLACKHOLE
:
6518 switch (p
->family
) {
6520 attr
.nexthop
.s_addr
= INADDR_ANY
;
6523 memset(&attr
.mp_nexthop_global
, 0,
6524 sizeof(attr
.mp_nexthop_global
));
6525 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6530 attr
.nh_ifindex
= ifindex
;
6533 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6536 afi
= family2afi(p
->family
);
6538 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6540 struct attr attr_new
;
6542 /* Copy attribute for modification. */
6543 bgp_attr_dup(&attr_new
, &attr
);
6545 if (red
->redist_metric_flag
)
6546 attr_new
.med
= red
->redist_metric
;
6548 /* Apply route-map. */
6549 if (red
->rmap
.name
) {
6550 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6551 rmap_path
.peer
= bgp
->peer_self
;
6552 rmap_path
.attr
= &attr_new
;
6554 SET_FLAG(bgp
->peer_self
->rmap_type
,
6555 PEER_RMAP_TYPE_REDISTRIBUTE
);
6557 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6560 bgp
->peer_self
->rmap_type
= 0;
6562 if (ret
== RMAP_DENYMATCH
) {
6563 /* Free uninterned attribute. */
6564 bgp_attr_flush(&attr_new
);
6566 /* Unintern original. */
6567 aspath_unintern(&attr
.aspath
);
6568 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6573 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6574 bgp_attr_add_gshut_community(&attr_new
);
6576 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6577 SAFI_UNICAST
, p
, NULL
);
6579 new_attr
= bgp_attr_intern(&attr_new
);
6581 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6583 if (bpi
->peer
== bgp
->peer_self
6584 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6588 /* Ensure the (source route) type is updated. */
6590 if (attrhash_cmp(bpi
->attr
, new_attr
)
6591 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6592 bgp_attr_unintern(&new_attr
);
6593 aspath_unintern(&attr
.aspath
);
6594 bgp_unlock_node(bn
);
6597 /* The attribute is changed. */
6598 bgp_path_info_set_flag(bn
, bpi
,
6599 BGP_PATH_ATTR_CHANGED
);
6601 /* Rewrite BGP route information. */
6602 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6603 bgp_path_info_restore(bn
, bpi
);
6605 bgp_aggregate_decrement(
6606 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6607 bgp_attr_unintern(&bpi
->attr
);
6608 bpi
->attr
= new_attr
;
6609 bpi
->uptime
= bgp_clock();
6611 /* Process change. */
6612 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6614 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6615 bgp_unlock_node(bn
);
6616 aspath_unintern(&attr
.aspath
);
6618 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6620 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6622 vpn_leak_from_vrf_update(
6623 bgp_get_default(), bgp
, bpi
);
6629 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6630 bgp
->peer_self
, new_attr
, bn
);
6631 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6633 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6634 bgp_path_info_add(bn
, new);
6635 bgp_unlock_node(bn
);
6636 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6638 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6639 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6641 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6645 /* Unintern original. */
6646 aspath_unintern(&attr
.aspath
);
6649 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6650 unsigned short instance
)
6653 struct bgp_node
*rn
;
6654 struct bgp_path_info
*pi
;
6655 struct bgp_redist
*red
;
6657 afi
= family2afi(p
->family
);
6659 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6661 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6662 SAFI_UNICAST
, p
, NULL
);
6664 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6665 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6669 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6670 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6672 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6675 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6676 bgp_path_info_delete(rn
, pi
);
6677 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6679 bgp_unlock_node(rn
);
6683 /* Withdraw specified route type's route. */
6684 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6685 unsigned short instance
)
6687 struct bgp_node
*rn
;
6688 struct bgp_path_info
*pi
;
6689 struct bgp_table
*table
;
6691 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6693 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6694 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6695 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6696 && pi
->instance
== instance
)
6700 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6701 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6703 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6706 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6708 bgp_path_info_delete(rn
, pi
);
6709 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6714 /* Static function to display route. */
6715 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6722 if (p
->family
== AF_INET
) {
6726 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6729 json_object_string_add(json
, "prefix",
6730 inet_ntop(p
->family
,
6733 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6734 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6735 json_object_string_add(json
, "network", buf2
);
6737 } else if (p
->family
== AF_ETHERNET
) {
6738 prefix2str(p
, buf
, PREFIX_STRLEN
);
6739 len
= vty_out(vty
, "%s", buf
);
6740 } else if (p
->family
== AF_EVPN
) {
6744 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6747 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6748 } else if (p
->family
== AF_FLOWSPEC
) {
6749 route_vty_out_flowspec(vty
, p
, NULL
,
6751 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6752 NLRI_STRING_FORMAT_MIN
, json
);
6757 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6760 json_object_string_add(json
, "prefix",
6761 inet_ntop(p
->family
,
6764 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6765 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6766 json_object_string_add(json
, "network", buf2
);
6773 vty_out(vty
, "\n%*s", 20, " ");
6775 vty_out(vty
, "%*s", len
, " ");
6779 enum bgp_display_type
{
6783 /* Print the short form route status for a bgp_path_info */
6784 static void route_vty_short_status_out(struct vty
*vty
,
6785 struct bgp_path_info
*path
,
6786 json_object
*json_path
)
6790 /* Route status display. */
6791 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6792 json_object_boolean_true_add(json_path
, "removed");
6794 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6795 json_object_boolean_true_add(json_path
, "stale");
6797 if (path
->extra
&& path
->extra
->suppress
)
6798 json_object_boolean_true_add(json_path
, "suppressed");
6800 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6801 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6802 json_object_boolean_true_add(json_path
, "valid");
6805 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6806 json_object_boolean_true_add(json_path
, "history");
6808 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6809 json_object_boolean_true_add(json_path
, "damped");
6811 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6812 json_object_boolean_true_add(json_path
, "bestpath");
6814 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6815 json_object_boolean_true_add(json_path
, "multipath");
6817 /* Internal route. */
6818 if ((path
->peer
->as
)
6819 && (path
->peer
->as
== path
->peer
->local_as
))
6820 json_object_string_add(json_path
, "pathFrom",
6823 json_object_string_add(json_path
, "pathFrom",
6829 /* Route status display. */
6830 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6832 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6834 else if (path
->extra
&& path
->extra
->suppress
)
6836 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6837 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6843 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6845 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6847 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6849 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6854 /* Internal route. */
6855 if (path
->peer
&& (path
->peer
->as
)
6856 && (path
->peer
->as
== path
->peer
->local_as
))
6862 /* called from terminal list command */
6863 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6864 struct bgp_path_info
*path
, int display
, safi_t safi
,
6865 json_object
*json_paths
)
6868 json_object
*json_path
= NULL
;
6869 json_object
*json_nexthops
= NULL
;
6870 json_object
*json_nexthop_global
= NULL
;
6871 json_object
*json_nexthop_ll
= NULL
;
6872 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6874 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6875 bool nexthop_othervrf
= false;
6876 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6877 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6880 json_path
= json_object_new_object();
6882 /* short status lead text */
6883 route_vty_short_status_out(vty
, path
, json_path
);
6886 /* print prefix and mask */
6888 route_vty_out_route(p
, vty
, json_path
);
6890 vty_out(vty
, "%*s", 17, " ");
6892 route_vty_out_route(p
, vty
, json_path
);
6895 /* Print attribute */
6899 json_object_array_add(json_paths
, json_path
);
6907 * If vrf id of nexthop is different from that of prefix,
6908 * set up printable string to append
6910 if (path
->extra
&& path
->extra
->bgp_orig
) {
6911 const char *self
= "";
6916 nexthop_othervrf
= true;
6917 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6919 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6920 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6921 "@%s%s", VRFID_NONE_STR
, self
);
6923 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6924 path
->extra
->bgp_orig
->vrf_id
, self
);
6926 if (path
->extra
->bgp_orig
->inst_type
6927 != BGP_INSTANCE_TYPE_DEFAULT
)
6929 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6931 const char *self
= "";
6936 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6940 * For ENCAP and EVPN routes, nexthop address family is not
6941 * neccessarily the same as the prefix address family.
6942 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6943 * EVPN routes are also exchanged with a MP nexthop. Currently,
6945 * is only IPv4, the value will be present in either
6947 * attr->mp_nexthop_global_in
6949 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6952 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6956 sprintf(nexthop
, "%s",
6957 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6961 sprintf(nexthop
, "%s",
6962 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6966 sprintf(nexthop
, "?");
6971 json_nexthop_global
= json_object_new_object();
6973 json_object_string_add(json_nexthop_global
, "afi",
6974 (af
== AF_INET
) ? "ip" : "ipv6");
6975 json_object_string_add(json_nexthop_global
,
6976 (af
== AF_INET
) ? "ip" : "ipv6",
6978 json_object_boolean_true_add(json_nexthop_global
,
6981 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6982 } else if (safi
== SAFI_EVPN
) {
6984 json_nexthop_global
= json_object_new_object();
6986 json_object_string_add(json_nexthop_global
, "ip",
6987 inet_ntoa(attr
->nexthop
));
6988 json_object_string_add(json_nexthop_global
, "afi",
6990 json_object_boolean_true_add(json_nexthop_global
,
6993 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6995 } else if (safi
== SAFI_FLOWSPEC
) {
6996 if (attr
->nexthop
.s_addr
!= 0) {
6998 json_nexthop_global
= json_object_new_object();
6999 json_object_string_add(
7000 json_nexthop_global
, "ip",
7001 inet_ntoa(attr
->nexthop
));
7002 json_object_string_add(json_nexthop_global
,
7004 json_object_boolean_true_add(
7005 json_nexthop_global
,
7008 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
7011 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7013 json_nexthop_global
= json_object_new_object();
7015 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
7016 json_object_string_add(
7017 json_nexthop_global
, "ip",
7018 inet_ntoa(attr
->mp_nexthop_global_in
));
7020 json_object_string_add(
7021 json_nexthop_global
, "ip",
7022 inet_ntoa(attr
->nexthop
));
7024 json_object_string_add(json_nexthop_global
, "afi",
7026 json_object_boolean_true_add(json_nexthop_global
,
7031 snprintf(buf
, sizeof(buf
), "%s%s",
7032 inet_ntoa(attr
->nexthop
), vrf_id_str
);
7033 vty_out(vty
, "%-16s", buf
);
7038 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7043 json_nexthop_global
= json_object_new_object();
7044 json_object_string_add(
7045 json_nexthop_global
, "ip",
7046 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7048 json_object_string_add(json_nexthop_global
, "afi",
7050 json_object_string_add(json_nexthop_global
, "scope",
7053 /* We display both LL & GL if both have been
7055 if ((attr
->mp_nexthop_len
== 32)
7056 || (path
->peer
->conf_if
)) {
7057 json_nexthop_ll
= json_object_new_object();
7058 json_object_string_add(
7059 json_nexthop_ll
, "ip",
7061 &attr
->mp_nexthop_local
, buf
,
7063 json_object_string_add(json_nexthop_ll
, "afi",
7065 json_object_string_add(json_nexthop_ll
, "scope",
7068 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7069 &attr
->mp_nexthop_local
)
7071 && !attr
->mp_nexthop_prefer_global
)
7072 json_object_boolean_true_add(
7073 json_nexthop_ll
, "used");
7075 json_object_boolean_true_add(
7076 json_nexthop_global
, "used");
7078 json_object_boolean_true_add(
7079 json_nexthop_global
, "used");
7081 /* Display LL if LL/Global both in table unless
7082 * prefer-global is set */
7083 if (((attr
->mp_nexthop_len
== 32)
7084 && !attr
->mp_nexthop_prefer_global
)
7085 || (path
->peer
->conf_if
)) {
7086 if (path
->peer
->conf_if
) {
7087 len
= vty_out(vty
, "%s",
7088 path
->peer
->conf_if
);
7089 len
= 16 - len
; /* len of IPv6
7095 vty_out(vty
, "\n%*s", 36, " ");
7097 vty_out(vty
, "%*s", len
, " ");
7103 &attr
->mp_nexthop_local
,
7109 vty_out(vty
, "\n%*s", 36, " ");
7111 vty_out(vty
, "%*s", len
, " ");
7117 &attr
->mp_nexthop_global
, buf
,
7123 vty_out(vty
, "\n%*s", 36, " ");
7125 vty_out(vty
, "%*s", len
, " ");
7131 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7135 * Adding "metric" field to match with corresponding
7136 * CLI. "med" will be deprecated in future.
7138 json_object_int_add(json_path
, "med", attr
->med
);
7139 json_object_int_add(json_path
, "metric", attr
->med
);
7141 vty_out(vty
, "%10u", attr
->med
);
7142 else if (!json_paths
)
7146 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7150 * Adding "locPrf" field to match with corresponding
7151 * CLI. "localPref" will be deprecated in future.
7153 json_object_int_add(json_path
, "localpref",
7155 json_object_int_add(json_path
, "locPrf",
7158 vty_out(vty
, "%7u", attr
->local_pref
);
7159 else if (!json_paths
)
7163 json_object_int_add(json_path
, "weight", attr
->weight
);
7165 vty_out(vty
, "%7u ", attr
->weight
);
7169 json_object_string_add(
7170 json_path
, "peerId",
7171 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7179 * Adding "path" field to match with corresponding
7180 * CLI. "aspath" will be deprecated in future.
7182 json_object_string_add(json_path
, "aspath",
7184 json_object_string_add(json_path
, "path",
7187 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7192 json_object_string_add(json_path
, "origin",
7193 bgp_origin_long_str
[attr
->origin
]);
7195 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7199 json_object_boolean_true_add(json_path
,
7200 "announceNexthopSelf");
7201 if (nexthop_othervrf
) {
7202 json_object_string_add(json_path
, "nhVrfName",
7205 json_object_int_add(json_path
, "nhVrfId",
7206 ((nexthop_vrfid
== VRF_UNKNOWN
)
7208 : (int)nexthop_vrfid
));
7213 if (json_nexthop_global
|| json_nexthop_ll
) {
7214 json_nexthops
= json_object_new_array();
7216 if (json_nexthop_global
)
7217 json_object_array_add(json_nexthops
,
7218 json_nexthop_global
);
7220 if (json_nexthop_ll
)
7221 json_object_array_add(json_nexthops
,
7224 json_object_object_add(json_path
, "nexthops",
7228 json_object_array_add(json_paths
, json_path
);
7232 /* prints an additional line, indented, with VNC info, if
7234 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7235 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7240 /* called from terminal list command */
7241 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7242 safi_t safi
, bool use_json
, json_object
*json_ar
)
7244 json_object
*json_status
= NULL
;
7245 json_object
*json_net
= NULL
;
7248 /* Route status display. */
7250 json_status
= json_object_new_object();
7251 json_net
= json_object_new_object();
7258 /* print prefix and mask */
7260 json_object_string_add(
7261 json_net
, "addrPrefix",
7262 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
7263 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
7264 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7265 json_object_string_add(json_net
, "network", buf2
);
7267 route_vty_out_route(p
, vty
, NULL
);
7269 /* Print attribute */
7272 if (p
->family
== AF_INET
7273 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7274 || safi
== SAFI_EVPN
7275 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7276 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7277 || safi
== SAFI_EVPN
)
7278 json_object_string_add(
7279 json_net
, "nextHop",
7281 attr
->mp_nexthop_global_in
));
7283 json_object_string_add(
7284 json_net
, "nextHop",
7285 inet_ntoa(attr
->nexthop
));
7286 } else if (p
->family
== AF_INET6
7287 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7290 json_object_string_add(
7291 json_net
, "nextHopGlobal",
7293 &attr
->mp_nexthop_global
, buf
,
7298 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7299 json_object_int_add(json_net
, "metric",
7302 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7305 * Adding "locPrf" field to match with
7306 * corresponding CLI. "localPref" will be
7307 * deprecated in future.
7309 json_object_int_add(json_net
, "localPref",
7311 json_object_int_add(json_net
, "locPrf",
7315 json_object_int_add(json_net
, "weight", attr
->weight
);
7321 * Adding "path" field to match with
7322 * corresponding CLI. "localPref" will be
7323 * deprecated in future.
7325 json_object_string_add(json_net
, "asPath",
7327 json_object_string_add(json_net
, "path",
7332 json_object_string_add(json_net
, "bgpOriginCode",
7333 bgp_origin_str
[attr
->origin
]);
7335 if (p
->family
== AF_INET
7336 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7337 || safi
== SAFI_EVPN
7338 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7339 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7340 || safi
== SAFI_EVPN
)
7341 vty_out(vty
, "%-16s",
7343 attr
->mp_nexthop_global_in
));
7345 vty_out(vty
, "%-16s",
7346 inet_ntoa(attr
->nexthop
));
7347 } else if (p
->family
== AF_INET6
7348 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7355 &attr
->mp_nexthop_global
, buf
,
7359 vty_out(vty
, "\n%*s", 36, " ");
7361 vty_out(vty
, "%*s", len
, " ");
7364 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7365 vty_out(vty
, "%10u", attr
->med
);
7369 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7370 vty_out(vty
, "%7u", attr
->local_pref
);
7374 vty_out(vty
, "%7u ", attr
->weight
);
7378 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7381 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7385 json_object_boolean_true_add(json_status
, "*");
7386 json_object_boolean_true_add(json_status
, ">");
7387 json_object_object_add(json_net
, "appliedStatusSymbols",
7389 char buf_cut
[BUFSIZ
];
7390 json_object_object_add(
7392 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7398 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7399 struct bgp_path_info
*path
, int display
, safi_t safi
,
7402 json_object
*json_out
= NULL
;
7404 mpls_label_t label
= MPLS_INVALID_LABEL
;
7410 json_out
= json_object_new_object();
7412 /* short status lead text */
7413 route_vty_short_status_out(vty
, path
, json_out
);
7415 /* print prefix and mask */
7418 route_vty_out_route(p
, vty
, NULL
);
7420 vty_out(vty
, "%*s", 17, " ");
7423 /* Print attribute */
7426 if (((p
->family
== AF_INET
)
7427 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7428 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7429 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7430 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7431 || safi
== SAFI_EVPN
) {
7433 json_object_string_add(
7434 json_out
, "mpNexthopGlobalIn",
7436 attr
->mp_nexthop_global_in
));
7438 vty_out(vty
, "%-16s",
7440 attr
->mp_nexthop_global_in
));
7443 json_object_string_add(
7444 json_out
, "nexthop",
7445 inet_ntoa(attr
->nexthop
));
7447 vty_out(vty
, "%-16s",
7448 inet_ntoa(attr
->nexthop
));
7450 } else if (((p
->family
== AF_INET6
)
7451 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7452 || (safi
== SAFI_EVPN
7453 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7454 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7458 if (attr
->mp_nexthop_len
7459 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7461 json_object_string_add(
7462 json_out
, "mpNexthopGlobalIn",
7465 &attr
->mp_nexthop_global
,
7466 buf_a
, sizeof(buf_a
)));
7471 &attr
->mp_nexthop_global
,
7472 buf_a
, sizeof(buf_a
)));
7473 } else if (attr
->mp_nexthop_len
7474 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7477 &attr
->mp_nexthop_global
,
7478 buf_a
, sizeof(buf_a
));
7480 &attr
->mp_nexthop_local
,
7481 buf_b
, sizeof(buf_b
));
7482 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7483 json_object_string_add(
7485 "mpNexthopGlobalLocal", buf_c
);
7487 vty_out(vty
, "%s(%s)",
7490 &attr
->mp_nexthop_global
,
7491 buf_a
, sizeof(buf_a
)),
7494 &attr
->mp_nexthop_local
,
7495 buf_b
, sizeof(buf_b
)));
7500 label
= decode_label(&path
->extra
->label
[0]);
7502 if (bgp_is_valid_label(&label
)) {
7504 json_object_int_add(json_out
, "notag", label
);
7505 json_object_array_add(json
, json_out
);
7507 vty_out(vty
, "notag/%d", label
);
7513 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7514 struct bgp_path_info
*path
, int display
,
7515 json_object
*json_paths
)
7519 json_object
*json_path
= NULL
;
7522 json_path
= json_object_new_object();
7527 /* short status lead text */
7528 route_vty_short_status_out(vty
, path
, json_path
);
7530 /* print prefix and mask */
7532 route_vty_out_route(p
, vty
, NULL
);
7534 vty_out(vty
, "%*s", 17, " ");
7536 /* Print attribute */
7540 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7544 vty_out(vty
, "%-16s",
7545 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7549 vty_out(vty
, "%s(%s)",
7550 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7552 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7559 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7561 vty_out(vty
, "%s", str
);
7562 XFREE(MTYPE_TMP
, str
);
7564 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7566 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7567 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7570 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7573 if (attr
->ecommunity
) {
7575 struct ecommunity_val
*routermac
= ecommunity_lookup(
7576 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7577 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7579 mac
= ecom_mac2str((char *)routermac
->val
);
7581 vty_out(vty
, "/%s", (char *)mac
);
7582 XFREE(MTYPE_TMP
, mac
);
7590 /* dampening route */
7591 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7592 struct bgp_path_info
*path
, int display
,
7593 safi_t safi
, bool use_json
, json_object
*json
)
7597 char timebuf
[BGP_UPTIME_LEN
];
7599 /* short status lead text */
7600 route_vty_short_status_out(vty
, path
, json
);
7602 /* print prefix and mask */
7605 route_vty_out_route(p
, vty
, NULL
);
7607 vty_out(vty
, "%*s", 17, " ");
7610 len
= vty_out(vty
, "%s", path
->peer
->host
);
7614 vty_out(vty
, "\n%*s", 34, " ");
7617 json_object_int_add(json
, "peerHost", len
);
7619 vty_out(vty
, "%*s", len
, " ");
7623 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7627 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7628 BGP_UPTIME_LEN
, use_json
,
7631 /* Print attribute */
7637 json_object_string_add(json
, "asPath",
7640 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7645 json_object_string_add(json
, "origin",
7646 bgp_origin_str
[attr
->origin
]);
7648 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7655 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7656 struct bgp_path_info
*path
, int display
,
7657 safi_t safi
, bool use_json
, json_object
*json
)
7660 struct bgp_damp_info
*bdi
;
7661 char timebuf
[BGP_UPTIME_LEN
];
7667 bdi
= path
->extra
->damp_info
;
7669 /* short status lead text */
7670 route_vty_short_status_out(vty
, path
, json
);
7672 /* print prefix and mask */
7675 route_vty_out_route(p
, vty
, NULL
);
7677 vty_out(vty
, "%*s", 17, " ");
7680 len
= vty_out(vty
, "%s", path
->peer
->host
);
7684 vty_out(vty
, "\n%*s", 33, " ");
7687 json_object_int_add(json
, "peerHost", len
);
7689 vty_out(vty
, "%*s", len
, " ");
7692 len
= vty_out(vty
, "%d", bdi
->flap
);
7699 json_object_int_add(json
, "bdiFlap", len
);
7701 vty_out(vty
, "%*s", len
, " ");
7705 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7708 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7709 BGP_UPTIME_LEN
, 0, NULL
));
7711 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7712 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7714 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7715 BGP_UPTIME_LEN
, use_json
, json
);
7718 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7723 vty_out(vty
, "%*s ", 8, " ");
7726 /* Print attribute */
7732 json_object_string_add(json
, "asPath",
7735 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7740 json_object_string_add(json
, "origin",
7741 bgp_origin_str
[attr
->origin
]);
7743 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7749 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7750 int *first
, const char *header
,
7751 json_object
*json_adv_to
)
7753 char buf1
[INET6_ADDRSTRLEN
];
7754 json_object
*json_peer
= NULL
;
7757 /* 'advertised-to' is a dictionary of peers we have advertised
7759 * prefix too. The key is the peer's IP or swpX, the value is
7761 * hostname if we know it and "" if not.
7763 json_peer
= json_object_new_object();
7766 json_object_string_add(json_peer
, "hostname",
7770 json_object_object_add(json_adv_to
, peer
->conf_if
,
7773 json_object_object_add(
7775 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7779 vty_out(vty
, "%s", header
);
7784 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7786 vty_out(vty
, " %s(%s)", peer
->hostname
,
7789 vty_out(vty
, " %s(%s)", peer
->hostname
,
7790 sockunion2str(&peer
->su
, buf1
,
7794 vty_out(vty
, " %s", peer
->conf_if
);
7797 sockunion2str(&peer
->su
, buf1
,
7803 static void route_vty_out_tx_ids(struct vty
*vty
,
7804 struct bgp_addpath_info_data
*d
)
7808 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7809 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7810 d
->addpath_tx_id
[i
],
7811 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7815 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7816 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7817 json_object
*json_paths
)
7819 char buf
[INET6_ADDRSTRLEN
];
7821 char buf2
[EVPN_ROUTE_STRLEN
];
7823 int sockunion_vty_out(struct vty
*, union sockunion
*);
7825 json_object
*json_bestpath
= NULL
;
7826 json_object
*json_cluster_list
= NULL
;
7827 json_object
*json_cluster_list_list
= NULL
;
7828 json_object
*json_ext_community
= NULL
;
7829 json_object
*json_last_update
= NULL
;
7830 json_object
*json_pmsi
= NULL
;
7831 json_object
*json_nexthop_global
= NULL
;
7832 json_object
*json_nexthop_ll
= NULL
;
7833 json_object
*json_nexthops
= NULL
;
7834 json_object
*json_path
= NULL
;
7835 json_object
*json_peer
= NULL
;
7836 json_object
*json_string
= NULL
;
7837 json_object
*json_adv_to
= NULL
;
7839 struct listnode
*node
, *nnode
;
7841 int addpath_capable
;
7843 unsigned int first_as
;
7845 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7849 json_path
= json_object_new_object();
7850 json_peer
= json_object_new_object();
7851 json_nexthop_global
= json_object_new_object();
7854 if (!json_paths
&& safi
== SAFI_EVPN
) {
7857 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7858 vty_out(vty
, " Route %s", buf2
);
7860 if (path
->extra
&& path
->extra
->num_labels
) {
7861 bgp_evpn_label2str(path
->extra
->label
,
7862 path
->extra
->num_labels
, tag_buf
,
7864 vty_out(vty
, " VNI %s", tag_buf
);
7867 if (path
->extra
&& path
->extra
->parent
) {
7868 struct bgp_path_info
*parent_ri
;
7869 struct bgp_node
*rn
, *prn
;
7871 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7872 rn
= parent_ri
->net
;
7873 if (rn
&& rn
->prn
) {
7875 vty_out(vty
, " Imported from %s:%s\n",
7877 (struct prefix_rd
*)&prn
->p
,
7878 buf1
, sizeof(buf1
)),
7887 /* Line1 display AS-path, Aggregator */
7890 if (!attr
->aspath
->json
)
7891 aspath_str_update(attr
->aspath
, true);
7892 json_object_lock(attr
->aspath
->json
);
7893 json_object_object_add(json_path
, "aspath",
7894 attr
->aspath
->json
);
7896 if (attr
->aspath
->segments
)
7897 aspath_print_vty(vty
, " %s",
7900 vty_out(vty
, " Local");
7904 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7906 json_object_boolean_true_add(json_path
,
7909 vty_out(vty
, ", (removed)");
7912 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7914 json_object_boolean_true_add(json_path
,
7917 vty_out(vty
, ", (stale)");
7920 if (CHECK_FLAG(attr
->flag
,
7921 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7923 json_object_int_add(json_path
, "aggregatorAs",
7924 attr
->aggregator_as
);
7925 json_object_string_add(
7926 json_path
, "aggregatorId",
7927 inet_ntoa(attr
->aggregator_addr
));
7929 vty_out(vty
, ", (aggregated by %u %s)",
7930 attr
->aggregator_as
,
7931 inet_ntoa(attr
->aggregator_addr
));
7935 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7936 PEER_FLAG_REFLECTOR_CLIENT
)) {
7938 json_object_boolean_true_add(
7939 json_path
, "rxedFromRrClient");
7941 vty_out(vty
, ", (Received from a RR-client)");
7944 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7945 PEER_FLAG_RSERVER_CLIENT
)) {
7947 json_object_boolean_true_add(
7948 json_path
, "rxedFromRsClient");
7950 vty_out(vty
, ", (Received from a RS-client)");
7953 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7955 json_object_boolean_true_add(
7956 json_path
, "dampeningHistoryEntry");
7958 vty_out(vty
, ", (history entry)");
7959 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
7961 json_object_boolean_true_add(
7962 json_path
, "dampeningSuppressed");
7964 vty_out(vty
, ", (suppressed due to dampening)");
7970 /* Line2 display Next-hop, Neighbor, Router-id */
7971 /* Display the nexthop */
7972 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7973 || p
->family
== AF_EVPN
)
7974 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7975 || safi
== SAFI_EVPN
7976 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7977 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7978 || safi
== SAFI_EVPN
) {
7980 json_object_string_add(
7981 json_nexthop_global
, "ip",
7983 attr
->mp_nexthop_global_in
));
7987 attr
->mp_nexthop_global_in
));
7990 json_object_string_add(
7991 json_nexthop_global
, "ip",
7992 inet_ntoa(attr
->nexthop
));
7995 inet_ntoa(attr
->nexthop
));
7999 json_object_string_add(json_nexthop_global
,
8003 json_object_string_add(
8004 json_nexthop_global
, "ip",
8006 &attr
->mp_nexthop_global
, buf
,
8008 json_object_string_add(json_nexthop_global
,
8010 json_object_string_add(json_nexthop_global
,
8015 &attr
->mp_nexthop_global
, buf
,
8020 /* Display the IGP cost or 'inaccessible' */
8021 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8023 json_object_boolean_false_add(
8024 json_nexthop_global
, "accessible");
8026 vty_out(vty
, " (inaccessible)");
8028 if (path
->extra
&& path
->extra
->igpmetric
) {
8030 json_object_int_add(
8031 json_nexthop_global
, "metric",
8032 path
->extra
->igpmetric
);
8034 vty_out(vty
, " (metric %u)",
8035 path
->extra
->igpmetric
);
8038 /* IGP cost is 0, display this only for json */
8041 json_object_int_add(json_nexthop_global
,
8046 json_object_boolean_true_add(
8047 json_nexthop_global
, "accessible");
8050 /* Display peer "from" output */
8051 /* This path was originated locally */
8052 if (path
->peer
== bgp
->peer_self
) {
8054 if (safi
== SAFI_EVPN
8055 || (p
->family
== AF_INET
8056 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8058 json_object_string_add(
8059 json_peer
, "peerId", "0.0.0.0");
8061 vty_out(vty
, " from 0.0.0.0 ");
8064 json_object_string_add(json_peer
,
8067 vty_out(vty
, " from :: ");
8071 json_object_string_add(
8072 json_peer
, "routerId",
8073 inet_ntoa(bgp
->router_id
));
8075 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8078 /* We RXed this path from one of our peers */
8082 json_object_string_add(
8083 json_peer
, "peerId",
8084 sockunion2str(&path
->peer
->su
, buf
,
8086 json_object_string_add(
8087 json_peer
, "routerId",
8089 &path
->peer
->remote_id
, buf1
,
8092 if (path
->peer
->hostname
)
8093 json_object_string_add(
8094 json_peer
, "hostname",
8095 path
->peer
->hostname
);
8097 if (path
->peer
->domainname
)
8098 json_object_string_add(
8099 json_peer
, "domainname",
8100 path
->peer
->domainname
);
8102 if (path
->peer
->conf_if
)
8103 json_object_string_add(
8104 json_peer
, "interface",
8105 path
->peer
->conf_if
);
8107 if (path
->peer
->conf_if
) {
8108 if (path
->peer
->hostname
8111 BGP_FLAG_SHOW_HOSTNAME
))
8112 vty_out(vty
, " from %s(%s)",
8113 path
->peer
->hostname
,
8114 path
->peer
->conf_if
);
8116 vty_out(vty
, " from %s",
8117 path
->peer
->conf_if
);
8119 if (path
->peer
->hostname
8122 BGP_FLAG_SHOW_HOSTNAME
))
8123 vty_out(vty
, " from %s(%s)",
8124 path
->peer
->hostname
,
8127 vty_out(vty
, " from %s",
8135 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8136 vty_out(vty
, " (%s)",
8137 inet_ntoa(attr
->originator_id
));
8139 vty_out(vty
, " (%s)",
8142 &path
->peer
->remote_id
,
8143 buf1
, sizeof(buf1
)));
8148 * Note when vrfid of nexthop is different from that of prefix
8150 if (path
->extra
&& path
->extra
->bgp_orig
) {
8151 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8156 if (path
->extra
->bgp_orig
->inst_type
8157 == BGP_INSTANCE_TYPE_DEFAULT
)
8159 vn
= VRF_DEFAULT_NAME
;
8161 vn
= path
->extra
->bgp_orig
->name
;
8163 json_object_string_add(json_path
, "nhVrfName",
8166 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8167 json_object_int_add(json_path
,
8170 json_object_int_add(json_path
,
8171 "nhVrfId", (int)nexthop_vrfid
);
8174 if (nexthop_vrfid
== VRF_UNKNOWN
)
8175 vty_out(vty
, " vrf ?");
8177 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8183 json_object_boolean_true_add(json_path
,
8184 "announceNexthopSelf");
8186 vty_out(vty
, " announce-nh-self");
8193 /* display the link-local nexthop */
8194 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8196 json_nexthop_ll
= json_object_new_object();
8197 json_object_string_add(
8198 json_nexthop_ll
, "ip",
8200 &attr
->mp_nexthop_local
, buf
,
8202 json_object_string_add(json_nexthop_ll
, "afi",
8204 json_object_string_add(json_nexthop_ll
, "scope",
8207 json_object_boolean_true_add(json_nexthop_ll
,
8210 if (!attr
->mp_nexthop_prefer_global
)
8211 json_object_boolean_true_add(
8212 json_nexthop_ll
, "used");
8214 json_object_boolean_true_add(
8215 json_nexthop_global
, "used");
8217 vty_out(vty
, " (%s) %s\n",
8219 &attr
->mp_nexthop_local
, buf
,
8221 attr
->mp_nexthop_prefer_global
8226 /* If we do not have a link-local nexthop then we must flag the
8230 json_object_boolean_true_add(
8231 json_nexthop_global
, "used");
8234 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8235 * Int/Ext/Local, Atomic, best */
8237 json_object_string_add(
8238 json_path
, "origin",
8239 bgp_origin_long_str
[attr
->origin
]);
8241 vty_out(vty
, " Origin %s",
8242 bgp_origin_long_str
[attr
->origin
]);
8244 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8248 * Adding "metric" field to match with
8249 * corresponding CLI. "med" will be
8250 * deprecated in future.
8252 json_object_int_add(json_path
, "med",
8254 json_object_int_add(json_path
, "metric",
8257 vty_out(vty
, ", metric %u", attr
->med
);
8260 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8262 json_object_int_add(json_path
, "localpref",
8265 vty_out(vty
, ", localpref %u",
8269 if (attr
->weight
!= 0) {
8271 json_object_int_add(json_path
, "weight",
8274 vty_out(vty
, ", weight %u", attr
->weight
);
8277 if (attr
->tag
!= 0) {
8279 json_object_int_add(json_path
, "tag",
8282 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8286 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8288 json_object_boolean_false_add(json_path
,
8291 vty_out(vty
, ", invalid");
8292 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8294 json_object_boolean_true_add(json_path
,
8297 vty_out(vty
, ", valid");
8300 if (path
->peer
!= bgp
->peer_self
) {
8301 if (path
->peer
->as
== path
->peer
->local_as
) {
8302 if (CHECK_FLAG(bgp
->config
,
8303 BGP_CONFIG_CONFEDERATION
)) {
8305 json_object_string_add(
8310 ", confed-internal");
8313 json_object_string_add(
8317 vty_out(vty
, ", internal");
8320 if (bgp_confederation_peers_check(
8321 bgp
, path
->peer
->as
)) {
8323 json_object_string_add(
8328 ", confed-external");
8331 json_object_string_add(
8335 vty_out(vty
, ", external");
8338 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8340 json_object_boolean_true_add(json_path
,
8342 json_object_boolean_true_add(json_path
,
8345 vty_out(vty
, ", aggregated, local");
8347 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8349 json_object_boolean_true_add(json_path
,
8352 vty_out(vty
, ", sourced");
8355 json_object_boolean_true_add(json_path
,
8357 json_object_boolean_true_add(json_path
,
8360 vty_out(vty
, ", sourced, local");
8364 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8366 json_object_boolean_true_add(json_path
,
8369 vty_out(vty
, ", atomic-aggregate");
8372 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8373 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8374 && bgp_path_info_mpath_count(path
))) {
8376 json_object_boolean_true_add(json_path
,
8379 vty_out(vty
, ", multipath");
8382 // Mark the bestpath(s)
8383 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8384 first_as
= aspath_get_first_as(attr
->aspath
);
8389 json_object_new_object();
8390 json_object_int_add(json_bestpath
,
8391 "bestpathFromAs", first_as
);
8394 vty_out(vty
, ", bestpath-from-AS %u",
8398 ", bestpath-from-AS Local");
8402 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8406 json_object_new_object();
8407 json_object_boolean_true_add(json_bestpath
,
8410 vty_out(vty
, ", best");
8414 json_object_object_add(json_path
, "bestpath",
8420 /* Line 4 display Community */
8421 if (attr
->community
) {
8423 if (!attr
->community
->json
)
8424 community_str(attr
->community
, true);
8425 json_object_lock(attr
->community
->json
);
8426 json_object_object_add(json_path
, "community",
8427 attr
->community
->json
);
8429 vty_out(vty
, " Community: %s\n",
8430 attr
->community
->str
);
8434 /* Line 5 display Extended-community */
8435 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8437 json_ext_community
= json_object_new_object();
8438 json_object_string_add(json_ext_community
,
8440 attr
->ecommunity
->str
);
8441 json_object_object_add(json_path
,
8442 "extendedCommunity",
8443 json_ext_community
);
8445 vty_out(vty
, " Extended Community: %s\n",
8446 attr
->ecommunity
->str
);
8450 /* Line 6 display Large community */
8451 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8453 if (!attr
->lcommunity
->json
)
8454 lcommunity_str(attr
->lcommunity
, true);
8455 json_object_lock(attr
->lcommunity
->json
);
8456 json_object_object_add(json_path
,
8458 attr
->lcommunity
->json
);
8460 vty_out(vty
, " Large Community: %s\n",
8461 attr
->lcommunity
->str
);
8465 /* Line 7 display Originator, Cluster-id */
8466 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8467 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8469 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8471 json_object_string_add(
8472 json_path
, "originatorId",
8473 inet_ntoa(attr
->originator_id
));
8475 vty_out(vty
, " Originator: %s",
8476 inet_ntoa(attr
->originator_id
));
8479 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8484 json_object_new_object();
8485 json_cluster_list_list
=
8486 json_object_new_array();
8489 i
< attr
->cluster
->length
/ 4;
8491 json_string
= json_object_new_string(
8495 json_object_array_add(
8496 json_cluster_list_list
,
8500 /* struct cluster_list does not have
8502 * aspath and community do. Add this
8505 json_object_string_add(json_cluster_list,
8506 "string", attr->cluster->str);
8508 json_object_object_add(
8509 json_cluster_list
, "list",
8510 json_cluster_list_list
);
8511 json_object_object_add(
8512 json_path
, "clusterList",
8515 vty_out(vty
, ", Cluster list: ");
8518 i
< attr
->cluster
->length
/ 4;
8532 if (path
->extra
&& path
->extra
->damp_info
)
8533 bgp_damp_info_vty(vty
, path
, json_path
);
8536 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8537 && safi
!= SAFI_EVPN
) {
8538 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8541 json_object_int_add(json_path
, "remoteLabel",
8544 vty_out(vty
, " Remote label: %d\n", label
);
8548 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8550 json_object_int_add(json_path
, "labelIndex",
8553 vty_out(vty
, " Label Index: %d\n",
8557 /* Line 8 display Addpath IDs */
8558 if (path
->addpath_rx_id
8559 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8561 json_object_int_add(json_path
, "addpathRxId",
8562 path
->addpath_rx_id
);
8564 /* Keep backwards compatibility with the old API
8565 * by putting TX All's ID in the old field
8567 json_object_int_add(
8568 json_path
, "addpathTxId",
8569 path
->tx_addpath
.addpath_tx_id
8572 /* ... but create a specific field for each
8575 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8576 json_object_int_add(
8578 bgp_addpath_names(i
)
8584 vty_out(vty
, " AddPath ID: RX %u, ",
8585 path
->addpath_rx_id
);
8587 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8591 /* If we used addpath to TX a non-bestpath we need to display
8592 * "Advertised to" on a path-by-path basis
8594 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8597 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8599 bgp_addpath_encode_tx(peer
, afi
, safi
);
8600 has_adj
= bgp_adj_out_lookup(
8602 bgp_addpath_id_for_peer(
8604 &path
->tx_addpath
));
8606 if ((addpath_capable
&& has_adj
)
8607 || (!addpath_capable
&& has_adj
8608 && CHECK_FLAG(path
->flags
,
8609 BGP_PATH_SELECTED
))) {
8610 if (json_path
&& !json_adv_to
)
8612 json_object_new_object();
8614 route_vty_out_advertised_to(
8623 json_object_object_add(json_path
,
8634 /* Line 9 display Uptime */
8635 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8637 json_last_update
= json_object_new_object();
8638 json_object_int_add(json_last_update
, "epoch", tbuf
);
8639 json_object_string_add(json_last_update
, "string",
8641 json_object_object_add(json_path
, "lastUpdate",
8644 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8646 /* Line 10 display PMSI tunnel attribute, if present */
8647 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8648 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8649 attr
->pmsi_tnl_type
,
8650 PMSI_TNLTYPE_STR_DEFAULT
);
8653 json_pmsi
= json_object_new_object();
8654 json_object_string_add(json_pmsi
,
8656 json_object_int_add(json_pmsi
,
8658 label2vni(&attr
->label
));
8659 json_object_object_add(json_path
, "pmsi",
8663 " PMSI Tunnel Type: %s, label: %d\n",
8664 str
, label2vni(&attr
->label
));
8669 /* We've constructed the json object for this path, add it to the json
8673 if (json_nexthop_global
|| json_nexthop_ll
) {
8674 json_nexthops
= json_object_new_array();
8676 if (json_nexthop_global
)
8677 json_object_array_add(json_nexthops
,
8678 json_nexthop_global
);
8680 if (json_nexthop_ll
)
8681 json_object_array_add(json_nexthops
,
8684 json_object_object_add(json_path
, "nexthops",
8688 json_object_object_add(json_path
, "peer", json_peer
);
8689 json_object_array_add(json_paths
, json_path
);
8694 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8695 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8696 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8698 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8699 const char *prefix_list_str
, afi_t afi
,
8700 safi_t safi
, enum bgp_show_type type
);
8701 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8702 const char *filter
, afi_t afi
, safi_t safi
,
8703 enum bgp_show_type type
);
8704 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8705 const char *rmap_str
, afi_t afi
, safi_t safi
,
8706 enum bgp_show_type type
);
8707 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8708 const char *com
, int exact
, afi_t afi
,
8710 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8711 const char *prefix
, afi_t afi
, safi_t safi
,
8712 enum bgp_show_type type
);
8713 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8714 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8715 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8716 const char *comstr
, int exact
, afi_t afi
,
8717 safi_t safi
, bool use_json
);
8720 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8721 struct bgp_table
*table
, enum bgp_show_type type
,
8722 void *output_arg
, bool use_json
, char *rd
,
8723 int is_last
, unsigned long *output_cum
,
8724 unsigned long *total_cum
,
8725 unsigned long *json_header_depth
)
8727 struct bgp_path_info
*pi
;
8728 struct bgp_node
*rn
;
8731 unsigned long output_count
= 0;
8732 unsigned long total_count
= 0;
8735 json_object
*json_paths
= NULL
;
8738 if (output_cum
&& *output_cum
!= 0)
8741 if (use_json
&& !*json_header_depth
) {
8743 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8744 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8745 " \"localAS\": %u,\n \"routes\": { ",
8746 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8747 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8750 table
->version
, inet_ntoa(bgp
->router_id
),
8751 bgp
->default_local_pref
, bgp
->as
);
8752 *json_header_depth
= 2;
8754 vty_out(vty
, " \"routeDistinguishers\" : {");
8755 ++*json_header_depth
;
8759 if (use_json
&& rd
) {
8760 vty_out(vty
, " \"%s\" : { ", rd
);
8763 /* Start processing of routes. */
8764 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8765 pi
= bgp_node_get_bgp_path_info(rn
);
8771 json_paths
= json_object_new_array();
8775 for (; pi
; pi
= pi
->next
) {
8777 if (type
== bgp_show_type_flap_statistics
8778 || type
== bgp_show_type_flap_neighbor
8779 || type
== bgp_show_type_dampend_paths
8780 || type
== bgp_show_type_damp_neighbor
) {
8781 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8784 if (type
== bgp_show_type_regexp
) {
8785 regex_t
*regex
= output_arg
;
8787 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8791 if (type
== bgp_show_type_prefix_list
) {
8792 struct prefix_list
*plist
= output_arg
;
8794 if (prefix_list_apply(plist
, &rn
->p
)
8798 if (type
== bgp_show_type_filter_list
) {
8799 struct as_list
*as_list
= output_arg
;
8801 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8802 != AS_FILTER_PERMIT
)
8805 if (type
== bgp_show_type_route_map
) {
8806 struct route_map
*rmap
= output_arg
;
8807 struct bgp_path_info path
;
8808 struct attr dummy_attr
;
8811 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8813 path
.peer
= pi
->peer
;
8814 path
.attr
= &dummy_attr
;
8816 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8818 if (ret
== RMAP_DENYMATCH
)
8821 if (type
== bgp_show_type_neighbor
8822 || type
== bgp_show_type_flap_neighbor
8823 || type
== bgp_show_type_damp_neighbor
) {
8824 union sockunion
*su
= output_arg
;
8826 if (pi
->peer
== NULL
8827 || pi
->peer
->su_remote
== NULL
8828 || !sockunion_same(pi
->peer
->su_remote
, su
))
8831 if (type
== bgp_show_type_cidr_only
) {
8832 uint32_t destination
;
8834 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8835 if (IN_CLASSC(destination
)
8836 && rn
->p
.prefixlen
== 24)
8838 if (IN_CLASSB(destination
)
8839 && rn
->p
.prefixlen
== 16)
8841 if (IN_CLASSA(destination
)
8842 && rn
->p
.prefixlen
== 8)
8845 if (type
== bgp_show_type_prefix_longer
) {
8847 if (!prefix_match(p
, &rn
->p
))
8850 if (type
== bgp_show_type_community_all
) {
8851 if (!pi
->attr
->community
)
8854 if (type
== bgp_show_type_community
) {
8855 struct community
*com
= output_arg
;
8857 if (!pi
->attr
->community
8858 || !community_match(pi
->attr
->community
,
8862 if (type
== bgp_show_type_community_exact
) {
8863 struct community
*com
= output_arg
;
8865 if (!pi
->attr
->community
8866 || !community_cmp(pi
->attr
->community
, com
))
8869 if (type
== bgp_show_type_community_list
) {
8870 struct community_list
*list
= output_arg
;
8872 if (!community_list_match(pi
->attr
->community
,
8876 if (type
== bgp_show_type_community_list_exact
) {
8877 struct community_list
*list
= output_arg
;
8879 if (!community_list_exact_match(
8880 pi
->attr
->community
, list
))
8883 if (type
== bgp_show_type_lcommunity
) {
8884 struct lcommunity
*lcom
= output_arg
;
8886 if (!pi
->attr
->lcommunity
8887 || !lcommunity_match(pi
->attr
->lcommunity
,
8891 if (type
== bgp_show_type_lcommunity_list
) {
8892 struct community_list
*list
= output_arg
;
8894 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8898 if (type
== bgp_show_type_lcommunity_all
) {
8899 if (!pi
->attr
->lcommunity
)
8902 if (type
== bgp_show_type_dampend_paths
8903 || type
== bgp_show_type_damp_neighbor
) {
8904 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8905 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8909 if (!use_json
&& header
) {
8910 vty_out(vty
, "BGP table version is %" PRIu64
8911 ", local router ID is %s, vrf id ",
8913 inet_ntoa(bgp
->router_id
));
8914 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8915 vty_out(vty
, "%s", VRFID_NONE_STR
);
8917 vty_out(vty
, "%u", bgp
->vrf_id
);
8919 vty_out(vty
, "Default local pref %u, ",
8920 bgp
->default_local_pref
);
8921 vty_out(vty
, "local AS %u\n", bgp
->as
);
8922 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8923 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8924 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8925 if (type
== bgp_show_type_dampend_paths
8926 || type
== bgp_show_type_damp_neighbor
)
8927 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8928 else if (type
== bgp_show_type_flap_statistics
8929 || type
== bgp_show_type_flap_neighbor
)
8930 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8932 vty_out(vty
, BGP_SHOW_HEADER
);
8935 if (rd
!= NULL
&& !display
&& !output_count
) {
8938 "Route Distinguisher: %s\n",
8941 if (type
== bgp_show_type_dampend_paths
8942 || type
== bgp_show_type_damp_neighbor
)
8943 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
8944 safi
, use_json
, json_paths
);
8945 else if (type
== bgp_show_type_flap_statistics
8946 || type
== bgp_show_type_flap_neighbor
)
8947 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
8948 safi
, use_json
, json_paths
);
8950 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
8962 if (p
->family
== AF_FLOWSPEC
) {
8963 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
8965 bgp_fs_nlri_get_string((unsigned char *)
8966 p
->u
.prefix_flowspec
.ptr
,
8967 p
->u
.prefix_flowspec
8970 NLRI_STRING_FORMAT_MIN
,
8973 vty_out(vty
, "\"%s/%d\": ",
8975 p
->u
.prefix_flowspec
.prefixlen
);
8977 vty_out(vty
, ",\"%s/%d\": ",
8979 p
->u
.prefix_flowspec
.prefixlen
);
8981 prefix2str(p
, buf2
, sizeof(buf2
));
8983 vty_out(vty
, "\"%s\": ", buf2
);
8985 vty_out(vty
, ",\"%s\": ", buf2
);
8988 json_object_to_json_string(json_paths
));
8989 json_object_free(json_paths
);
8996 output_count
+= *output_cum
;
8997 *output_cum
= output_count
;
9000 total_count
+= *total_cum
;
9001 *total_cum
= total_count
;
9005 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9009 for (i
= 0; i
< *json_header_depth
; ++i
)
9010 vty_out(vty
, " } ");
9014 /* No route is displayed */
9015 if (output_count
== 0) {
9016 if (type
== bgp_show_type_normal
)
9018 "No BGP prefixes displayed, %ld exist\n",
9022 "\nDisplayed %ld routes and %ld total paths\n",
9023 output_count
, total_count
);
9030 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9031 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9032 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9034 struct bgp_node
*rn
, *next
;
9035 unsigned long output_cum
= 0;
9036 unsigned long total_cum
= 0;
9037 unsigned long json_header_depth
= 0;
9038 struct bgp_table
*itable
;
9041 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9043 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9044 next
= bgp_route_next(rn
);
9045 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9048 itable
= bgp_node_get_bgp_table_info(rn
);
9049 if (itable
!= NULL
) {
9050 struct prefix_rd prd
;
9051 char rd
[RD_ADDRSTRLEN
];
9053 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9054 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9055 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9056 use_json
, rd
, next
== NULL
, &output_cum
,
9057 &total_cum
, &json_header_depth
);
9063 if (output_cum
== 0)
9064 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9068 "\nDisplayed %ld routes and %ld total paths\n",
9069 output_cum
, total_cum
);
9073 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9074 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9076 struct bgp_table
*table
;
9077 unsigned long json_header_depth
= 0;
9080 bgp
= bgp_get_default();
9085 vty_out(vty
, "No BGP process is configured\n");
9087 vty_out(vty
, "{}\n");
9091 table
= bgp
->rib
[afi
][safi
];
9092 /* use MPLS and ENCAP specific shows until they are merged */
9093 if (safi
== SAFI_MPLS_VPN
) {
9094 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9095 output_arg
, use_json
);
9098 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9099 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9100 output_arg
, use_json
,
9103 /* labeled-unicast routes live in the unicast table */
9104 else if (safi
== SAFI_LABELED_UNICAST
)
9105 safi
= SAFI_UNICAST
;
9107 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9108 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9111 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9112 safi_t safi
, bool use_json
)
9114 struct listnode
*node
, *nnode
;
9117 bool route_output
= false;
9120 vty_out(vty
, "{\n");
9122 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9123 route_output
= true;
9126 vty_out(vty
, ",\n");
9130 vty_out(vty
, "\"%s\":",
9131 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9135 vty_out(vty
, "\nInstance %s:\n",
9136 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9140 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9145 vty_out(vty
, "}\n");
9146 else if (!route_output
)
9147 vty_out(vty
, "%% BGP instance not found\n");
9150 /* Header of detailed BGP route information */
9151 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9152 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9153 afi_t afi
, safi_t safi
, json_object
*json
)
9155 struct bgp_path_info
*pi
;
9158 struct listnode
*node
, *nnode
;
9159 char buf1
[RD_ADDRSTRLEN
];
9160 char buf2
[INET6_ADDRSTRLEN
];
9161 char buf3
[EVPN_ROUTE_STRLEN
];
9162 char prefix_str
[BUFSIZ
];
9167 int route_filter_translated_v4
= 0;
9168 int route_filter_v4
= 0;
9169 int route_filter_translated_v6
= 0;
9170 int route_filter_v6
= 0;
9173 int accept_own_nexthop
= 0;
9176 int no_advertise
= 0;
9180 int has_valid_label
= 0;
9181 mpls_label_t label
= 0;
9182 json_object
*json_adv_to
= NULL
;
9185 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9187 if (has_valid_label
)
9188 label
= label_pton(&rn
->local_label
);
9191 if (has_valid_label
)
9192 json_object_int_add(json
, "localLabel", label
);
9194 json_object_string_add(
9196 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9198 if (safi
== SAFI_EVPN
)
9199 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9200 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9203 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9204 buf3
, sizeof(buf3
)));
9206 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9207 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9208 ? prefix_rd2str(prd
, buf1
,
9211 safi
== SAFI_MPLS_VPN
? ":" : "",
9212 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9216 if (has_valid_label
)
9217 vty_out(vty
, "Local label: %d\n", label
);
9218 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9219 vty_out(vty
, "not allocated\n");
9222 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9224 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9226 if (pi
->extra
&& pi
->extra
->suppress
)
9229 if (pi
->attr
->community
== NULL
)
9232 no_advertise
+= community_include(
9233 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9234 no_export
+= community_include(pi
->attr
->community
,
9235 COMMUNITY_NO_EXPORT
);
9236 local_as
+= community_include(pi
->attr
->community
,
9237 COMMUNITY_LOCAL_AS
);
9238 accept_own
+= community_include(pi
->attr
->community
,
9239 COMMUNITY_ACCEPT_OWN
);
9240 route_filter_translated_v4
+= community_include(
9241 pi
->attr
->community
,
9242 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9243 route_filter_translated_v6
+= community_include(
9244 pi
->attr
->community
,
9245 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9246 route_filter_v4
+= community_include(
9247 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9248 route_filter_v6
+= community_include(
9249 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9250 llgr_stale
+= community_include(pi
->attr
->community
,
9251 COMMUNITY_LLGR_STALE
);
9252 no_llgr
+= community_include(pi
->attr
->community
,
9254 accept_own_nexthop
+=
9255 community_include(pi
->attr
->community
,
9256 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9257 blackhole
+= community_include(pi
->attr
->community
,
9258 COMMUNITY_BLACKHOLE
);
9259 no_peer
+= community_include(pi
->attr
->community
,
9265 vty_out(vty
, "Paths: (%d available", count
);
9267 vty_out(vty
, ", best #%d", best
);
9268 if (safi
== SAFI_UNICAST
)
9269 vty_out(vty
, ", table %s",
9271 == BGP_INSTANCE_TYPE_DEFAULT
)
9275 vty_out(vty
, ", no best path");
9279 ", accept own local route exported and imported in different VRF");
9280 else if (route_filter_translated_v4
)
9282 ", mark translated RTs for VPNv4 route filtering");
9283 else if (route_filter_v4
)
9285 ", attach RT as-is for VPNv4 route filtering");
9286 else if (route_filter_translated_v6
)
9288 ", mark translated RTs for VPNv6 route filtering");
9289 else if (route_filter_v6
)
9291 ", attach RT as-is for VPNv6 route filtering");
9292 else if (llgr_stale
)
9294 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9297 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9298 else if (accept_own_nexthop
)
9300 ", accept local nexthop");
9302 vty_out(vty
, ", inform peer to blackhole prefix");
9304 vty_out(vty
, ", not advertised to EBGP peer");
9305 else if (no_advertise
)
9306 vty_out(vty
, ", not advertised to any peer");
9308 vty_out(vty
, ", not advertised outside local AS");
9311 ", inform EBGP peer not to advertise to their EBGP peers");
9315 ", Advertisements suppressed by an aggregate.");
9316 vty_out(vty
, ")\n");
9319 /* If we are not using addpath then we can display Advertised to and
9321 * show what peers we advertised the bestpath to. If we are using
9323 * though then we must display Advertised to on a path-by-path basis. */
9324 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9325 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9326 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9327 if (json
&& !json_adv_to
)
9328 json_adv_to
= json_object_new_object();
9330 route_vty_out_advertised_to(
9332 " Advertised to non peer-group peers:\n ",
9339 json_object_object_add(json
, "advertisedTo",
9344 vty_out(vty
, " Not advertised to any peer");
9350 /* Display specified route of BGP table. */
9351 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9352 struct bgp_table
*rib
, const char *ip_str
,
9353 afi_t afi
, safi_t safi
,
9354 struct prefix_rd
*prd
, int prefix_check
,
9355 enum bgp_path_type pathtype
, bool use_json
)
9360 struct prefix match
;
9361 struct bgp_node
*rn
;
9362 struct bgp_node
*rm
;
9363 struct bgp_path_info
*pi
;
9364 struct bgp_table
*table
;
9365 json_object
*json
= NULL
;
9366 json_object
*json_paths
= NULL
;
9368 /* Check IP address argument. */
9369 ret
= str2prefix(ip_str
, &match
);
9371 vty_out(vty
, "address is malformed\n");
9375 match
.family
= afi2family(afi
);
9378 json
= json_object_new_object();
9379 json_paths
= json_object_new_array();
9382 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9383 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9384 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9386 table
= bgp_node_get_bgp_table_info(rn
);
9392 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9396 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9397 bgp_unlock_node(rm
);
9401 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9404 route_vty_out_detail_header(
9406 (struct prefix_rd
*)&rn
->p
,
9407 AFI_IP
, safi
, json
);
9412 if (pathtype
== BGP_PATH_SHOW_ALL
9413 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9414 && CHECK_FLAG(pi
->flags
,
9416 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9417 && (CHECK_FLAG(pi
->flags
,
9419 || CHECK_FLAG(pi
->flags
,
9420 BGP_PATH_SELECTED
))))
9421 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9426 bgp_unlock_node(rm
);
9428 } else if (safi
== SAFI_FLOWSPEC
) {
9429 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9430 &match
, prefix_check
,
9437 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9439 || rn
->p
.prefixlen
== match
.prefixlen
) {
9440 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9443 route_vty_out_detail_header(
9444 vty
, bgp
, rn
, NULL
, afi
,
9450 if (pathtype
== BGP_PATH_SHOW_ALL
9452 == BGP_PATH_SHOW_BESTPATH
9457 == BGP_PATH_SHOW_MULTIPATH
9463 BGP_PATH_SELECTED
))))
9464 route_vty_out_detail(
9465 vty
, bgp
, &rn
->p
, pi
,
9466 afi
, safi
, json_paths
);
9470 bgp_unlock_node(rn
);
9476 json_object_object_add(json
, "paths", json_paths
);
9478 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9479 json
, JSON_C_TO_STRING_PRETTY
));
9480 json_object_free(json
);
9483 vty_out(vty
, "%% Network not in table\n");
9491 /* Display specified route of Main RIB */
9492 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9493 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9494 int prefix_check
, enum bgp_path_type pathtype
,
9498 bgp
= bgp_get_default();
9501 vty_out(vty
, "No BGP process is configured\n");
9503 vty_out(vty
, "{}\n");
9508 /* labeled-unicast routes live in the unicast table */
9509 if (safi
== SAFI_LABELED_UNICAST
)
9510 safi
= SAFI_UNICAST
;
9512 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9513 afi
, safi
, prd
, prefix_check
, pathtype
,
9517 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9518 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9521 struct lcommunity
*lcom
;
9527 b
= buffer_new(1024);
9528 for (i
= 0; i
< argc
; i
++) {
9530 buffer_putc(b
, ' ');
9532 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9534 buffer_putstr(b
, argv
[i
]->arg
);
9538 buffer_putc(b
, '\0');
9540 str
= buffer_getstr(b
);
9543 lcom
= lcommunity_str2com(str
);
9544 XFREE(MTYPE_TMP
, str
);
9546 vty_out(vty
, "%% Large-community malformed\n");
9550 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9554 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9555 const char *lcom
, afi_t afi
, safi_t safi
,
9558 struct community_list
*list
;
9560 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9561 LARGE_COMMUNITY_LIST_MASTER
);
9563 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9568 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9572 DEFUN (show_ip_bgp_large_community_list
,
9573 show_ip_bgp_large_community_list_cmd
,
9574 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9578 BGP_INSTANCE_HELP_STR
9580 BGP_SAFI_WITH_LABEL_HELP_STR
9581 "Display routes matching the large-community-list\n"
9582 "large-community-list number\n"
9583 "large-community-list name\n"
9587 afi_t afi
= AFI_IP6
;
9588 safi_t safi
= SAFI_UNICAST
;
9591 if (argv_find(argv
, argc
, "ip", &idx
))
9593 if (argv_find(argv
, argc
, "view", &idx
)
9594 || argv_find(argv
, argc
, "vrf", &idx
))
9595 vrf
= argv
[++idx
]->arg
;
9596 if (argv_find(argv
, argc
, "ipv4", &idx
)
9597 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9598 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9599 if (argv_find(argv
, argc
, "unicast", &idx
)
9600 || argv_find(argv
, argc
, "multicast", &idx
))
9601 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9604 bool uj
= use_json(argc
, argv
);
9606 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9608 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9612 argv_find(argv
, argc
, "large-community-list", &idx
);
9613 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9616 DEFUN (show_ip_bgp_large_community
,
9617 show_ip_bgp_large_community_cmd
,
9618 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9622 BGP_INSTANCE_HELP_STR
9624 BGP_SAFI_WITH_LABEL_HELP_STR
9625 "Display routes matching the large-communities\n"
9626 "List of large-community numbers\n"
9630 afi_t afi
= AFI_IP6
;
9631 safi_t safi
= SAFI_UNICAST
;
9634 if (argv_find(argv
, argc
, "ip", &idx
))
9636 if (argv_find(argv
, argc
, "view", &idx
)
9637 || argv_find(argv
, argc
, "vrf", &idx
))
9638 vrf
= argv
[++idx
]->arg
;
9639 if (argv_find(argv
, argc
, "ipv4", &idx
)
9640 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9641 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9642 if (argv_find(argv
, argc
, "unicast", &idx
)
9643 || argv_find(argv
, argc
, "multicast", &idx
))
9644 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9647 bool uj
= use_json(argc
, argv
);
9649 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9651 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9655 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9656 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9658 return bgp_show(vty
, bgp
, afi
, safi
,
9659 bgp_show_type_lcommunity_all
, NULL
, uj
);
9662 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9666 /* BGP route print out function without JSON */
9669 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9670 <dampening <parameters>\
9675 |community-list <(1-500)|WORD> [exact-match]\
9676 |A.B.C.D/M longer-prefixes\
9677 |X:X::X:X/M longer-prefixes\
9682 BGP_INSTANCE_HELP_STR
9684 BGP_SAFI_WITH_LABEL_HELP_STR
9685 "Display detailed information about dampening\n"
9686 "Display detail of configured dampening parameters\n"
9687 "Display routes matching the route-map\n"
9688 "A route-map to match on\n"
9689 "Display routes conforming to the prefix-list\n"
9690 "Prefix-list name\n"
9691 "Display routes conforming to the filter-list\n"
9692 "Regular expression access list name\n"
9693 "BGP RIB advertisement statistics\n"
9694 "Display routes matching the community-list\n"
9695 "community-list number\n"
9696 "community-list name\n"
9697 "Exact match of the communities\n"
9699 "Display route and more specific routes\n"
9701 "Display route and more specific routes\n")
9703 afi_t afi
= AFI_IP6
;
9704 safi_t safi
= SAFI_UNICAST
;
9705 int exact_match
= 0;
9706 struct bgp
*bgp
= NULL
;
9709 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9714 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9715 if (argv_find(argv
, argc
, "parameters", &idx
))
9716 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9719 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9720 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9721 safi
, bgp_show_type_prefix_list
);
9723 if (argv_find(argv
, argc
, "filter-list", &idx
))
9724 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9725 safi
, bgp_show_type_filter_list
);
9727 if (argv_find(argv
, argc
, "statistics", &idx
))
9728 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9730 if (argv_find(argv
, argc
, "route-map", &idx
))
9731 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9732 safi
, bgp_show_type_route_map
);
9734 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9735 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9736 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9738 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9739 exact_match
, afi
, safi
);
9742 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9743 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9744 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9746 bgp_show_type_prefix_longer
);
9751 /* BGP route print out function with JSON */
9752 DEFUN (show_ip_bgp_json
,
9753 show_ip_bgp_json_cmd
,
9754 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9756 |dampening <flap-statistics|dampened-paths>\
9757 |community [AA:NN|local-AS|no-advertise|no-export\
9758 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9759 |accept-own|accept-own-nexthop|route-filter-v6\
9760 |route-filter-v4|route-filter-translated-v6\
9761 |route-filter-translated-v4] [exact-match]\
9766 BGP_INSTANCE_HELP_STR
9768 BGP_SAFI_WITH_LABEL_HELP_STR
9769 "Display only routes with non-natural netmasks\n"
9770 "Display detailed information about dampening\n"
9771 "Display flap statistics of routes\n"
9772 "Display paths suppressed due to dampening\n"
9773 "Display routes matching the communities\n"
9775 "Do not send outside local AS (well-known community)\n"
9776 "Do not advertise to any peer (well-known community)\n"
9777 "Do not export to next AS (well-known community)\n"
9778 "Graceful shutdown (well-known community)\n"
9779 "Do not export to any peer (well-known community)\n"
9780 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9781 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9782 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9783 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9784 "Should accept VPN route with local nexthop (well-known community)\n"
9785 "RT VPNv6 route filtering (well-known community)\n"
9786 "RT VPNv4 route filtering (well-known community)\n"
9787 "RT translated VPNv6 route filtering (well-known community)\n"
9788 "RT translated VPNv4 route filtering (well-known community)\n"
9789 "Exact match of the communities\n"
9792 afi_t afi
= AFI_IP6
;
9793 safi_t safi
= SAFI_UNICAST
;
9794 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9795 struct bgp
*bgp
= NULL
;
9797 int exact_match
= 0;
9798 bool uj
= use_json(argc
, argv
);
9803 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9808 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9809 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9812 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9813 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9814 return bgp_show(vty
, bgp
, afi
, safi
,
9815 bgp_show_type_dampend_paths
, NULL
, uj
);
9816 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9817 return bgp_show(vty
, bgp
, afi
, safi
,
9818 bgp_show_type_flap_statistics
, NULL
,
9822 if (argv_find(argv
, argc
, "community", &idx
)) {
9823 char *maybecomm
= NULL
;
9824 char *community
= NULL
;
9826 if (idx
+ 1 < argc
) {
9827 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
9828 maybecomm
= argv
[idx
+ 1]->arg
;
9830 maybecomm
= argv
[idx
+ 1]->text
;
9833 if (maybecomm
&& !strmatch(maybecomm
, "json")
9834 && !strmatch(maybecomm
, "exact-match"))
9835 community
= maybecomm
;
9837 if (argv_find(argv
, argc
, "exact-match", &idx
))
9841 return bgp_show_community(vty
, bgp
, community
,
9842 exact_match
, afi
, safi
, uj
);
9844 return (bgp_show(vty
, bgp
, afi
, safi
,
9845 bgp_show_type_community_all
, NULL
,
9849 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9852 DEFUN (show_ip_bgp_route
,
9853 show_ip_bgp_route_cmd
,
9854 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9855 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9859 BGP_INSTANCE_HELP_STR
9861 BGP_SAFI_WITH_LABEL_HELP_STR
9862 "Network in the BGP routing table to display\n"
9864 "Network in the BGP routing table to display\n"
9866 "Display only the bestpath\n"
9867 "Display only multipaths\n"
9870 int prefix_check
= 0;
9872 afi_t afi
= AFI_IP6
;
9873 safi_t safi
= SAFI_UNICAST
;
9874 char *prefix
= NULL
;
9875 struct bgp
*bgp
= NULL
;
9876 enum bgp_path_type path_type
;
9877 bool uj
= use_json(argc
, argv
);
9881 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9888 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9892 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9893 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9894 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9896 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9897 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9900 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9901 && afi
!= AFI_IP6
) {
9903 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9906 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9909 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9913 prefix
= argv
[idx
]->arg
;
9915 /* [<bestpath|multipath>] */
9916 if (argv_find(argv
, argc
, "bestpath", &idx
))
9917 path_type
= BGP_PATH_SHOW_BESTPATH
;
9918 else if (argv_find(argv
, argc
, "multipath", &idx
))
9919 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9921 path_type
= BGP_PATH_SHOW_ALL
;
9923 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9927 DEFUN (show_ip_bgp_regexp
,
9928 show_ip_bgp_regexp_cmd
,
9929 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9933 BGP_INSTANCE_HELP_STR
9935 BGP_SAFI_WITH_LABEL_HELP_STR
9936 "Display routes matching the AS path regular expression\n"
9937 "A regular-expression to match the BGP AS paths\n")
9939 afi_t afi
= AFI_IP6
;
9940 safi_t safi
= SAFI_UNICAST
;
9941 struct bgp
*bgp
= NULL
;
9944 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9949 // get index of regex
9950 argv_find(argv
, argc
, "regexp", &idx
);
9953 char *regstr
= argv_concat(argv
, argc
, idx
);
9954 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9955 bgp_show_type_regexp
);
9956 XFREE(MTYPE_TMP
, regstr
);
9960 DEFUN (show_ip_bgp_instance_all
,
9961 show_ip_bgp_instance_all_cmd
,
9962 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9966 BGP_INSTANCE_ALL_HELP_STR
9968 BGP_SAFI_WITH_LABEL_HELP_STR
9972 safi_t safi
= SAFI_UNICAST
;
9973 struct bgp
*bgp
= NULL
;
9975 bool uj
= use_json(argc
, argv
);
9980 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9985 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9989 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9990 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9995 regex
= bgp_regcomp(regstr
);
9997 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10001 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10002 bgp_regex_free(regex
);
10006 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10007 const char *prefix_list_str
, afi_t afi
,
10008 safi_t safi
, enum bgp_show_type type
)
10010 struct prefix_list
*plist
;
10012 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10013 if (plist
== NULL
) {
10014 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10016 return CMD_WARNING
;
10019 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10022 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10023 const char *filter
, afi_t afi
, safi_t safi
,
10024 enum bgp_show_type type
)
10026 struct as_list
*as_list
;
10028 as_list
= as_list_lookup(filter
);
10029 if (as_list
== NULL
) {
10030 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10032 return CMD_WARNING
;
10035 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10038 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10039 const char *rmap_str
, afi_t afi
, safi_t safi
,
10040 enum bgp_show_type type
)
10042 struct route_map
*rmap
;
10044 rmap
= route_map_lookup_by_name(rmap_str
);
10046 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10047 return CMD_WARNING
;
10050 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10053 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10054 const char *comstr
, int exact
, afi_t afi
,
10055 safi_t safi
, bool use_json
)
10057 struct community
*com
;
10060 com
= community_str2com(comstr
);
10062 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10063 return CMD_WARNING
;
10066 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10067 (exact
? bgp_show_type_community_exact
10068 : bgp_show_type_community
),
10070 community_free(&com
);
10075 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10076 const char *com
, int exact
, afi_t afi
,
10079 struct community_list
*list
;
10081 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10082 if (list
== NULL
) {
10083 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10084 return CMD_WARNING
;
10087 return bgp_show(vty
, bgp
, afi
, safi
,
10088 (exact
? bgp_show_type_community_list_exact
10089 : bgp_show_type_community_list
),
10093 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10094 const char *prefix
, afi_t afi
, safi_t safi
,
10095 enum bgp_show_type type
)
10102 ret
= str2prefix(prefix
, p
);
10104 vty_out(vty
, "%% Malformed Prefix\n");
10105 return CMD_WARNING
;
10108 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10113 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
10114 const char *ip_str
, bool use_json
)
10118 union sockunion su
;
10120 /* Get peer sockunion. */
10121 ret
= str2sockunion(ip_str
, &su
);
10123 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
10125 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
10129 json_object
*json_no
= NULL
;
10130 json_no
= json_object_new_object();
10131 json_object_string_add(
10133 "malformedAddressOrName",
10135 vty_out(vty
, "%s\n",
10136 json_object_to_json_string_ext(
10138 JSON_C_TO_STRING_PRETTY
));
10139 json_object_free(json_no
);
10142 "%% Malformed address or name: %s\n",
10150 /* Peer structure lookup. */
10151 peer
= peer_lookup(bgp
, &su
);
10154 json_object
*json_no
= NULL
;
10155 json_no
= json_object_new_object();
10156 json_object_string_add(json_no
, "warning",
10157 "No such neighbor in this view/vrf");
10158 vty_out(vty
, "%s\n",
10159 json_object_to_json_string_ext(
10160 json_no
, JSON_C_TO_STRING_PRETTY
));
10161 json_object_free(json_no
);
10163 vty_out(vty
, "No such neighbor in this view/vrf\n");
10171 BGP_STATS_MAXBITLEN
= 0,
10173 BGP_STATS_PREFIXES
,
10175 BGP_STATS_UNAGGREGATEABLE
,
10176 BGP_STATS_MAX_AGGREGATEABLE
,
10177 BGP_STATS_AGGREGATES
,
10179 BGP_STATS_ASPATH_COUNT
,
10180 BGP_STATS_ASPATH_MAXHOPS
,
10181 BGP_STATS_ASPATH_TOTHOPS
,
10182 BGP_STATS_ASPATH_MAXSIZE
,
10183 BGP_STATS_ASPATH_TOTSIZE
,
10184 BGP_STATS_ASN_HIGHEST
,
10188 static const char *table_stats_strs
[] = {
10189 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10190 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10191 [BGP_STATS_RIB
] = "Total Advertisements",
10192 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10193 [BGP_STATS_MAX_AGGREGATEABLE
] =
10194 "Maximum aggregateable prefixes",
10195 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10196 [BGP_STATS_SPACE
] = "Address space advertised",
10197 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10198 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10199 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10200 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10201 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10202 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10203 [BGP_STATS_MAX
] = NULL
,
10206 struct bgp_table_stats
{
10207 struct bgp_table
*table
;
10208 unsigned long long counts
[BGP_STATS_MAX
];
10209 double total_space
;
10213 #define TALLY_SIGFIG 100000
10214 static unsigned long
10215 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10217 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10218 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10219 unsigned long ret
= newtot
/ count
;
10221 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10228 static int bgp_table_stats_walker(struct thread
*t
)
10230 struct bgp_node
*rn
;
10231 struct bgp_node
*top
;
10232 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10233 unsigned int space
= 0;
10235 if (!(top
= bgp_table_top(ts
->table
)))
10238 switch (top
->p
.family
) {
10240 space
= IPV4_MAX_BITLEN
;
10243 space
= IPV6_MAX_BITLEN
;
10247 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10249 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10250 struct bgp_path_info
*pi
;
10251 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10252 unsigned int pinum
= 0;
10257 if (!bgp_node_has_bgp_path_info_data(rn
))
10260 ts
->counts
[BGP_STATS_PREFIXES
]++;
10261 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10264 ts
->counts
[BGP_STATS_AVGPLEN
]
10265 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10266 ts
->counts
[BGP_STATS_AVGPLEN
],
10270 /* check if the prefix is included by any other announcements */
10271 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10272 prn
= bgp_node_parent_nolock(prn
);
10274 if (prn
== NULL
|| prn
== top
) {
10275 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10276 /* announced address space */
10279 pow(2.0, space
- rn
->p
.prefixlen
);
10280 } else if (bgp_node_has_bgp_path_info_data(prn
))
10281 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10283 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10285 ts
->counts
[BGP_STATS_RIB
]++;
10288 && (CHECK_FLAG(pi
->attr
->flag
,
10290 BGP_ATTR_ATOMIC_AGGREGATE
))))
10291 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10293 /* as-path stats */
10294 if (pi
->attr
&& pi
->attr
->aspath
) {
10295 unsigned int hops
=
10296 aspath_count_hops(pi
->attr
->aspath
);
10297 unsigned int size
=
10298 aspath_size(pi
->attr
->aspath
);
10299 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10301 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10303 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10304 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
10307 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10308 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
10311 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10312 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10314 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10315 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10316 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10318 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10319 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10320 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10323 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10324 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
10332 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10335 struct bgp_table_stats ts
;
10338 if (!bgp
->rib
[afi
][safi
]) {
10339 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10341 return CMD_WARNING
;
10344 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10346 /* labeled-unicast routes live in the unicast table */
10347 if (safi
== SAFI_LABELED_UNICAST
)
10348 safi
= SAFI_UNICAST
;
10350 memset(&ts
, 0, sizeof(ts
));
10351 ts
.table
= bgp
->rib
[afi
][safi
];
10352 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10354 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10355 if (!table_stats_strs
[i
])
10360 case BGP_STATS_ASPATH_AVGHOPS
:
10361 case BGP_STATS_ASPATH_AVGSIZE
:
10362 case BGP_STATS_AVGPLEN
:
10363 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10364 vty_out (vty
, "%12.2f",
10365 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10368 case BGP_STATS_ASPATH_TOTHOPS
:
10369 case BGP_STATS_ASPATH_TOTSIZE
:
10370 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10371 vty_out(vty
, "%12.2f",
10373 ? (float)ts
.counts
[i
]
10375 [BGP_STATS_ASPATH_COUNT
]
10378 case BGP_STATS_TOTPLEN
:
10379 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10380 vty_out(vty
, "%12.2f",
10382 ? (float)ts
.counts
[i
]
10384 [BGP_STATS_PREFIXES
]
10387 case BGP_STATS_SPACE
:
10388 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10389 vty_out(vty
, "%12g\n", ts
.total_space
);
10391 if (afi
== AFI_IP6
) {
10392 vty_out(vty
, "%30s: ", "/32 equivalent ");
10393 vty_out(vty
, "%12g\n",
10394 ts
.total_space
* pow(2.0, -128 + 32));
10395 vty_out(vty
, "%30s: ", "/48 equivalent ");
10396 vty_out(vty
, "%12g\n",
10397 ts
.total_space
* pow(2.0, -128 + 48));
10399 vty_out(vty
, "%30s: ", "% announced ");
10400 vty_out(vty
, "%12.2f\n",
10401 ts
.total_space
* 100. * pow(2.0, -32));
10402 vty_out(vty
, "%30s: ", "/8 equivalent ");
10403 vty_out(vty
, "%12.2f\n",
10404 ts
.total_space
* pow(2.0, -32 + 8));
10405 vty_out(vty
, "%30s: ", "/24 equivalent ");
10406 vty_out(vty
, "%12.2f\n",
10407 ts
.total_space
* pow(2.0, -32 + 24));
10411 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10412 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10415 vty_out(vty
, "\n");
10417 return CMD_SUCCESS
;
10429 PCOUNT_PFCNT
, /* the figure we display to users */
10433 static const char *pcount_strs
[] = {
10434 [PCOUNT_ADJ_IN
] = "Adj-in",
10435 [PCOUNT_DAMPED
] = "Damped",
10436 [PCOUNT_REMOVED
] = "Removed",
10437 [PCOUNT_HISTORY
] = "History",
10438 [PCOUNT_STALE
] = "Stale",
10439 [PCOUNT_VALID
] = "Valid",
10440 [PCOUNT_ALL
] = "All RIB",
10441 [PCOUNT_COUNTED
] = "PfxCt counted",
10442 [PCOUNT_PFCNT
] = "Useable",
10443 [PCOUNT_MAX
] = NULL
,
10446 struct peer_pcounts
{
10447 unsigned int count
[PCOUNT_MAX
];
10448 const struct peer
*peer
;
10449 const struct bgp_table
*table
;
10452 static int bgp_peer_count_walker(struct thread
*t
)
10454 struct bgp_node
*rn
;
10455 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10456 const struct peer
*peer
= pc
->peer
;
10458 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10459 struct bgp_adj_in
*ain
;
10460 struct bgp_path_info
*pi
;
10462 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10463 if (ain
->peer
== peer
)
10464 pc
->count
[PCOUNT_ADJ_IN
]++;
10466 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10468 if (pi
->peer
!= peer
)
10471 pc
->count
[PCOUNT_ALL
]++;
10473 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10474 pc
->count
[PCOUNT_DAMPED
]++;
10475 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10476 pc
->count
[PCOUNT_HISTORY
]++;
10477 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10478 pc
->count
[PCOUNT_REMOVED
]++;
10479 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10480 pc
->count
[PCOUNT_STALE
]++;
10481 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10482 pc
->count
[PCOUNT_VALID
]++;
10483 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10484 pc
->count
[PCOUNT_PFCNT
]++;
10486 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10487 pc
->count
[PCOUNT_COUNTED
]++;
10488 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10490 EC_LIB_DEVELOPMENT
,
10491 "Attempting to count but flags say it is unusable");
10493 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10495 EC_LIB_DEVELOPMENT
,
10496 "Not counted but flags say we should");
10503 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10504 safi_t safi
, bool use_json
)
10506 struct peer_pcounts pcounts
= {.peer
= peer
};
10508 json_object
*json
= NULL
;
10509 json_object
*json_loop
= NULL
;
10512 json
= json_object_new_object();
10513 json_loop
= json_object_new_object();
10516 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10517 || !peer
->bgp
->rib
[afi
][safi
]) {
10519 json_object_string_add(
10521 "No such neighbor or address family");
10522 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10523 json_object_free(json
);
10525 vty_out(vty
, "%% No such neighbor or address family\n");
10527 return CMD_WARNING
;
10530 memset(&pcounts
, 0, sizeof(pcounts
));
10531 pcounts
.peer
= peer
;
10532 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10534 /* in-place call via thread subsystem so as to record execution time
10535 * stats for the thread-walk (i.e. ensure this can't be blamed on
10536 * on just vty_read()).
10538 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10541 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10542 json_object_string_add(json
, "multiProtocol",
10543 afi_safi_print(afi
, safi
));
10544 json_object_int_add(json
, "pfxCounter",
10545 peer
->pcount
[afi
][safi
]);
10547 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10548 json_object_int_add(json_loop
, pcount_strs
[i
],
10551 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10553 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10554 json_object_string_add(json
, "pfxctDriftFor",
10556 json_object_string_add(
10557 json
, "recommended",
10558 "Please report this bug, with the above command output");
10560 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10561 json
, JSON_C_TO_STRING_PRETTY
));
10562 json_object_free(json
);
10566 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10567 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10568 peer
->hostname
, peer
->host
,
10569 afi_safi_print(afi
, safi
));
10571 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10572 afi_safi_print(afi
, safi
));
10575 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10576 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10578 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10579 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10582 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10583 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10585 "Please report this bug, with the above command output\n");
10589 return CMD_SUCCESS
;
10592 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10593 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10594 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10595 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10599 BGP_INSTANCE_HELP_STR
10602 "Detailed information on TCP and BGP neighbor connections\n"
10603 "Neighbor to display information about\n"
10604 "Neighbor to display information about\n"
10605 "Neighbor on BGP configured interface\n"
10606 "Display detailed prefix count information\n"
10609 afi_t afi
= AFI_IP6
;
10610 safi_t safi
= SAFI_UNICAST
;
10613 struct bgp
*bgp
= NULL
;
10614 bool uj
= use_json(argc
, argv
);
10619 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10622 return CMD_WARNING
;
10624 argv_find(argv
, argc
, "neighbors", &idx
);
10625 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10627 return CMD_WARNING
;
10629 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10632 #ifdef KEEP_OLD_VPN_COMMANDS
10633 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10634 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10635 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10640 "Display information about all VPNv4 NLRIs\n"
10641 "Detailed information on TCP and BGP neighbor connections\n"
10642 "Neighbor to display information about\n"
10643 "Neighbor to display information about\n"
10644 "Neighbor on BGP configured interface\n"
10645 "Display detailed prefix count information\n"
10650 bool uj
= use_json(argc
, argv
);
10652 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10654 return CMD_WARNING
;
10656 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10659 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10660 show_ip_bgp_vpn_all_route_prefix_cmd
,
10661 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10666 "Display information about all VPNv4 NLRIs\n"
10667 "Network in the BGP routing table to display\n"
10668 "Network in the BGP routing table to display\n"
10672 char *network
= NULL
;
10673 struct bgp
*bgp
= bgp_get_default();
10675 vty_out(vty
, "Can't find default instance\n");
10676 return CMD_WARNING
;
10679 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10680 network
= argv
[idx
]->arg
;
10681 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10682 network
= argv
[idx
]->arg
;
10684 vty_out(vty
, "Unable to figure out Network\n");
10685 return CMD_WARNING
;
10688 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10689 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10691 #endif /* KEEP_OLD_VPN_COMMANDS */
10693 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10694 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10695 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10701 "Display information about all EVPN NLRIs\n"
10702 "Network in the BGP routing table to display\n"
10703 "Network in the BGP routing table to display\n"
10707 char *network
= NULL
;
10709 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10710 network
= argv
[idx
]->arg
;
10711 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10712 network
= argv
[idx
]->arg
;
10714 vty_out(vty
, "Unable to figure out Network\n");
10715 return CMD_WARNING
;
10717 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10718 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10721 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10722 safi_t safi
, enum bgp_show_adj_route_type type
,
10723 const char *rmap_name
, bool use_json
,
10726 struct bgp_table
*table
;
10727 struct bgp_adj_in
*ain
;
10728 struct bgp_adj_out
*adj
;
10729 unsigned long output_count
;
10730 unsigned long filtered_count
;
10731 struct bgp_node
*rn
;
10737 struct update_subgroup
*subgrp
;
10738 json_object
*json_scode
= NULL
;
10739 json_object
*json_ocode
= NULL
;
10740 json_object
*json_ar
= NULL
;
10741 struct peer_af
*paf
;
10742 bool route_filtered
;
10745 json_scode
= json_object_new_object();
10746 json_ocode
= json_object_new_object();
10747 json_ar
= json_object_new_object();
10749 json_object_string_add(json_scode
, "suppressed", "s");
10750 json_object_string_add(json_scode
, "damped", "d");
10751 json_object_string_add(json_scode
, "history", "h");
10752 json_object_string_add(json_scode
, "valid", "*");
10753 json_object_string_add(json_scode
, "best", ">");
10754 json_object_string_add(json_scode
, "multipath", "=");
10755 json_object_string_add(json_scode
, "internal", "i");
10756 json_object_string_add(json_scode
, "ribFailure", "r");
10757 json_object_string_add(json_scode
, "stale", "S");
10758 json_object_string_add(json_scode
, "removed", "R");
10760 json_object_string_add(json_ocode
, "igp", "i");
10761 json_object_string_add(json_ocode
, "egp", "e");
10762 json_object_string_add(json_ocode
, "incomplete", "?");
10769 json_object_string_add(json
, "alert", "no BGP");
10770 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10771 json_object_free(json
);
10773 vty_out(vty
, "%% No bgp\n");
10777 table
= bgp
->rib
[afi
][safi
];
10779 output_count
= filtered_count
= 0;
10780 subgrp
= peer_subgroup(peer
, afi
, safi
);
10782 if (type
== bgp_show_adj_route_advertised
&& subgrp
10783 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10785 json_object_int_add(json
, "bgpTableVersion",
10787 json_object_string_add(json
, "bgpLocalRouterId",
10788 inet_ntoa(bgp
->router_id
));
10789 json_object_int_add(json
, "defaultLocPrf",
10790 bgp
->default_local_pref
);
10791 json_object_int_add(json
, "localAS", bgp
->as
);
10792 json_object_object_add(json
, "bgpStatusCodes",
10794 json_object_object_add(json
, "bgpOriginCodes",
10796 json_object_string_add(
10797 json
, "bgpOriginatingDefaultNetwork",
10798 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10800 vty_out(vty
, "BGP table version is %" PRIu64
10801 ", local router ID is %s, vrf id ",
10802 table
->version
, inet_ntoa(bgp
->router_id
));
10803 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10804 vty_out(vty
, "%s", VRFID_NONE_STR
);
10806 vty_out(vty
, "%u", bgp
->vrf_id
);
10807 vty_out(vty
, "\n");
10808 vty_out(vty
, "Default local pref %u, ",
10809 bgp
->default_local_pref
);
10810 vty_out(vty
, "local AS %u\n", bgp
->as
);
10811 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10812 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10813 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10815 vty_out(vty
, "Originating default network %s\n\n",
10816 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10821 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10822 if (type
== bgp_show_adj_route_received
10823 || type
== bgp_show_adj_route_filtered
) {
10824 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10825 if (ain
->peer
!= peer
|| !ain
->attr
)
10830 json_object_int_add(
10831 json
, "bgpTableVersion",
10833 json_object_string_add(
10835 "bgpLocalRouterId",
10838 json_object_int_add(json
,
10840 bgp
->default_local_pref
);
10841 json_object_int_add(json
,
10842 "localAS", bgp
->as
);
10843 json_object_object_add(
10844 json
, "bgpStatusCodes",
10846 json_object_object_add(
10847 json
, "bgpOriginCodes",
10851 "BGP table version is 0, local router ID is %s, vrf id ",
10854 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10860 vty_out(vty
, "\n");
10862 "Default local pref %u, ",
10863 bgp
->default_local_pref
);
10864 vty_out(vty
, "local AS %u\n",
10867 BGP_SHOW_SCODE_HEADER
);
10869 BGP_SHOW_NCODE_HEADER
);
10871 BGP_SHOW_OCODE_HEADER
);
10877 vty_out(vty
, BGP_SHOW_HEADER
);
10881 bgp_attr_dup(&attr
, ain
->attr
);
10882 route_filtered
= false;
10884 /* Filter prefix using distribute list,
10885 * filter list or prefix list
10887 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10888 safi
)) == FILTER_DENY
)
10889 route_filtered
= true;
10891 /* Filter prefix using route-map */
10892 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10893 afi
, safi
, rmap_name
);
10895 if (type
== bgp_show_adj_route_filtered
&&
10896 !route_filtered
&& ret
!= RMAP_DENY
) {
10897 bgp_attr_undup(&attr
, ain
->attr
);
10901 if (type
== bgp_show_adj_route_received
&&
10902 (route_filtered
|| ret
== RMAP_DENY
))
10905 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10906 use_json
, json_ar
);
10907 bgp_attr_undup(&attr
, ain
->attr
);
10910 } else if (type
== bgp_show_adj_route_advertised
) {
10911 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
10912 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10913 if (paf
->peer
!= peer
|| !adj
->attr
)
10918 json_object_int_add(
10922 json_object_string_add(
10924 "bgpLocalRouterId",
10927 json_object_int_add(
10928 json
, "defaultLocPrf",
10929 bgp
->default_local_pref
10931 json_object_int_add(
10934 json_object_object_add(
10938 json_object_object_add(
10944 "BGP table version is %" PRIu64
10945 ", local router ID is %s, vrf id ",
10958 vty_out(vty
, "\n");
10960 "Default local pref %u, ",
10961 bgp
->default_local_pref
10967 BGP_SHOW_SCODE_HEADER
);
10969 BGP_SHOW_NCODE_HEADER
);
10971 BGP_SHOW_OCODE_HEADER
);
10982 bgp_attr_dup(&attr
, adj
->attr
);
10983 ret
= bgp_output_modifier(
10984 peer
, &rn
->p
, &attr
, afi
, safi
,
10987 if (ret
!= RMAP_DENY
) {
10988 route_vty_out_tmp(vty
, &rn
->p
,
10997 bgp_attr_undup(&attr
, adj
->attr
);
11003 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11004 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11005 json_object_int_add(json
, "filteredPrefixCounter",
11008 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11009 json
, JSON_C_TO_STRING_PRETTY
));
11010 json_object_free(json
);
11011 } else if (output_count
> 0) {
11012 if (filtered_count
> 0)
11014 "\nTotal number of prefixes %ld (%ld filtered)\n",
11015 output_count
, filtered_count
);
11017 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11022 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11023 safi_t safi
, enum bgp_show_adj_route_type type
,
11024 const char *rmap_name
, bool use_json
)
11026 json_object
*json
= NULL
;
11029 json
= json_object_new_object();
11031 /* labeled-unicast routes live in the unicast table */
11032 if (safi
== SAFI_LABELED_UNICAST
)
11033 safi
= SAFI_UNICAST
;
11035 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11037 json_object_string_add(
11039 "No such neighbor or address family");
11040 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11041 json_object_free(json
);
11043 vty_out(vty
, "%% No such neighbor or address family\n");
11045 return CMD_WARNING
;
11048 if ((type
== bgp_show_adj_route_received
11049 || type
== bgp_show_adj_route_filtered
)
11050 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11051 PEER_FLAG_SOFT_RECONFIG
)) {
11053 json_object_string_add(
11055 "Inbound soft reconfiguration not enabled");
11056 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11057 json_object_free(json
);
11060 "%% Inbound soft reconfiguration not enabled\n");
11062 return CMD_WARNING
;
11065 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11067 return CMD_SUCCESS
;
11070 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11071 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11072 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11073 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11077 BGP_INSTANCE_HELP_STR
11079 BGP_SAFI_WITH_LABEL_HELP_STR
11080 "Detailed information on TCP and BGP neighbor connections\n"
11081 "Neighbor to display information about\n"
11082 "Neighbor to display information about\n"
11083 "Neighbor on BGP configured interface\n"
11084 "Display the routes advertised to a BGP neighbor\n"
11085 "Display the received routes from neighbor\n"
11086 "Display the filtered routes received from neighbor\n"
11087 "Route-map to modify the attributes\n"
11088 "Name of the route map\n"
11091 afi_t afi
= AFI_IP6
;
11092 safi_t safi
= SAFI_UNICAST
;
11093 char *rmap_name
= NULL
;
11094 char *peerstr
= NULL
;
11095 struct bgp
*bgp
= NULL
;
11097 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11099 bool uj
= use_json(argc
, argv
);
11104 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11107 return CMD_WARNING
;
11109 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11110 argv_find(argv
, argc
, "neighbors", &idx
);
11111 peerstr
= argv
[++idx
]->arg
;
11113 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11115 return CMD_WARNING
;
11117 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11118 type
= bgp_show_adj_route_advertised
;
11119 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11120 type
= bgp_show_adj_route_received
;
11121 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11122 type
= bgp_show_adj_route_filtered
;
11124 if (argv_find(argv
, argc
, "route-map", &idx
))
11125 rmap_name
= argv
[++idx
]->arg
;
11127 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11130 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11131 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11132 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11138 "Address Family modifier\n"
11139 "Detailed information on TCP and BGP neighbor connections\n"
11140 "Neighbor to display information about\n"
11141 "Neighbor to display information about\n"
11142 "Neighbor on BGP configured interface\n"
11143 "Display information received from a BGP neighbor\n"
11144 "Display the prefixlist filter\n"
11147 afi_t afi
= AFI_IP6
;
11148 safi_t safi
= SAFI_UNICAST
;
11149 char *peerstr
= NULL
;
11152 union sockunion su
;
11158 /* show [ip] bgp */
11159 if (argv_find(argv
, argc
, "ip", &idx
))
11161 /* [<ipv4|ipv6> [unicast]] */
11162 if (argv_find(argv
, argc
, "ipv4", &idx
))
11164 if (argv_find(argv
, argc
, "ipv6", &idx
))
11166 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11167 argv_find(argv
, argc
, "neighbors", &idx
);
11168 peerstr
= argv
[++idx
]->arg
;
11170 bool uj
= use_json(argc
, argv
);
11172 ret
= str2sockunion(peerstr
, &su
);
11174 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11177 vty_out(vty
, "{}\n");
11180 "%% Malformed address or name: %s\n",
11182 return CMD_WARNING
;
11185 peer
= peer_lookup(NULL
, &su
);
11188 vty_out(vty
, "{}\n");
11190 vty_out(vty
, "No peer\n");
11191 return CMD_WARNING
;
11195 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11196 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11199 vty_out(vty
, "Address Family: %s\n",
11200 afi_safi_print(afi
, safi
));
11201 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11204 vty_out(vty
, "{}\n");
11206 vty_out(vty
, "No functional output\n");
11209 return CMD_SUCCESS
;
11212 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11213 afi_t afi
, safi_t safi
,
11214 enum bgp_show_type type
, bool use_json
)
11216 /* labeled-unicast routes live in the unicast table */
11217 if (safi
== SAFI_LABELED_UNICAST
)
11218 safi
= SAFI_UNICAST
;
11220 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11222 json_object
*json_no
= NULL
;
11223 json_no
= json_object_new_object();
11224 json_object_string_add(
11225 json_no
, "warning",
11226 "No such neighbor or address family");
11227 vty_out(vty
, "%s\n",
11228 json_object_to_json_string(json_no
));
11229 json_object_free(json_no
);
11231 vty_out(vty
, "%% No such neighbor or address family\n");
11232 return CMD_WARNING
;
11235 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11238 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11239 show_ip_bgp_flowspec_routes_detailed_cmd
,
11240 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11244 BGP_INSTANCE_HELP_STR
11247 "Detailed information on flowspec entries\n"
11250 afi_t afi
= AFI_IP
;
11251 safi_t safi
= SAFI_UNICAST
;
11252 struct bgp
*bgp
= NULL
;
11254 bool uj
= use_json(argc
, argv
);
11259 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11262 return CMD_WARNING
;
11264 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11267 DEFUN (show_ip_bgp_neighbor_routes
,
11268 show_ip_bgp_neighbor_routes_cmd
,
11269 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11270 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11274 BGP_INSTANCE_HELP_STR
11276 BGP_SAFI_WITH_LABEL_HELP_STR
11277 "Detailed information on TCP and BGP neighbor connections\n"
11278 "Neighbor to display information about\n"
11279 "Neighbor to display information about\n"
11280 "Neighbor on BGP configured interface\n"
11281 "Display flap statistics of the routes learned from neighbor\n"
11282 "Display the dampened routes received from neighbor\n"
11283 "Display routes learned from neighbor\n"
11286 char *peerstr
= NULL
;
11287 struct bgp
*bgp
= NULL
;
11288 afi_t afi
= AFI_IP6
;
11289 safi_t safi
= SAFI_UNICAST
;
11291 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11293 bool uj
= use_json(argc
, argv
);
11298 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11301 return CMD_WARNING
;
11303 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11304 argv_find(argv
, argc
, "neighbors", &idx
);
11305 peerstr
= argv
[++idx
]->arg
;
11307 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11309 return CMD_WARNING
;
11311 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11312 sh_type
= bgp_show_type_flap_neighbor
;
11313 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11314 sh_type
= bgp_show_type_damp_neighbor
;
11315 else if (argv_find(argv
, argc
, "routes", &idx
))
11316 sh_type
= bgp_show_type_neighbor
;
11318 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11321 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11323 struct bgp_distance
{
11324 /* Distance value for the IP source prefix. */
11327 /* Name of the access-list to be matched. */
11331 DEFUN (show_bgp_afi_vpn_rd_route
,
11332 show_bgp_afi_vpn_rd_route_cmd
,
11333 "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]",
11337 "Address Family modifier\n"
11338 "Display information for a route distinguisher\n"
11339 "Route Distinguisher\n"
11340 "Network in the BGP routing table to display\n"
11341 "Network in the BGP routing table to display\n"
11345 struct prefix_rd prd
;
11346 afi_t afi
= AFI_MAX
;
11349 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11350 vty_out(vty
, "%% Malformed Address Family\n");
11351 return CMD_WARNING
;
11354 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11356 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11357 return CMD_WARNING
;
11360 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11361 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11364 static struct bgp_distance
*bgp_distance_new(void)
11366 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11369 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11371 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11374 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11375 const char *ip_str
, const char *access_list_str
)
11382 struct bgp_node
*rn
;
11383 struct bgp_distance
*bdistance
;
11385 afi
= bgp_node_afi(vty
);
11386 safi
= bgp_node_safi(vty
);
11388 ret
= str2prefix(ip_str
, &p
);
11390 vty_out(vty
, "Malformed prefix\n");
11391 return CMD_WARNING_CONFIG_FAILED
;
11394 distance
= atoi(distance_str
);
11396 /* Get BGP distance node. */
11397 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11398 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11400 bgp_unlock_node(rn
);
11402 bdistance
= bgp_distance_new();
11403 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11406 /* Set distance value. */
11407 bdistance
->distance
= distance
;
11409 /* Reset access-list configuration. */
11410 if (bdistance
->access_list
) {
11411 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11412 bdistance
->access_list
= NULL
;
11414 if (access_list_str
)
11415 bdistance
->access_list
=
11416 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11418 return CMD_SUCCESS
;
11421 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11422 const char *ip_str
, const char *access_list_str
)
11429 struct bgp_node
*rn
;
11430 struct bgp_distance
*bdistance
;
11432 afi
= bgp_node_afi(vty
);
11433 safi
= bgp_node_safi(vty
);
11435 ret
= str2prefix(ip_str
, &p
);
11437 vty_out(vty
, "Malformed prefix\n");
11438 return CMD_WARNING_CONFIG_FAILED
;
11441 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11442 (struct prefix
*)&p
);
11444 vty_out(vty
, "Can't find specified prefix\n");
11445 return CMD_WARNING_CONFIG_FAILED
;
11448 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11449 distance
= atoi(distance_str
);
11451 if (bdistance
->distance
!= distance
) {
11452 vty_out(vty
, "Distance does not match configured\n");
11453 return CMD_WARNING_CONFIG_FAILED
;
11456 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11457 bgp_distance_free(bdistance
);
11459 bgp_node_set_bgp_path_info(rn
, NULL
);
11460 bgp_unlock_node(rn
);
11461 bgp_unlock_node(rn
);
11463 return CMD_SUCCESS
;
11466 /* Apply BGP information to distance method. */
11467 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11468 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11470 struct bgp_node
*rn
;
11473 struct bgp_distance
*bdistance
;
11474 struct access_list
*alist
;
11475 struct bgp_static
*bgp_static
;
11480 peer
= pinfo
->peer
;
11482 /* Check source address. */
11483 sockunion2hostprefix(&peer
->su
, &q
);
11484 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11486 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11487 bgp_unlock_node(rn
);
11489 if (bdistance
->access_list
) {
11490 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11492 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11493 return bdistance
->distance
;
11495 return bdistance
->distance
;
11498 /* Backdoor check. */
11499 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11501 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11502 bgp_unlock_node(rn
);
11504 if (bgp_static
->backdoor
) {
11505 if (bgp
->distance_local
[afi
][safi
])
11506 return bgp
->distance_local
[afi
][safi
];
11508 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11512 if (peer
->sort
== BGP_PEER_EBGP
) {
11513 if (bgp
->distance_ebgp
[afi
][safi
])
11514 return bgp
->distance_ebgp
[afi
][safi
];
11515 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11517 if (bgp
->distance_ibgp
[afi
][safi
])
11518 return bgp
->distance_ibgp
[afi
][safi
];
11519 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11523 DEFUN (bgp_distance
,
11525 "distance bgp (1-255) (1-255) (1-255)",
11526 "Define an administrative distance\n"
11528 "Distance for routes external to the AS\n"
11529 "Distance for routes internal to the AS\n"
11530 "Distance for local routes\n")
11532 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11533 int idx_number
= 2;
11534 int idx_number_2
= 3;
11535 int idx_number_3
= 4;
11539 afi
= bgp_node_afi(vty
);
11540 safi
= bgp_node_safi(vty
);
11542 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11543 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11544 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11545 return CMD_SUCCESS
;
11548 DEFUN (no_bgp_distance
,
11549 no_bgp_distance_cmd
,
11550 "no distance bgp [(1-255) (1-255) (1-255)]",
11552 "Define an administrative distance\n"
11554 "Distance for routes external to the AS\n"
11555 "Distance for routes internal to the AS\n"
11556 "Distance for local routes\n")
11558 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11562 afi
= bgp_node_afi(vty
);
11563 safi
= bgp_node_safi(vty
);
11565 bgp
->distance_ebgp
[afi
][safi
] = 0;
11566 bgp
->distance_ibgp
[afi
][safi
] = 0;
11567 bgp
->distance_local
[afi
][safi
] = 0;
11568 return CMD_SUCCESS
;
11572 DEFUN (bgp_distance_source
,
11573 bgp_distance_source_cmd
,
11574 "distance (1-255) A.B.C.D/M",
11575 "Define an administrative distance\n"
11576 "Administrative distance\n"
11577 "IP source prefix\n")
11579 int idx_number
= 1;
11580 int idx_ipv4_prefixlen
= 2;
11581 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11582 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11583 return CMD_SUCCESS
;
11586 DEFUN (no_bgp_distance_source
,
11587 no_bgp_distance_source_cmd
,
11588 "no distance (1-255) A.B.C.D/M",
11590 "Define an administrative distance\n"
11591 "Administrative distance\n"
11592 "IP source prefix\n")
11594 int idx_number
= 2;
11595 int idx_ipv4_prefixlen
= 3;
11596 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11597 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11598 return CMD_SUCCESS
;
11601 DEFUN (bgp_distance_source_access_list
,
11602 bgp_distance_source_access_list_cmd
,
11603 "distance (1-255) A.B.C.D/M WORD",
11604 "Define an administrative distance\n"
11605 "Administrative distance\n"
11606 "IP source prefix\n"
11607 "Access list name\n")
11609 int idx_number
= 1;
11610 int idx_ipv4_prefixlen
= 2;
11612 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11613 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11614 return CMD_SUCCESS
;
11617 DEFUN (no_bgp_distance_source_access_list
,
11618 no_bgp_distance_source_access_list_cmd
,
11619 "no distance (1-255) A.B.C.D/M WORD",
11621 "Define an administrative distance\n"
11622 "Administrative distance\n"
11623 "IP source prefix\n"
11624 "Access list name\n")
11626 int idx_number
= 2;
11627 int idx_ipv4_prefixlen
= 3;
11629 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11630 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11631 return CMD_SUCCESS
;
11634 DEFUN (ipv6_bgp_distance_source
,
11635 ipv6_bgp_distance_source_cmd
,
11636 "distance (1-255) X:X::X:X/M",
11637 "Define an administrative distance\n"
11638 "Administrative distance\n"
11639 "IP source prefix\n")
11641 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11642 return CMD_SUCCESS
;
11645 DEFUN (no_ipv6_bgp_distance_source
,
11646 no_ipv6_bgp_distance_source_cmd
,
11647 "no distance (1-255) X:X::X:X/M",
11649 "Define an administrative distance\n"
11650 "Administrative distance\n"
11651 "IP source prefix\n")
11653 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11654 return CMD_SUCCESS
;
11657 DEFUN (ipv6_bgp_distance_source_access_list
,
11658 ipv6_bgp_distance_source_access_list_cmd
,
11659 "distance (1-255) X:X::X:X/M WORD",
11660 "Define an administrative distance\n"
11661 "Administrative distance\n"
11662 "IP source prefix\n"
11663 "Access list name\n")
11665 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11666 return CMD_SUCCESS
;
11669 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11670 no_ipv6_bgp_distance_source_access_list_cmd
,
11671 "no distance (1-255) X:X::X:X/M WORD",
11673 "Define an administrative distance\n"
11674 "Administrative distance\n"
11675 "IP source prefix\n"
11676 "Access list name\n")
11678 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11679 return CMD_SUCCESS
;
11682 DEFUN (bgp_damp_set
,
11684 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11685 "BGP Specific commands\n"
11686 "Enable route-flap dampening\n"
11687 "Half-life time for the penalty\n"
11688 "Value to start reusing a route\n"
11689 "Value to start suppressing a route\n"
11690 "Maximum duration to suppress a stable route\n")
11692 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11693 int idx_half_life
= 2;
11695 int idx_suppress
= 4;
11696 int idx_max_suppress
= 5;
11697 int half
= DEFAULT_HALF_LIFE
* 60;
11698 int reuse
= DEFAULT_REUSE
;
11699 int suppress
= DEFAULT_SUPPRESS
;
11700 int max
= 4 * half
;
11703 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11704 reuse
= atoi(argv
[idx_reuse
]->arg
);
11705 suppress
= atoi(argv
[idx_suppress
]->arg
);
11706 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11707 } else if (argc
== 3) {
11708 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11712 if (suppress
< reuse
) {
11714 "Suppress value cannot be less than reuse value \n");
11718 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11719 reuse
, suppress
, max
);
11722 DEFUN (bgp_damp_unset
,
11723 bgp_damp_unset_cmd
,
11724 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11726 "BGP Specific commands\n"
11727 "Enable route-flap dampening\n"
11728 "Half-life time for the penalty\n"
11729 "Value to start reusing a route\n"
11730 "Value to start suppressing a route\n"
11731 "Maximum duration to suppress a stable route\n")
11733 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11734 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11737 /* Display specified route of BGP table. */
11738 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11739 const char *ip_str
, afi_t afi
, safi_t safi
,
11740 struct prefix_rd
*prd
, int prefix_check
)
11743 struct prefix match
;
11744 struct bgp_node
*rn
;
11745 struct bgp_node
*rm
;
11746 struct bgp_path_info
*pi
;
11747 struct bgp_path_info
*pi_temp
;
11749 struct bgp_table
*table
;
11751 /* BGP structure lookup. */
11753 bgp
= bgp_lookup_by_name(view_name
);
11755 vty_out(vty
, "%% Can't find BGP instance %s\n",
11757 return CMD_WARNING
;
11760 bgp
= bgp_get_default();
11762 vty_out(vty
, "%% No BGP process is configured\n");
11763 return CMD_WARNING
;
11767 /* Check IP address argument. */
11768 ret
= str2prefix(ip_str
, &match
);
11770 vty_out(vty
, "%% address is malformed\n");
11771 return CMD_WARNING
;
11774 match
.family
= afi2family(afi
);
11776 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11777 || (safi
== SAFI_EVPN
)) {
11778 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11779 rn
= bgp_route_next(rn
)) {
11780 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11782 table
= bgp_node_get_bgp_table_info(rn
);
11785 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11789 || rm
->p
.prefixlen
== match
.prefixlen
) {
11790 pi
= bgp_node_get_bgp_path_info(rm
);
11792 if (pi
->extra
&& pi
->extra
->damp_info
) {
11793 pi_temp
= pi
->next
;
11794 bgp_damp_info_free(
11795 pi
->extra
->damp_info
,
11803 bgp_unlock_node(rm
);
11806 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11809 || rn
->p
.prefixlen
== match
.prefixlen
) {
11810 pi
= bgp_node_get_bgp_path_info(rn
);
11812 if (pi
->extra
&& pi
->extra
->damp_info
) {
11813 pi_temp
= pi
->next
;
11814 bgp_damp_info_free(
11815 pi
->extra
->damp_info
,
11823 bgp_unlock_node(rn
);
11827 return CMD_SUCCESS
;
11830 DEFUN (clear_ip_bgp_dampening
,
11831 clear_ip_bgp_dampening_cmd
,
11832 "clear ip bgp dampening",
11836 "Clear route flap dampening information\n")
11838 bgp_damp_info_clean();
11839 return CMD_SUCCESS
;
11842 DEFUN (clear_ip_bgp_dampening_prefix
,
11843 clear_ip_bgp_dampening_prefix_cmd
,
11844 "clear ip bgp dampening A.B.C.D/M",
11848 "Clear route flap dampening information\n"
11851 int idx_ipv4_prefixlen
= 4;
11852 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11853 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11856 DEFUN (clear_ip_bgp_dampening_address
,
11857 clear_ip_bgp_dampening_address_cmd
,
11858 "clear ip bgp dampening A.B.C.D",
11862 "Clear route flap dampening information\n"
11863 "Network to clear damping information\n")
11866 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11867 SAFI_UNICAST
, NULL
, 0);
11870 DEFUN (clear_ip_bgp_dampening_address_mask
,
11871 clear_ip_bgp_dampening_address_mask_cmd
,
11872 "clear ip bgp dampening A.B.C.D A.B.C.D",
11876 "Clear route flap dampening information\n"
11877 "Network to clear damping information\n"
11881 int idx_ipv4_2
= 5;
11883 char prefix_str
[BUFSIZ
];
11885 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11888 vty_out(vty
, "%% Inconsistent address and mask\n");
11889 return CMD_WARNING
;
11892 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11896 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
11898 struct vty
*vty
= arg
;
11899 struct peer
*peer
= bucket
->data
;
11900 char buf
[SU_ADDRSTRLEN
];
11902 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
11903 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
11906 DEFUN (show_bgp_peerhash
,
11907 show_bgp_peerhash_cmd
,
11908 "show bgp peerhash",
11911 "Display information about the BGP peerhash\n")
11913 struct list
*instances
= bm
->bgp
;
11914 struct listnode
*node
;
11917 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
11918 vty_out(vty
, "BGP: %s\n", bgp
->name
);
11919 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
11923 return CMD_SUCCESS
;
11926 /* also used for encap safi */
11927 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11928 afi_t afi
, safi_t safi
)
11930 struct bgp_node
*prn
;
11931 struct bgp_node
*rn
;
11932 struct bgp_table
*table
;
11934 struct prefix_rd
*prd
;
11935 struct bgp_static
*bgp_static
;
11936 mpls_label_t label
;
11937 char buf
[SU_ADDRSTRLEN
];
11938 char rdbuf
[RD_ADDRSTRLEN
];
11940 /* Network configuration. */
11941 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11942 prn
= bgp_route_next(prn
)) {
11943 table
= bgp_node_get_bgp_table_info(prn
);
11947 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11948 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11949 if (bgp_static
== NULL
)
11953 prd
= (struct prefix_rd
*)&prn
->p
;
11955 /* "network" configuration display. */
11956 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11957 label
= decode_label(&bgp_static
->label
);
11959 vty_out(vty
, " network %s/%d rd %s",
11960 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11962 p
->prefixlen
, rdbuf
);
11963 if (safi
== SAFI_MPLS_VPN
)
11964 vty_out(vty
, " label %u", label
);
11966 if (bgp_static
->rmap
.name
)
11967 vty_out(vty
, " route-map %s",
11968 bgp_static
->rmap
.name
);
11970 if (bgp_static
->backdoor
)
11971 vty_out(vty
, " backdoor");
11973 vty_out(vty
, "\n");
11978 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11979 afi_t afi
, safi_t safi
)
11981 struct bgp_node
*prn
;
11982 struct bgp_node
*rn
;
11983 struct bgp_table
*table
;
11985 struct prefix_rd
*prd
;
11986 struct bgp_static
*bgp_static
;
11987 char buf
[PREFIX_STRLEN
* 2];
11988 char buf2
[SU_ADDRSTRLEN
];
11989 char rdbuf
[RD_ADDRSTRLEN
];
11991 /* Network configuration. */
11992 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11993 prn
= bgp_route_next(prn
)) {
11994 table
= bgp_node_get_bgp_table_info(prn
);
11998 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11999 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12000 if (bgp_static
== NULL
)
12003 char *macrouter
= NULL
;
12006 if (bgp_static
->router_mac
)
12007 macrouter
= prefix_mac2str(
12008 bgp_static
->router_mac
, NULL
, 0);
12009 if (bgp_static
->eth_s_id
)
12010 esi
= esi2str(bgp_static
->eth_s_id
);
12012 prd
= (struct prefix_rd
*)&prn
->p
;
12014 /* "network" configuration display. */
12015 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12016 if (p
->u
.prefix_evpn
.route_type
== 5) {
12017 char local_buf
[PREFIX_STRLEN
];
12018 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12019 struct prefix_evpn
*)p
)
12023 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12024 local_buf
, PREFIX_STRLEN
);
12025 sprintf(buf
, "%s/%u", local_buf
,
12026 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12028 prefix2str(p
, buf
, sizeof(buf
));
12031 if (bgp_static
->gatewayIp
.family
== AF_INET
12032 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12033 inet_ntop(bgp_static
->gatewayIp
.family
,
12034 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12037 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12039 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12040 decode_label(&bgp_static
->label
), esi
, buf2
,
12043 XFREE(MTYPE_TMP
, macrouter
);
12044 XFREE(MTYPE_TMP
, esi
);
12049 /* Configuration of static route announcement and aggregate
12051 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12054 struct bgp_node
*rn
;
12056 struct bgp_static
*bgp_static
;
12057 struct bgp_aggregate
*bgp_aggregate
;
12058 char buf
[SU_ADDRSTRLEN
];
12060 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12061 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12065 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12066 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12070 /* Network configuration. */
12071 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12072 rn
= bgp_route_next(rn
)) {
12073 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12074 if (bgp_static
== NULL
)
12079 /* "network" configuration display. */
12080 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
12081 uint32_t destination
;
12082 struct in_addr netmask
;
12084 destination
= ntohl(p
->u
.prefix4
.s_addr
);
12085 masklen2ip(p
->prefixlen
, &netmask
);
12086 vty_out(vty
, " network %s",
12087 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12090 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
12091 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
12092 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
12093 || p
->u
.prefix4
.s_addr
== 0) {
12094 /* Natural mask is not display. */
12096 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
12098 vty_out(vty
, " network %s/%d",
12099 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12104 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12105 vty_out(vty
, " label-index %u",
12106 bgp_static
->label_index
);
12108 if (bgp_static
->rmap
.name
)
12109 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12111 if (bgp_static
->backdoor
)
12112 vty_out(vty
, " backdoor");
12114 vty_out(vty
, "\n");
12117 /* Aggregate-address configuration. */
12118 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12119 rn
= bgp_route_next(rn
)) {
12120 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12121 if (bgp_aggregate
== NULL
)
12126 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
12127 struct in_addr netmask
;
12129 masklen2ip(p
->prefixlen
, &netmask
);
12130 vty_out(vty
, " aggregate-address %s %s",
12131 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12133 inet_ntoa(netmask
));
12135 vty_out(vty
, " aggregate-address %s/%d",
12136 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12141 if (bgp_aggregate
->as_set
)
12142 vty_out(vty
, " as-set");
12144 if (bgp_aggregate
->summary_only
)
12145 vty_out(vty
, " summary-only");
12147 vty_out(vty
, "\n");
12151 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12154 struct bgp_node
*rn
;
12155 struct bgp_distance
*bdistance
;
12157 /* Distance configuration. */
12158 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12159 && bgp
->distance_local
[afi
][safi
]
12160 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12161 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12162 || bgp
->distance_local
[afi
][safi
]
12163 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12164 vty_out(vty
, " distance bgp %d %d %d\n",
12165 bgp
->distance_ebgp
[afi
][safi
],
12166 bgp
->distance_ibgp
[afi
][safi
],
12167 bgp
->distance_local
[afi
][safi
]);
12170 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12171 rn
= bgp_route_next(rn
)) {
12172 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12173 if (bdistance
!= NULL
) {
12174 char buf
[PREFIX_STRLEN
];
12176 vty_out(vty
, " distance %d %s %s\n",
12177 bdistance
->distance
,
12178 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12179 bdistance
->access_list
? bdistance
->access_list
12185 /* Allocate routing table structure and install commands. */
12186 void bgp_route_init(void)
12191 /* Init BGP distance table. */
12192 FOREACH_AFI_SAFI (afi
, safi
)
12193 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12195 /* IPv4 BGP commands. */
12196 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12197 install_element(BGP_NODE
, &bgp_network_cmd
);
12198 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12200 install_element(BGP_NODE
, &aggregate_address_cmd
);
12201 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12202 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12203 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12205 /* IPv4 unicast configuration. */
12206 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12207 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12208 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12210 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12211 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12212 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12213 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12215 /* IPv4 multicast configuration. */
12216 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12217 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12218 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12219 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12220 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12221 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12222 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12224 /* IPv4 labeled-unicast configuration. */
12225 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12226 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12227 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12228 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12229 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12231 install_element(VIEW_NODE
,
12232 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12233 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12234 install_element(VIEW_NODE
,
12235 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12236 #ifdef KEEP_OLD_VPN_COMMANDS
12237 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12238 #endif /* KEEP_OLD_VPN_COMMANDS */
12239 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12240 install_element(VIEW_NODE
,
12241 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
12243 /* BGP dampening clear commands */
12244 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12245 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12247 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12248 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12251 install_element(ENABLE_NODE
,
12252 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12253 #ifdef KEEP_OLD_VPN_COMMANDS
12254 install_element(ENABLE_NODE
,
12255 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12256 #endif /* KEEP_OLD_VPN_COMMANDS */
12258 /* New config IPv6 BGP commands. */
12259 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12260 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12261 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12263 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12264 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12266 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12268 install_element(BGP_NODE
, &bgp_distance_cmd
);
12269 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12270 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12271 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12272 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12273 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12274 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12275 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12276 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12277 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12278 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12279 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12280 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12281 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12282 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12283 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12284 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12285 install_element(BGP_IPV4M_NODE
,
12286 &no_bgp_distance_source_access_list_cmd
);
12287 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12288 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12289 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12290 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12291 install_element(BGP_IPV6_NODE
,
12292 &ipv6_bgp_distance_source_access_list_cmd
);
12293 install_element(BGP_IPV6_NODE
,
12294 &no_ipv6_bgp_distance_source_access_list_cmd
);
12295 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12296 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12297 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12298 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12299 install_element(BGP_IPV6M_NODE
,
12300 &ipv6_bgp_distance_source_access_list_cmd
);
12301 install_element(BGP_IPV6M_NODE
,
12302 &no_ipv6_bgp_distance_source_access_list_cmd
);
12304 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12305 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12306 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12307 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12309 /* IPv4 Multicast Mode */
12310 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12311 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12313 /* Large Communities */
12314 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12315 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12317 /* show bgp ipv4 flowspec detailed */
12318 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12320 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12323 void bgp_route_finish(void)
12328 FOREACH_AFI_SAFI (afi
, safi
) {
12329 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12330 bgp_distance_table
[afi
][safi
] = NULL
;