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
) && new_select
&&
2480 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2482 /* apply the route-map */
2483 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2486 ret
= route_map_apply(
2487 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2488 &rn
->p
, RMAP_BGP
, new_select
);
2489 if (ret
== RMAP_MATCH
)
2490 bgp_evpn_advertise_type5_route(
2491 bgp
, &rn
->p
, new_select
->attr
,
2494 bgp_evpn_withdraw_type5_route(
2495 bgp
, &rn
->p
, afi
, safi
);
2497 bgp_evpn_advertise_type5_route(bgp
,
2503 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2504 (!old_select
->extra
|| !old_select
->extra
->parent
))
2505 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2508 /* Clear any route change flags. */
2509 bgp_zebra_clear_route_change_flags(rn
);
2511 /* Reap old select bgp_path_info, if it has been removed */
2512 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2513 bgp_path_info_reap(rn
, old_select
);
2515 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2519 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2521 struct bgp_process_queue
*pqnode
= data
;
2522 struct bgp
*bgp
= pqnode
->bgp
;
2523 struct bgp_table
*table
;
2524 struct bgp_node
*rn
;
2527 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2528 bgp_process_main_one(bgp
, NULL
, 0, 0);
2529 /* should always have dedicated wq call */
2530 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2534 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2535 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2536 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2537 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2538 table
= bgp_node_table(rn
);
2539 /* note, new RNs may be added as part of processing */
2540 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2542 bgp_unlock_node(rn
);
2543 bgp_table_unlock(table
);
2549 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2551 struct bgp_process_queue
*pqnode
= data
;
2553 bgp_unlock(pqnode
->bgp
);
2555 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2558 void bgp_process_queue_init(void)
2560 if (!bm
->process_main_queue
)
2561 bm
->process_main_queue
=
2562 work_queue_new(bm
->master
, "process_main_queue");
2564 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2565 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2566 bm
->process_main_queue
->spec
.max_retries
= 0;
2567 bm
->process_main_queue
->spec
.hold
= 50;
2568 /* Use a higher yield value of 50ms for main queue processing */
2569 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2572 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2574 struct bgp_process_queue
*pqnode
;
2576 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2577 sizeof(struct bgp_process_queue
));
2579 /* unlocked in bgp_processq_del */
2580 pqnode
->bgp
= bgp_lock(bgp
);
2581 STAILQ_INIT(&pqnode
->pqueue
);
2586 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2588 #define ARBITRARY_PROCESS_QLEN 10000
2589 struct work_queue
*wq
= bm
->process_main_queue
;
2590 struct bgp_process_queue
*pqnode
;
2591 int pqnode_reuse
= 0;
2593 /* already scheduled for processing? */
2594 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2600 /* Add route nodes to an existing work queue item until reaching the
2601 limit only if is from the same BGP view and it's not an EOIU marker
2603 if (work_queue_item_count(wq
)) {
2604 struct work_queue_item
*item
= work_queue_last_item(wq
);
2605 pqnode
= item
->data
;
2607 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2608 || pqnode
->bgp
!= bgp
2609 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2610 pqnode
= bgp_processq_alloc(bgp
);
2614 pqnode
= bgp_processq_alloc(bgp
);
2615 /* all unlocked in bgp_process_wq */
2616 bgp_table_lock(bgp_node_table(rn
));
2618 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2621 /* can't be enqueued twice */
2622 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2623 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2627 work_queue_add(wq
, pqnode
);
2632 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2634 struct bgp_process_queue
*pqnode
;
2636 if (bm
->process_main_queue
== NULL
)
2639 pqnode
= bgp_processq_alloc(bgp
);
2641 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2642 work_queue_add(bm
->process_main_queue
, pqnode
);
2645 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2649 peer
= THREAD_ARG(thread
);
2650 peer
->t_pmax_restart
= NULL
;
2652 if (bgp_debug_neighbor_events(peer
))
2654 "%s Maximum-prefix restart timer expired, restore peering",
2657 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2658 zlog_debug("%s: %s peer_clear failed",
2659 __PRETTY_FUNCTION__
, peer
->host
);
2664 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2668 iana_safi_t pkt_safi
;
2670 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2673 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2674 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2675 PEER_STATUS_PREFIX_LIMIT
)
2680 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2682 afi_safi_print(afi
, safi
), peer
->host
,
2683 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2684 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2686 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2687 PEER_FLAG_MAX_PREFIX_WARNING
))
2690 /* Convert AFI, SAFI to values for packet. */
2691 pkt_afi
= afi_int2iana(afi
);
2692 pkt_safi
= safi_int2iana(safi
);
2696 ndata
[0] = (pkt_afi
>> 8);
2698 ndata
[2] = pkt_safi
;
2699 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2700 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2701 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2702 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2704 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2705 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2706 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2710 /* Dynamic peers will just close their connection. */
2711 if (peer_dynamic_neighbor(peer
))
2714 /* restart timer start */
2715 if (peer
->pmax_restart
[afi
][safi
]) {
2716 peer
->v_pmax_restart
=
2717 peer
->pmax_restart
[afi
][safi
] * 60;
2719 if (bgp_debug_neighbor_events(peer
))
2721 "%s Maximum-prefix restart timer started for %d secs",
2722 peer
->host
, peer
->v_pmax_restart
);
2724 BGP_TIMER_ON(peer
->t_pmax_restart
,
2725 bgp_maximum_prefix_restart_timer
,
2726 peer
->v_pmax_restart
);
2731 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2732 PEER_STATUS_PREFIX_LIMIT
);
2734 if (peer
->pcount
[afi
][safi
]
2735 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2736 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2737 PEER_STATUS_PREFIX_THRESHOLD
)
2742 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2743 afi_safi_print(afi
, safi
), peer
->host
,
2744 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2745 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2746 PEER_STATUS_PREFIX_THRESHOLD
);
2748 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2749 PEER_STATUS_PREFIX_THRESHOLD
);
2753 /* Unconditionally remove the route from the RIB, without taking
2754 * damping into consideration (eg, because the session went down)
2756 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2757 struct peer
*peer
, afi_t afi
, safi_t safi
)
2759 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2761 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2762 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2764 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2767 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2768 struct peer
*peer
, afi_t afi
, safi_t safi
,
2769 struct prefix_rd
*prd
)
2771 /* apply dampening, if result is suppressed, we'll be retaining
2772 * the bgp_path_info in the RIB for historical reference.
2774 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2775 && peer
->sort
== BGP_PEER_EBGP
)
2776 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2777 == BGP_DAMP_SUPPRESSED
) {
2778 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2784 if (safi
== SAFI_MPLS_VPN
) {
2785 struct bgp_node
*prn
= NULL
;
2786 struct bgp_table
*table
= NULL
;
2788 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2789 (struct prefix
*)prd
);
2790 if (bgp_node_has_bgp_path_info_data(prn
)) {
2791 table
= bgp_node_get_bgp_table_info(prn
);
2793 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2794 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2796 bgp_unlock_node(prn
);
2798 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2799 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2801 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2802 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2808 /* If this is an EVPN route, process for un-import. */
2809 if (safi
== SAFI_EVPN
)
2810 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2812 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2815 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2816 struct peer
*peer
, struct attr
*attr
,
2817 struct bgp_node
*rn
)
2819 struct bgp_path_info
*new;
2821 /* Make new BGP info. */
2822 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2824 new->instance
= instance
;
2825 new->sub_type
= sub_type
;
2828 new->uptime
= bgp_clock();
2833 static void overlay_index_update(struct attr
*attr
,
2834 struct eth_segment_id
*eth_s_id
,
2835 union gw_addr
*gw_ip
)
2840 if (eth_s_id
== NULL
) {
2841 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2842 sizeof(struct eth_segment_id
));
2844 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2845 sizeof(struct eth_segment_id
));
2847 if (gw_ip
== NULL
) {
2848 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2850 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2851 sizeof(union gw_addr
));
2855 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2856 struct eth_segment_id
*eth_s_id
,
2857 union gw_addr
*gw_ip
)
2859 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2860 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2862 struct eth_segment_id esi
;
2866 if (afi
!= AFI_L2VPN
)
2869 memset(&temp
, 0, sizeof(temp
));
2870 path_eth_s_id
= &temp
.esi
;
2871 path_gw_ip
= &temp
.ip
;
2873 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2876 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2877 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2880 if (gw_ip
== NULL
) {
2881 memset(&temp
, 0, sizeof(temp
));
2882 path_gw_ip_remote
= &temp
.ip
;
2884 path_gw_ip_remote
= gw_ip
;
2886 if (eth_s_id
== NULL
) {
2887 memset(&temp
, 0, sizeof(temp
));
2888 path_eth_s_id_remote
= &temp
.esi
;
2890 path_eth_s_id_remote
= eth_s_id
;
2892 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2895 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2896 sizeof(struct eth_segment_id
));
2899 /* Check if received nexthop is valid or not. */
2900 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2905 /* Only validated for unicast and multicast currently. */
2906 /* Also valid for EVPN where the nexthop is an IP address. */
2907 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2910 /* If NEXT_HOP is present, validate it. */
2911 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2912 if (attr
->nexthop
.s_addr
== 0
2913 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2914 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2918 /* If MP_NEXTHOP is present, validate it. */
2919 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2920 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2921 * it is not an IPv6 link-local address.
2923 if (attr
->mp_nexthop_len
) {
2924 switch (attr
->mp_nexthop_len
) {
2925 case BGP_ATTR_NHLEN_IPV4
:
2926 case BGP_ATTR_NHLEN_VPNV4
:
2927 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2928 || IPV4_CLASS_DE(ntohl(
2929 attr
->mp_nexthop_global_in
.s_addr
))
2930 || bgp_nexthop_self(bgp
,
2931 attr
->mp_nexthop_global_in
));
2934 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2935 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2936 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2937 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2938 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2939 || IN6_IS_ADDR_MULTICAST(
2940 &attr
->mp_nexthop_global
));
2952 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2953 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2954 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2955 uint32_t num_labels
, int soft_reconfig
,
2956 struct bgp_route_evpn
*evpn
)
2959 int aspath_loop_count
= 0;
2960 struct bgp_node
*rn
;
2962 struct attr new_attr
;
2963 struct attr
*attr_new
;
2964 struct bgp_path_info
*pi
;
2965 struct bgp_path_info
*new;
2966 struct bgp_path_info_extra
*extra
;
2968 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2970 int do_loop_check
= 1;
2971 int has_valid_label
= 0;
2973 int vnc_implicit_withdraw
= 0;
2977 memset(&new_attr
, 0, sizeof(struct attr
));
2978 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2979 new_attr
.label
= MPLS_INVALID_LABEL
;
2982 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2983 /* TODO: Check to see if we can get rid of "is_valid_label" */
2984 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2985 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2987 has_valid_label
= bgp_is_valid_label(label
);
2989 /* When peer's soft reconfiguration enabled. Record input packet in
2992 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2993 && peer
!= bgp
->peer_self
)
2994 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2996 /* Check previously received route. */
2997 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
2998 if (pi
->peer
== peer
&& pi
->type
== type
2999 && pi
->sub_type
== sub_type
3000 && pi
->addpath_rx_id
== addpath_id
)
3003 /* AS path local-as loop check. */
3004 if (peer
->change_local_as
) {
3005 if (peer
->allowas_in
[afi
][safi
])
3006 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3007 else if (!CHECK_FLAG(peer
->flags
,
3008 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3009 aspath_loop_count
= 1;
3011 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3012 > aspath_loop_count
) {
3013 reason
= "as-path contains our own AS;";
3018 /* If the peer is configured for "allowas-in origin" and the last ASN in
3020 * as-path is our ASN then we do not need to call aspath_loop_check
3022 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3023 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3026 /* AS path loop check. */
3027 if (do_loop_check
) {
3028 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3029 > peer
->allowas_in
[afi
][safi
]
3030 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3031 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3032 > peer
->allowas_in
[afi
][safi
])) {
3033 reason
= "as-path contains our own AS;";
3038 /* Route reflector originator ID check. */
3039 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3040 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3041 reason
= "originator is us;";
3045 /* Route reflector cluster ID check. */
3046 if (bgp_cluster_filter(peer
, attr
)) {
3047 reason
= "reflected from the same cluster;";
3051 /* Apply incoming filter. */
3052 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3057 bgp_attr_dup(&new_attr
, attr
);
3059 /* Apply incoming route-map.
3060 * NB: new_attr may now contain newly allocated values from route-map
3062 * commands, so we need bgp_attr_flush in the error paths, until we
3064 * the attr (which takes over the memory references) */
3065 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3067 reason
= "route-map;";
3068 bgp_attr_flush(&new_attr
);
3072 if (peer
->sort
== BGP_PEER_EBGP
) {
3074 /* If we receive the graceful-shutdown community from an eBGP
3075 * peer we must lower local-preference */
3076 if (new_attr
.community
3077 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3078 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3079 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3081 /* If graceful-shutdown is configured then add the GSHUT
3082 * community to all paths received from eBGP peers */
3083 } else if (bgp_flag_check(peer
->bgp
,
3084 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3085 bgp_attr_add_gshut_community(&new_attr
);
3089 /* next hop check. */
3090 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3091 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3092 reason
= "martian or self next-hop;";
3093 bgp_attr_flush(&new_attr
);
3097 if (bgp_mac_entry_exists(p
)) {
3098 reason
= "self mac;";
3102 attr_new
= bgp_attr_intern(&new_attr
);
3104 /* If the update is implicit withdraw. */
3106 pi
->uptime
= bgp_clock();
3107 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3109 /* Same attribute comes in. */
3110 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3111 && attrhash_cmp(pi
->attr
, attr_new
)
3112 && (!has_valid_label
3113 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3114 num_labels
* sizeof(mpls_label_t
))
3116 && (overlay_index_equal(
3117 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3118 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3119 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3120 BGP_CONFIG_DAMPENING
)
3121 && peer
->sort
== BGP_PEER_EBGP
3122 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3123 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3124 bgp_debug_rdpfxpath2str(
3125 afi
, safi
, prd
, p
, label
,
3126 num_labels
, addpath_id
? 1 : 0,
3127 addpath_id
, pfx_buf
,
3129 zlog_debug("%s rcvd %s", peer
->host
,
3133 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3134 != BGP_DAMP_SUPPRESSED
) {
3135 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3137 bgp_process(bgp
, rn
, afi
, safi
);
3139 } else /* Duplicate - odd */
3141 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3142 if (!peer
->rcvd_attr_printed
) {
3144 "%s rcvd UPDATE w/ attr: %s",
3146 peer
->rcvd_attr_str
);
3147 peer
->rcvd_attr_printed
= 1;
3150 bgp_debug_rdpfxpath2str(
3151 afi
, safi
, prd
, p
, label
,
3152 num_labels
, addpath_id
? 1 : 0,
3153 addpath_id
, pfx_buf
,
3156 "%s rcvd %s...duplicate ignored",
3157 peer
->host
, pfx_buf
);
3160 /* graceful restart STALE flag unset. */
3161 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3162 bgp_path_info_unset_flag(
3163 rn
, pi
, BGP_PATH_STALE
);
3164 bgp_process(bgp
, rn
, afi
, safi
);
3168 bgp_unlock_node(rn
);
3169 bgp_attr_unintern(&attr_new
);
3174 /* Withdraw/Announce before we fully processed the withdraw */
3175 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3176 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3177 bgp_debug_rdpfxpath2str(
3178 afi
, safi
, prd
, p
, label
, num_labels
,
3179 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3182 "%s rcvd %s, flapped quicker than processing",
3183 peer
->host
, pfx_buf
);
3186 bgp_path_info_restore(rn
, pi
);
3189 /* Received Logging. */
3190 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3191 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3192 num_labels
, addpath_id
? 1 : 0,
3193 addpath_id
, pfx_buf
,
3195 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3198 /* graceful restart STALE flag unset. */
3199 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3200 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3202 /* The attribute is changed. */
3203 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3205 /* implicit withdraw, decrement aggregate and pcount here.
3206 * only if update is accepted, they'll increment below.
3208 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3210 /* Update bgp route dampening information. */
3211 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3212 && peer
->sort
== BGP_PEER_EBGP
) {
3213 /* This is implicit withdraw so we should update
3216 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3217 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3220 if (safi
== SAFI_MPLS_VPN
) {
3221 struct bgp_node
*prn
= NULL
;
3222 struct bgp_table
*table
= NULL
;
3224 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3225 (struct prefix
*)prd
);
3226 if (bgp_node_has_bgp_path_info_data(prn
)) {
3227 table
= bgp_node_get_bgp_table_info(prn
);
3229 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3230 bgp
, prd
, table
, p
, pi
);
3232 bgp_unlock_node(prn
);
3234 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3235 && (safi
== SAFI_UNICAST
)) {
3236 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3238 * Implicit withdraw case.
3240 ++vnc_implicit_withdraw
;
3241 vnc_import_bgp_del_route(bgp
, p
, pi
);
3242 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3247 /* Special handling for EVPN update of an existing route. If the
3248 * extended community attribute has changed, we need to
3250 * the route using its existing extended community. It will be
3251 * subsequently processed for import with the new extended
3254 if (safi
== SAFI_EVPN
&& !same_attr
) {
3256 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3258 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3261 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3262 attr_new
->ecommunity
);
3264 if (bgp_debug_update(peer
, p
, NULL
, 1))
3266 "Change in EXT-COMM, existing %s new %s",
3268 pi
->attr
->ecommunity
),
3270 attr_new
->ecommunity
));
3271 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3277 /* Update to new attribute. */
3278 bgp_attr_unintern(&pi
->attr
);
3279 pi
->attr
= attr_new
;
3281 /* Update MPLS label */
3282 if (has_valid_label
) {
3283 extra
= bgp_path_info_extra_get(pi
);
3284 if (extra
->label
!= label
) {
3285 memcpy(&extra
->label
, label
,
3286 num_labels
* sizeof(mpls_label_t
));
3287 extra
->num_labels
= num_labels
;
3289 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3290 bgp_set_valid_label(&extra
->label
[0]);
3294 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3295 && (safi
== SAFI_UNICAST
)) {
3296 if (vnc_implicit_withdraw
) {
3298 * Add back the route with its new attributes
3300 * The route is still selected, until the route
3302 * queued by bgp_process actually runs. We have
3304 * update to the VNC side immediately to avoid
3306 * configuration changes (e.g., route-map
3308 * trigger re-importation of the entire RIB.
3310 vnc_import_bgp_add_route(bgp
, p
, pi
);
3311 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3315 /* Update Overlay Index */
3316 if (afi
== AFI_L2VPN
) {
3317 overlay_index_update(
3318 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3319 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3322 /* Update bgp route dampening information. */
3323 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3324 && peer
->sort
== BGP_PEER_EBGP
) {
3325 /* Now we do normal update dampening. */
3326 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3327 if (ret
== BGP_DAMP_SUPPRESSED
) {
3328 bgp_unlock_node(rn
);
3333 /* Nexthop reachability check - for unicast and
3334 * labeled-unicast.. */
3335 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3336 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3337 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3338 && !CHECK_FLAG(peer
->flags
,
3339 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3341 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3346 struct bgp
*bgp_nexthop
= bgp
;
3348 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3349 bgp_nexthop
= pi
->extra
->bgp_orig
;
3351 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3353 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3354 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3356 if (BGP_DEBUG(nht
, NHT
)) {
3357 char buf1
[INET6_ADDRSTRLEN
];
3359 (const void *)&attr_new
3361 buf1
, INET6_ADDRSTRLEN
);
3362 zlog_debug("%s(%s): NH unresolved",
3363 __FUNCTION__
, buf1
);
3365 bgp_path_info_unset_flag(rn
, pi
,
3369 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3372 if (safi
== SAFI_MPLS_VPN
) {
3373 struct bgp_node
*prn
= NULL
;
3374 struct bgp_table
*table
= NULL
;
3376 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3377 (struct prefix
*)prd
);
3378 if (bgp_node_has_bgp_path_info_data(prn
)) {
3379 table
= bgp_node_get_bgp_table_info(prn
);
3381 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3382 bgp
, prd
, table
, p
, pi
);
3384 bgp_unlock_node(prn
);
3388 /* If this is an EVPN route and some attribute has changed,
3390 * route for import. If the extended community has changed, we
3392 * have done the un-import earlier and the import would result
3394 * route getting injected into appropriate L2 VNIs. If it is
3396 * some other attribute change, the import will result in
3398 * the attributes for the route in the VNI(s).
3400 if (safi
== SAFI_EVPN
&& !same_attr
)
3401 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3403 /* Process change. */
3404 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3406 bgp_process(bgp
, rn
, afi
, safi
);
3407 bgp_unlock_node(rn
);
3409 if (SAFI_UNICAST
== safi
3410 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3411 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3413 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3415 if ((SAFI_MPLS_VPN
== safi
)
3416 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3418 vpn_leak_to_vrf_update(bgp
, pi
);
3422 if (SAFI_MPLS_VPN
== safi
) {
3423 mpls_label_t label_decoded
= decode_label(label
);
3425 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3426 type
, sub_type
, &label_decoded
);
3428 if (SAFI_ENCAP
== safi
) {
3429 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3430 type
, sub_type
, NULL
);
3435 } // End of implicit withdraw
3437 /* Received Logging. */
3438 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3439 if (!peer
->rcvd_attr_printed
) {
3440 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3441 peer
->rcvd_attr_str
);
3442 peer
->rcvd_attr_printed
= 1;
3445 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3446 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3448 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3451 /* Make new BGP info. */
3452 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3454 /* Update MPLS label */
3455 if (has_valid_label
) {
3456 extra
= bgp_path_info_extra_get(new);
3457 if (extra
->label
!= label
) {
3458 memcpy(&extra
->label
, label
,
3459 num_labels
* sizeof(mpls_label_t
));
3460 extra
->num_labels
= num_labels
;
3462 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3463 bgp_set_valid_label(&extra
->label
[0]);
3466 /* Update Overlay Index */
3467 if (afi
== AFI_L2VPN
) {
3468 overlay_index_update(new->attr
,
3469 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3470 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3472 /* Nexthop reachability check. */
3473 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3474 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3475 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3476 && !CHECK_FLAG(peer
->flags
,
3477 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3478 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3483 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3484 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3485 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3487 if (BGP_DEBUG(nht
, NHT
)) {
3488 char buf1
[INET6_ADDRSTRLEN
];
3490 (const void *)&attr_new
->nexthop
,
3491 buf1
, INET6_ADDRSTRLEN
);
3492 zlog_debug("%s(%s): NH unresolved",
3493 __FUNCTION__
, buf1
);
3495 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3498 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3501 new->addpath_rx_id
= addpath_id
;
3503 /* Increment prefix */
3504 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3506 /* Register new BGP information. */
3507 bgp_path_info_add(rn
, new);
3509 /* route_node_get lock */
3510 bgp_unlock_node(rn
);
3513 if (safi
== SAFI_MPLS_VPN
) {
3514 struct bgp_node
*prn
= NULL
;
3515 struct bgp_table
*table
= NULL
;
3517 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3518 if (bgp_node_has_bgp_path_info_data(prn
)) {
3519 table
= bgp_node_get_bgp_table_info(prn
);
3521 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3522 bgp
, prd
, table
, p
, new);
3524 bgp_unlock_node(prn
);
3528 /* If maximum prefix count is configured and current prefix
3530 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3533 /* If this is an EVPN route, process for import. */
3534 if (safi
== SAFI_EVPN
)
3535 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3537 /* Process change. */
3538 bgp_process(bgp
, rn
, afi
, safi
);
3540 if (SAFI_UNICAST
== safi
3541 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3542 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3543 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3545 if ((SAFI_MPLS_VPN
== safi
)
3546 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3548 vpn_leak_to_vrf_update(bgp
, new);
3551 if (SAFI_MPLS_VPN
== safi
) {
3552 mpls_label_t label_decoded
= decode_label(label
);
3554 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3555 sub_type
, &label_decoded
);
3557 if (SAFI_ENCAP
== safi
) {
3558 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3565 /* This BGP update is filtered. Log the reason then update BGP
3568 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3569 if (!peer
->rcvd_attr_printed
) {
3570 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3571 peer
->rcvd_attr_str
);
3572 peer
->rcvd_attr_printed
= 1;
3575 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3576 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3578 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3579 peer
->host
, pfx_buf
, reason
);
3583 /* If this is an EVPN route, un-import it as it is now filtered.
3585 if (safi
== SAFI_EVPN
)
3586 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3588 if (SAFI_UNICAST
== safi
3589 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3590 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3592 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3594 if ((SAFI_MPLS_VPN
== safi
)
3595 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3597 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3600 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3603 bgp_unlock_node(rn
);
3607 * Filtered update is treated as an implicit withdrawal (see
3609 * a few lines above)
3611 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3612 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3620 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3621 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3622 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3623 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3626 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3627 struct bgp_node
*rn
;
3628 struct bgp_path_info
*pi
;
3631 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3632 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3640 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3642 /* If peer is soft reconfiguration enabled. Record input packet for
3643 * further calculation.
3645 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3646 * routes that are filtered. This tanks out Quagga RS pretty badly due
3648 * the iteration over all RS clients.
3649 * Since we need to remove the entry from adj_in anyway, do that first
3651 * if there was no entry, we don't need to do anything more.
3653 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3654 && peer
!= bgp
->peer_self
)
3655 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3656 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3657 bgp_debug_rdpfxpath2str(
3658 afi
, safi
, prd
, p
, label
, num_labels
,
3659 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3662 "%s withdrawing route %s not in adj-in",
3663 peer
->host
, pfx_buf
);
3665 bgp_unlock_node(rn
);
3669 /* Lookup withdrawn route. */
3670 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3671 if (pi
->peer
== peer
&& pi
->type
== type
3672 && pi
->sub_type
== sub_type
3673 && pi
->addpath_rx_id
== addpath_id
)
3677 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3678 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3679 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3681 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3685 /* Withdraw specified route from routing table. */
3686 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3687 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3688 if (SAFI_UNICAST
== safi
3689 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3690 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3691 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3693 if ((SAFI_MPLS_VPN
== safi
)
3694 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3696 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3698 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3699 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3700 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3702 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3705 /* Unlock bgp_node_get() lock. */
3706 bgp_unlock_node(rn
);
3711 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3714 struct update_subgroup
*subgrp
;
3715 subgrp
= peer_subgroup(peer
, afi
, safi
);
3716 subgroup_default_originate(subgrp
, withdraw
);
3721 * bgp_stop_announce_route_timer
3723 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3725 if (!paf
->t_announce_route
)
3728 THREAD_TIMER_OFF(paf
->t_announce_route
);
3732 * bgp_announce_route_timer_expired
3734 * Callback that is invoked when the route announcement timer for a
3737 static int bgp_announce_route_timer_expired(struct thread
*t
)
3739 struct peer_af
*paf
;
3742 paf
= THREAD_ARG(t
);
3745 if (peer
->status
!= Established
)
3748 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3751 peer_af_announce_route(paf
, 1);
3756 * bgp_announce_route
3758 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3760 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3762 struct peer_af
*paf
;
3763 struct update_subgroup
*subgrp
;
3765 paf
= peer_af_find(peer
, afi
, safi
);
3768 subgrp
= PAF_SUBGRP(paf
);
3771 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3772 * or a refresh has already been triggered.
3774 if (!subgrp
|| paf
->t_announce_route
)
3778 * Start a timer to stagger/delay the announce. This serves
3779 * two purposes - announcement can potentially be combined for
3780 * multiple peers and the announcement doesn't happen in the
3783 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3784 (subgrp
->peer_count
== 1)
3785 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3786 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3787 &paf
->t_announce_route
);
3791 * Announce routes from all AF tables to a peer.
3793 * This should ONLY be called when there is a need to refresh the
3794 * routes to the peer based on a policy change for this peer alone
3795 * or a route refresh request received from the peer.
3796 * The operation will result in splitting the peer from its existing
3797 * subgroups and putting it in new subgroups.
3799 void bgp_announce_route_all(struct peer
*peer
)
3804 FOREACH_AFI_SAFI (afi
, safi
)
3805 bgp_announce_route(peer
, afi
, safi
);
3808 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3809 struct bgp_table
*table
,
3810 struct prefix_rd
*prd
)
3813 struct bgp_node
*rn
;
3814 struct bgp_adj_in
*ain
;
3817 table
= peer
->bgp
->rib
[afi
][safi
];
3819 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3820 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3821 if (ain
->peer
!= peer
)
3824 struct bgp_path_info
*pi
=
3825 bgp_node_get_bgp_path_info(rn
);
3826 uint32_t num_labels
= 0;
3827 mpls_label_t
*label_pnt
= NULL
;
3828 struct bgp_route_evpn evpn
;
3830 if (pi
&& pi
->extra
)
3831 num_labels
= pi
->extra
->num_labels
;
3833 label_pnt
= &pi
->extra
->label
[0];
3835 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3838 memset(&evpn
, 0, sizeof(evpn
));
3840 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3841 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3842 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3843 num_labels
, 1, &evpn
);
3846 bgp_unlock_node(rn
);
3852 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3854 struct bgp_node
*rn
;
3855 struct bgp_table
*table
;
3857 if (peer
->status
!= Established
)
3860 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3861 && (safi
!= SAFI_EVPN
))
3862 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3864 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3865 rn
= bgp_route_next(rn
)) {
3866 table
= bgp_node_get_bgp_table_info(rn
);
3867 if (table
!= NULL
) {
3868 struct prefix_rd prd
;
3870 prd
.family
= AF_UNSPEC
;
3872 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3874 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3881 struct bgp_clear_node_queue
{
3882 struct bgp_node
*rn
;
3885 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3887 struct bgp_clear_node_queue
*cnq
= data
;
3888 struct bgp_node
*rn
= cnq
->rn
;
3889 struct peer
*peer
= wq
->spec
.data
;
3890 struct bgp_path_info
*pi
;
3892 afi_t afi
= bgp_node_table(rn
)->afi
;
3893 safi_t safi
= bgp_node_table(rn
)->safi
;
3898 /* It is possible that we have multiple paths for a prefix from a peer
3899 * if that peer is using AddPath.
3901 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3902 if (pi
->peer
!= peer
)
3905 /* graceful restart STALE flag set. */
3906 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3907 && peer
->nsf
[afi
][safi
]
3908 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3909 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3910 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3912 /* If this is an EVPN route, process for
3914 if (safi
== SAFI_EVPN
)
3915 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3917 /* Handle withdraw for VRF route-leaking and L3VPN */
3918 if (SAFI_UNICAST
== safi
3919 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3920 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3921 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3924 if (SAFI_MPLS_VPN
== safi
&&
3925 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3926 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3929 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3935 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3937 struct bgp_clear_node_queue
*cnq
= data
;
3938 struct bgp_node
*rn
= cnq
->rn
;
3939 struct bgp_table
*table
= bgp_node_table(rn
);
3941 bgp_unlock_node(rn
);
3942 bgp_table_unlock(table
);
3943 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3946 static void bgp_clear_node_complete(struct work_queue
*wq
)
3948 struct peer
*peer
= wq
->spec
.data
;
3950 /* Tickle FSM to start moving again */
3951 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3953 peer_unlock(peer
); /* bgp_clear_route */
3956 static void bgp_clear_node_queue_init(struct peer
*peer
)
3958 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3960 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3961 #undef CLEAR_QUEUE_NAME_LEN
3963 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3964 peer
->clear_node_queue
->spec
.hold
= 10;
3965 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3966 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3967 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3968 peer
->clear_node_queue
->spec
.max_retries
= 0;
3970 /* we only 'lock' this peer reference when the queue is actually active
3972 peer
->clear_node_queue
->spec
.data
= peer
;
3975 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3976 struct bgp_table
*table
)
3978 struct bgp_node
*rn
;
3979 int force
= bm
->process_main_queue
? 0 : 1;
3982 table
= peer
->bgp
->rib
[afi
][safi
];
3984 /* If still no table => afi/safi isn't configured at all or smth. */
3988 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3989 struct bgp_path_info
*pi
, *next
;
3990 struct bgp_adj_in
*ain
;
3991 struct bgp_adj_in
*ain_next
;
3993 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3994 * queued for every clearing peer, regardless of whether it is
3995 * relevant to the peer at hand.
3997 * Overview: There are 3 different indices which need to be
3998 * scrubbed, potentially, when a peer is removed:
4000 * 1 peer's routes visible via the RIB (ie accepted routes)
4001 * 2 peer's routes visible by the (optional) peer's adj-in index
4002 * 3 other routes visible by the peer's adj-out index
4004 * 3 there is no hurry in scrubbing, once the struct peer is
4005 * removed from bgp->peer, we could just GC such deleted peer's
4006 * adj-outs at our leisure.
4008 * 1 and 2 must be 'scrubbed' in some way, at least made
4009 * invisible via RIB index before peer session is allowed to be
4010 * brought back up. So one needs to know when such a 'search' is
4015 * - there'd be a single global queue or a single RIB walker
4016 * - rather than tracking which route_nodes still need to be
4017 * examined on a peer basis, we'd track which peers still
4020 * Given that our per-peer prefix-counts now should be reliable,
4021 * this may actually be achievable. It doesn't seem to be a huge
4022 * problem at this time,
4024 * It is possible that we have multiple paths for a prefix from
4026 * if that peer is using AddPath.
4030 ain_next
= ain
->next
;
4032 if (ain
->peer
== peer
) {
4033 bgp_adj_in_remove(rn
, ain
);
4034 bgp_unlock_node(rn
);
4040 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4042 if (pi
->peer
!= peer
)
4046 bgp_path_info_reap(rn
, pi
);
4048 struct bgp_clear_node_queue
*cnq
;
4050 /* both unlocked in bgp_clear_node_queue_del */
4051 bgp_table_lock(bgp_node_table(rn
));
4054 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4055 sizeof(struct bgp_clear_node_queue
));
4057 work_queue_add(peer
->clear_node_queue
, cnq
);
4065 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4067 struct bgp_node
*rn
;
4068 struct bgp_table
*table
;
4070 if (peer
->clear_node_queue
== NULL
)
4071 bgp_clear_node_queue_init(peer
);
4073 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4074 * Idle until it receives a Clearing_Completed event. This protects
4075 * against peers which flap faster than we can we clear, which could
4078 * a) race with routes from the new session being installed before
4079 * clear_route_node visits the node (to delete the route of that
4081 * b) resource exhaustion, clear_route_node likely leads to an entry
4082 * on the process_main queue. Fast-flapping could cause that queue
4086 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4087 * the unlock will happen upon work-queue completion; other wise, the
4088 * unlock happens at the end of this function.
4090 if (!peer
->clear_node_queue
->thread
)
4093 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4094 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4096 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4097 rn
= bgp_route_next(rn
)) {
4098 table
= bgp_node_get_bgp_table_info(rn
);
4102 bgp_clear_route_table(peer
, afi
, safi
, table
);
4105 /* unlock if no nodes got added to the clear-node-queue. */
4106 if (!peer
->clear_node_queue
->thread
)
4110 void bgp_clear_route_all(struct peer
*peer
)
4115 FOREACH_AFI_SAFI (afi
, safi
)
4116 bgp_clear_route(peer
, afi
, safi
);
4119 rfapiProcessPeerDown(peer
);
4123 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4125 struct bgp_table
*table
;
4126 struct bgp_node
*rn
;
4127 struct bgp_adj_in
*ain
;
4128 struct bgp_adj_in
*ain_next
;
4130 table
= peer
->bgp
->rib
[afi
][safi
];
4132 /* It is possible that we have multiple paths for a prefix from a peer
4133 * if that peer is using AddPath.
4135 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4139 ain_next
= ain
->next
;
4141 if (ain
->peer
== peer
) {
4142 bgp_adj_in_remove(rn
, ain
);
4143 bgp_unlock_node(rn
);
4151 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4153 struct bgp_node
*rn
;
4154 struct bgp_path_info
*pi
;
4155 struct bgp_table
*table
;
4157 if (safi
== SAFI_MPLS_VPN
) {
4158 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4159 rn
= bgp_route_next(rn
)) {
4160 struct bgp_node
*rm
;
4162 /* look for neighbor in tables */
4163 table
= bgp_node_get_bgp_table_info(rn
);
4167 for (rm
= bgp_table_top(table
); rm
;
4168 rm
= bgp_route_next(rm
))
4169 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4171 if (pi
->peer
!= peer
)
4173 if (!CHECK_FLAG(pi
->flags
,
4177 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4182 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4183 rn
= bgp_route_next(rn
))
4184 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4186 if (pi
->peer
!= peer
)
4188 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4190 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4196 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4198 if (peer
->sort
== BGP_PEER_EBGP
4199 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4200 || FILTER_LIST_OUT_NAME(filter
)
4201 || DISTRIBUTE_OUT_NAME(filter
)))
4206 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4208 if (peer
->sort
== BGP_PEER_EBGP
4209 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4210 || FILTER_LIST_IN_NAME(filter
)
4211 || DISTRIBUTE_IN_NAME(filter
)))
4216 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4219 struct bgp_node
*rn
;
4220 struct bgp_path_info
*pi
;
4221 struct bgp_path_info
*next
;
4223 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4224 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4226 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4227 && pi
->type
== ZEBRA_ROUTE_BGP
4228 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4229 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4230 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4232 if (bgp_fibupd_safi(safi
))
4233 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4235 bgp_path_info_reap(rn
, pi
);
4240 /* Delete all kernel routes. */
4241 void bgp_cleanup_routes(struct bgp
*bgp
)
4244 struct bgp_node
*rn
;
4245 struct bgp_table
*table
;
4247 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4248 if (afi
== AFI_L2VPN
)
4250 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4253 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4255 if (afi
!= AFI_L2VPN
) {
4257 safi
= SAFI_MPLS_VPN
;
4258 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4259 rn
= bgp_route_next(rn
)) {
4260 table
= bgp_node_get_bgp_table_info(rn
);
4261 if (table
!= NULL
) {
4262 bgp_cleanup_table(bgp
, table
, safi
);
4263 bgp_table_finish(&table
);
4264 bgp_node_set_bgp_table_info(rn
, NULL
);
4265 bgp_unlock_node(rn
);
4269 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4270 rn
= bgp_route_next(rn
)) {
4271 table
= bgp_node_get_bgp_table_info(rn
);
4272 if (table
!= NULL
) {
4273 bgp_cleanup_table(bgp
, table
, safi
);
4274 bgp_table_finish(&table
);
4275 bgp_node_set_bgp_table_info(rn
, NULL
);
4276 bgp_unlock_node(rn
);
4281 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4282 rn
= bgp_route_next(rn
)) {
4283 table
= bgp_node_get_bgp_table_info(rn
);
4284 if (table
!= NULL
) {
4285 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4286 bgp_table_finish(&table
);
4287 bgp_node_set_bgp_table_info(rn
, NULL
);
4288 bgp_unlock_node(rn
);
4293 void bgp_reset(void)
4296 bgp_zclient_reset();
4297 access_list_reset();
4298 prefix_list_reset();
4301 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4303 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4304 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4305 PEER_CAP_ADDPATH_AF_TX_RCV
));
4308 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4310 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4311 struct bgp_nlri
*packet
)
4320 int addpath_encoded
;
4321 uint32_t addpath_id
;
4324 lim
= pnt
+ packet
->length
;
4326 safi
= packet
->safi
;
4328 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4330 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4331 syntactic validity. If the field is syntactically incorrect,
4332 then the Error Subcode is set to Invalid Network Field. */
4333 for (; pnt
< lim
; pnt
+= psize
) {
4334 /* Clear prefix structure. */
4335 memset(&p
, 0, sizeof(struct prefix
));
4337 if (addpath_encoded
) {
4339 /* When packet overflow occurs return immediately. */
4340 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4343 addpath_id
= ntohl(*((uint32_t *)pnt
));
4344 pnt
+= BGP_ADDPATH_ID_LEN
;
4347 /* Fetch prefix length. */
4348 p
.prefixlen
= *pnt
++;
4349 /* afi/safi validity already verified by caller,
4350 * bgp_update_receive */
4351 p
.family
= afi2family(afi
);
4353 /* Prefix length check. */
4354 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4357 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4358 peer
->host
, p
.prefixlen
, packet
->afi
);
4362 /* Packet size overflow check. */
4363 psize
= PSIZE(p
.prefixlen
);
4365 /* When packet overflow occur return immediately. */
4366 if (pnt
+ psize
> lim
) {
4369 "%s [Error] Update packet error (prefix length %d overflows packet)",
4370 peer
->host
, p
.prefixlen
);
4374 /* Defensive coding, double-check the psize fits in a struct
4376 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4379 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4380 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4384 /* Fetch prefix from NLRI packet. */
4385 memcpy(p
.u
.val
, pnt
, psize
);
4387 /* Check address. */
4388 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4389 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4390 /* From RFC4271 Section 6.3:
4392 * If a prefix in the NLRI field is semantically
4394 * (e.g., an unexpected multicast IP address),
4396 * be logged locally, and the prefix SHOULD be
4401 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4402 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4407 /* Check address. */
4408 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4409 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4414 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4416 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4421 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4426 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4428 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4435 /* Normal process. */
4437 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4438 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4439 NULL
, NULL
, 0, 0, NULL
);
4441 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4442 safi
, ZEBRA_ROUTE_BGP
,
4443 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4446 /* Address family configuration mismatch or maximum-prefix count
4452 /* Packet length consistency check. */
4456 "%s [Error] Update packet error (prefix length mismatch with total length)",
4464 static struct bgp_static
*bgp_static_new(void)
4466 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4469 static void bgp_static_free(struct bgp_static
*bgp_static
)
4471 if (bgp_static
->rmap
.name
)
4472 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4473 route_map_counter_decrement(bgp_static
->rmap
.map
);
4475 if (bgp_static
->eth_s_id
)
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 if (bgp_static
->rmap
.name
)
5037 XFREE(MTYPE_ROUTE_MAP_NAME
,
5038 bgp_static
->rmap
.name
);
5039 route_map_counter_decrement(
5040 bgp_static
->rmap
.map
);
5041 bgp_static
->rmap
.name
=
5042 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5043 bgp_static
->rmap
.map
=
5044 route_map_lookup_by_name(rmap
);
5045 route_map_counter_increment(
5046 bgp_static
->rmap
.map
);
5048 if (bgp_static
->rmap
.name
)
5049 XFREE(MTYPE_ROUTE_MAP_NAME
,
5050 bgp_static
->rmap
.name
);
5051 route_map_counter_decrement(
5052 bgp_static
->rmap
.map
);
5053 bgp_static
->rmap
.name
= NULL
;
5054 bgp_static
->rmap
.map
= NULL
;
5055 bgp_static
->valid
= 0;
5057 bgp_unlock_node(rn
);
5059 /* New configuration. */
5060 bgp_static
= bgp_static_new();
5061 bgp_static
->backdoor
= backdoor
;
5062 bgp_static
->valid
= 0;
5063 bgp_static
->igpmetric
= 0;
5064 bgp_static
->igpnexthop
.s_addr
= 0;
5065 bgp_static
->label_index
= label_index
;
5068 if (bgp_static
->rmap
.name
)
5069 XFREE(MTYPE_ROUTE_MAP_NAME
,
5070 bgp_static
->rmap
.name
);
5071 route_map_counter_decrement(
5072 bgp_static
->rmap
.map
);
5073 bgp_static
->rmap
.name
=
5074 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5075 bgp_static
->rmap
.map
=
5076 route_map_lookup_by_name(rmap
);
5077 route_map_counter_increment(
5078 bgp_static
->rmap
.map
);
5080 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5083 bgp_static
->valid
= 1;
5085 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5087 if (!bgp_static
->backdoor
)
5088 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5094 void bgp_static_add(struct bgp
*bgp
)
5098 struct bgp_node
*rn
;
5099 struct bgp_node
*rm
;
5100 struct bgp_table
*table
;
5101 struct bgp_static
*bgp_static
;
5103 FOREACH_AFI_SAFI (afi
, safi
)
5104 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5105 rn
= bgp_route_next(rn
)) {
5106 if (!bgp_node_has_bgp_path_info_data(rn
))
5109 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5110 || (safi
== SAFI_EVPN
)) {
5111 table
= bgp_node_get_bgp_table_info(rn
);
5113 for (rm
= bgp_table_top(table
); rm
;
5114 rm
= bgp_route_next(rm
)) {
5116 bgp_node_get_bgp_static_info(
5118 bgp_static_update_safi(bgp
, &rm
->p
,
5125 bgp_node_get_bgp_static_info(rn
), afi
,
5131 /* Called from bgp_delete(). Delete all static routes from the BGP
5133 void bgp_static_delete(struct bgp
*bgp
)
5137 struct bgp_node
*rn
;
5138 struct bgp_node
*rm
;
5139 struct bgp_table
*table
;
5140 struct bgp_static
*bgp_static
;
5142 FOREACH_AFI_SAFI (afi
, safi
)
5143 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5144 rn
= bgp_route_next(rn
)) {
5145 if (!bgp_node_has_bgp_path_info_data(rn
))
5148 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5149 || (safi
== SAFI_EVPN
)) {
5150 table
= bgp_node_get_bgp_table_info(rn
);
5152 for (rm
= bgp_table_top(table
); rm
;
5153 rm
= bgp_route_next(rm
)) {
5155 bgp_node_get_bgp_static_info(
5160 bgp_static_withdraw_safi(
5161 bgp
, &rm
->p
, AFI_IP
, safi
,
5162 (struct prefix_rd
*)&rn
->p
);
5163 bgp_static_free(bgp_static
);
5164 bgp_node_set_bgp_static_info(rn
, NULL
);
5165 bgp_unlock_node(rn
);
5168 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5169 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5170 bgp_static_free(bgp_static
);
5171 bgp_node_set_bgp_static_info(rn
, NULL
);
5172 bgp_unlock_node(rn
);
5177 void bgp_static_redo_import_check(struct bgp
*bgp
)
5181 struct bgp_node
*rn
;
5182 struct bgp_node
*rm
;
5183 struct bgp_table
*table
;
5184 struct bgp_static
*bgp_static
;
5186 /* Use this flag to force reprocessing of the route */
5187 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5188 FOREACH_AFI_SAFI (afi
, safi
) {
5189 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5190 rn
= bgp_route_next(rn
)) {
5191 if (!bgp_node_has_bgp_path_info_data(rn
))
5194 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5195 || (safi
== SAFI_EVPN
)) {
5196 table
= bgp_node_get_bgp_table_info(rn
);
5198 for (rm
= bgp_table_top(table
); rm
;
5199 rm
= bgp_route_next(rm
)) {
5201 bgp_node_get_bgp_static_info(
5203 bgp_static_update_safi(bgp
, &rm
->p
,
5208 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5209 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5214 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5217 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5220 struct bgp_table
*table
;
5221 struct bgp_node
*rn
;
5222 struct bgp_path_info
*pi
;
5224 table
= bgp
->rib
[afi
][safi
];
5225 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5226 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5227 if (pi
->peer
== bgp
->peer_self
5228 && ((pi
->type
== ZEBRA_ROUTE_BGP
5229 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5230 || (pi
->type
!= ZEBRA_ROUTE_BGP
5232 == BGP_ROUTE_REDISTRIBUTE
))) {
5233 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5235 bgp_unlink_nexthop(pi
);
5236 bgp_path_info_delete(rn
, pi
);
5237 bgp_process(bgp
, rn
, afi
, safi
);
5244 * Purge all networks and redistributed routes from routing table.
5245 * Invoked upon the instance going down.
5247 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5252 FOREACH_AFI_SAFI (afi
, safi
)
5253 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5258 * Currently this is used to set static routes for VPN and ENCAP.
5259 * I think it can probably be factored with bgp_static_set.
5261 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5262 const char *ip_str
, const char *rd_str
,
5263 const char *label_str
, const char *rmap_str
,
5264 int evpn_type
, const char *esi
, const char *gwip
,
5265 const char *ethtag
, const char *routermac
)
5267 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5270 struct prefix_rd prd
;
5271 struct bgp_node
*prn
;
5272 struct bgp_node
*rn
;
5273 struct bgp_table
*table
;
5274 struct bgp_static
*bgp_static
;
5275 mpls_label_t label
= MPLS_INVALID_LABEL
;
5276 struct prefix gw_ip
;
5278 /* validate ip prefix */
5279 ret
= str2prefix(ip_str
, &p
);
5281 vty_out(vty
, "%% Malformed prefix\n");
5282 return CMD_WARNING_CONFIG_FAILED
;
5285 if ((afi
== AFI_L2VPN
)
5286 && (bgp_build_evpn_prefix(evpn_type
,
5287 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5288 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5289 return CMD_WARNING_CONFIG_FAILED
;
5292 ret
= str2prefix_rd(rd_str
, &prd
);
5294 vty_out(vty
, "%% Malformed rd\n");
5295 return CMD_WARNING_CONFIG_FAILED
;
5299 unsigned long label_val
;
5300 label_val
= strtoul(label_str
, NULL
, 10);
5301 encode_label(label_val
, &label
);
5304 if (safi
== SAFI_EVPN
) {
5305 if (esi
&& str2esi(esi
, NULL
) == 0) {
5306 vty_out(vty
, "%% Malformed ESI\n");
5307 return CMD_WARNING_CONFIG_FAILED
;
5309 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5310 vty_out(vty
, "%% Malformed Router MAC\n");
5311 return CMD_WARNING_CONFIG_FAILED
;
5314 memset(&gw_ip
, 0, sizeof(struct prefix
));
5315 ret
= str2prefix(gwip
, &gw_ip
);
5317 vty_out(vty
, "%% Malformed GatewayIp\n");
5318 return CMD_WARNING_CONFIG_FAILED
;
5320 if ((gw_ip
.family
== AF_INET
5321 && is_evpn_prefix_ipaddr_v6(
5322 (struct prefix_evpn
*)&p
))
5323 || (gw_ip
.family
== AF_INET6
5324 && is_evpn_prefix_ipaddr_v4(
5325 (struct prefix_evpn
*)&p
))) {
5327 "%% GatewayIp family differs with IP prefix\n");
5328 return CMD_WARNING_CONFIG_FAILED
;
5332 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5333 if (!bgp_node_has_bgp_path_info_data(prn
))
5334 bgp_node_set_bgp_table_info(prn
,
5335 bgp_table_init(bgp
, afi
, safi
));
5336 table
= bgp_node_get_bgp_table_info(prn
);
5338 rn
= bgp_node_get(table
, &p
);
5340 if (bgp_node_has_bgp_path_info_data(rn
)) {
5341 vty_out(vty
, "%% Same network configuration exists\n");
5342 bgp_unlock_node(rn
);
5344 /* New configuration. */
5345 bgp_static
= bgp_static_new();
5346 bgp_static
->backdoor
= 0;
5347 bgp_static
->valid
= 0;
5348 bgp_static
->igpmetric
= 0;
5349 bgp_static
->igpnexthop
.s_addr
= 0;
5350 bgp_static
->label
= label
;
5351 bgp_static
->prd
= prd
;
5354 if (bgp_static
->rmap
.name
)
5355 XFREE(MTYPE_ROUTE_MAP_NAME
,
5356 bgp_static
->rmap
.name
);
5357 route_map_counter_decrement(bgp_static
->rmap
.map
);
5358 bgp_static
->rmap
.name
=
5359 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5360 bgp_static
->rmap
.map
=
5361 route_map_lookup_by_name(rmap_str
);
5362 route_map_counter_increment(bgp_static
->rmap
.map
);
5365 if (safi
== SAFI_EVPN
) {
5367 bgp_static
->eth_s_id
=
5369 sizeof(struct eth_segment_id
));
5370 str2esi(esi
, bgp_static
->eth_s_id
);
5373 bgp_static
->router_mac
=
5374 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5375 (void)prefix_str2mac(routermac
,
5376 bgp_static
->router_mac
);
5379 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5381 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5383 bgp_static
->valid
= 1;
5384 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5390 /* Configure static BGP network. */
5391 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5392 const char *ip_str
, const char *rd_str
,
5393 const char *label_str
, int evpn_type
, const char *esi
,
5394 const char *gwip
, const char *ethtag
)
5396 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5399 struct prefix_rd prd
;
5400 struct bgp_node
*prn
;
5401 struct bgp_node
*rn
;
5402 struct bgp_table
*table
;
5403 struct bgp_static
*bgp_static
;
5404 mpls_label_t label
= MPLS_INVALID_LABEL
;
5406 /* Convert IP prefix string to struct prefix. */
5407 ret
= str2prefix(ip_str
, &p
);
5409 vty_out(vty
, "%% Malformed prefix\n");
5410 return CMD_WARNING_CONFIG_FAILED
;
5413 if ((afi
== AFI_L2VPN
)
5414 && (bgp_build_evpn_prefix(evpn_type
,
5415 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5416 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5417 return CMD_WARNING_CONFIG_FAILED
;
5419 ret
= str2prefix_rd(rd_str
, &prd
);
5421 vty_out(vty
, "%% Malformed rd\n");
5422 return CMD_WARNING_CONFIG_FAILED
;
5426 unsigned long label_val
;
5427 label_val
= strtoul(label_str
, NULL
, 10);
5428 encode_label(label_val
, &label
);
5431 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5432 if (!bgp_node_has_bgp_path_info_data(prn
))
5433 bgp_node_set_bgp_table_info(prn
,
5434 bgp_table_init(bgp
, afi
, safi
));
5436 bgp_unlock_node(prn
);
5437 table
= bgp_node_get_bgp_table_info(prn
);
5439 rn
= bgp_node_lookup(table
, &p
);
5442 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5444 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5445 bgp_static_free(bgp_static
);
5446 bgp_node_set_bgp_static_info(rn
, NULL
);
5447 bgp_unlock_node(rn
);
5448 bgp_unlock_node(rn
);
5450 vty_out(vty
, "%% Can't find the route\n");
5455 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5456 const char *rmap_name
)
5458 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5459 struct bgp_rmap
*rmap
;
5461 rmap
= &bgp
->table_map
[afi
][safi
];
5464 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5465 route_map_counter_decrement(rmap
->map
);
5466 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5467 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5468 route_map_counter_increment(rmap
->map
);
5471 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5472 route_map_counter_decrement(rmap
->map
);
5477 if (bgp_fibupd_safi(safi
))
5478 bgp_zebra_announce_table(bgp
, afi
, safi
);
5483 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5484 const char *rmap_name
)
5486 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5487 struct bgp_rmap
*rmap
;
5489 rmap
= &bgp
->table_map
[afi
][safi
];
5491 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5492 route_map_counter_decrement(rmap
->map
);
5496 if (bgp_fibupd_safi(safi
))
5497 bgp_zebra_announce_table(bgp
, afi
, safi
);
5502 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5505 if (bgp
->table_map
[afi
][safi
].name
) {
5506 vty_out(vty
, " table-map %s\n",
5507 bgp
->table_map
[afi
][safi
].name
);
5511 DEFUN (bgp_table_map
,
5514 "BGP table to RIB route download filter\n"
5515 "Name of the route map\n")
5518 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5519 argv
[idx_word
]->arg
);
5521 DEFUN (no_bgp_table_map
,
5522 no_bgp_table_map_cmd
,
5523 "no table-map WORD",
5525 "BGP table to RIB route download filter\n"
5526 "Name of the route map\n")
5529 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5530 argv
[idx_word
]->arg
);
5536 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5537 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5538 backdoor$backdoor}]",
5540 "Specify a network to announce via BGP\n"
5545 "Route-map to modify the attributes\n"
5546 "Name of the route map\n"
5547 "Label index to associate with the prefix\n"
5548 "Label index value\n"
5549 "Specify a BGP backdoor route\n")
5551 char addr_prefix_str
[BUFSIZ
];
5556 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5559 vty_out(vty
, "%% Inconsistent address and mask\n");
5560 return CMD_WARNING_CONFIG_FAILED
;
5564 return bgp_static_set(
5565 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5566 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5567 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5570 DEFPY(ipv6_bgp_network
,
5571 ipv6_bgp_network_cmd
,
5572 "[no] network X:X::X:X/M$prefix \
5573 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5575 "Specify a network to announce via BGP\n"
5577 "Route-map to modify the attributes\n"
5578 "Name of the route map\n"
5579 "Label index to associate with the prefix\n"
5580 "Label index value\n")
5582 return bgp_static_set(
5583 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5584 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5587 static struct bgp_aggregate
*bgp_aggregate_new(void)
5589 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5592 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5594 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5597 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5598 struct aspath
*aspath
,
5599 struct community
*comm
,
5600 struct ecommunity
*ecomm
,
5601 struct lcommunity
*lcomm
)
5603 static struct aspath
*ae
= NULL
;
5606 ae
= aspath_empty();
5611 if (origin
!= pi
->attr
->origin
)
5614 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5617 if (!community_cmp(pi
->attr
->community
, comm
))
5620 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5623 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5626 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5632 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5633 struct prefix
*p
, uint8_t origin
,
5634 struct aspath
*aspath
,
5635 struct community
*community
,
5636 struct ecommunity
*ecommunity
,
5637 struct lcommunity
*lcommunity
,
5638 uint8_t atomic_aggregate
,
5639 struct bgp_aggregate
*aggregate
)
5641 struct bgp_node
*rn
;
5642 struct bgp_table
*table
;
5643 struct bgp_path_info
*pi
, *orig
, *new;
5645 table
= bgp
->rib
[afi
][safi
];
5647 rn
= bgp_node_get(table
, p
);
5649 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5650 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5651 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5654 if (aggregate
->count
> 0) {
5656 * If the aggregate information has not changed
5657 * no need to re-install it again.
5659 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5660 ecommunity
, lcommunity
)) {
5661 bgp_unlock_node(rn
);
5664 aspath_free(aspath
);
5666 community_free(&community
);
5668 ecommunity_free(&ecommunity
);
5670 lcommunity_free(&lcommunity
);
5676 * Mark the old as unusable
5679 bgp_path_info_delete(rn
, pi
);
5681 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5683 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5684 community
, ecommunity
,
5689 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5691 bgp_path_info_add(rn
, new);
5692 bgp_process(bgp
, rn
, afi
, safi
);
5694 for (pi
= orig
; pi
; pi
= pi
->next
)
5695 if (pi
->peer
== bgp
->peer_self
5696 && pi
->type
== ZEBRA_ROUTE_BGP
5697 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5700 /* Withdraw static BGP route from routing table. */
5702 bgp_path_info_delete(rn
, pi
);
5703 bgp_process(bgp
, rn
, afi
, safi
);
5707 bgp_unlock_node(rn
);
5710 /* Update an aggregate as routes are added/removed from the BGP table */
5711 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5712 afi_t afi
, safi_t safi
,
5713 struct bgp_aggregate
*aggregate
)
5715 struct bgp_table
*table
;
5716 struct bgp_node
*top
;
5717 struct bgp_node
*rn
;
5719 struct aspath
*aspath
= NULL
;
5720 struct community
*community
= NULL
;
5721 struct ecommunity
*ecommunity
= NULL
;
5722 struct lcommunity
*lcommunity
= NULL
;
5723 struct bgp_path_info
*pi
;
5724 unsigned long match
= 0;
5725 uint8_t atomic_aggregate
= 0;
5727 /* ORIGIN attribute: If at least one route among routes that are
5728 aggregated has ORIGIN with the value INCOMPLETE, then the
5729 aggregated route must have the ORIGIN attribute with the value
5730 INCOMPLETE. Otherwise, if at least one route among routes that
5731 are aggregated has ORIGIN with the value EGP, then the aggregated
5732 route must have the origin attribute with the value EGP. In all
5733 other case the value of the ORIGIN attribute of the aggregated
5734 route is INTERNAL. */
5735 origin
= BGP_ORIGIN_IGP
;
5737 table
= bgp
->rib
[afi
][safi
];
5739 top
= bgp_node_get(table
, p
);
5740 for (rn
= bgp_node_get(table
, p
); rn
;
5741 rn
= bgp_route_next_until(rn
, top
)) {
5742 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5747 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5748 if (BGP_PATH_HOLDDOWN(pi
))
5752 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5753 atomic_aggregate
= 1;
5755 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5759 * summary-only aggregate route suppress
5760 * aggregated route announcements.
5762 if (aggregate
->summary_only
) {
5763 (bgp_path_info_extra_get(pi
))->suppress
++;
5764 bgp_path_info_set_flag(rn
, pi
,
5765 BGP_PATH_ATTR_CHANGED
);
5772 * If at least one route among routes that are
5773 * aggregated has ORIGIN with the value INCOMPLETE,
5774 * then the aggregated route MUST have the ORIGIN
5775 * attribute with the value INCOMPLETE. Otherwise, if
5776 * at least one route among routes that are aggregated
5777 * has ORIGIN with the value EGP, then the aggregated
5778 * route MUST have the ORIGIN attribute with the value
5781 switch (pi
->attr
->origin
) {
5782 case BGP_ORIGIN_INCOMPLETE
:
5783 aggregate
->incomplete_origin_count
++;
5785 case BGP_ORIGIN_EGP
:
5786 aggregate
->egp_origin_count
++;
5794 if (!aggregate
->as_set
)
5798 * as-set aggregate route generate origin, as path,
5799 * and community aggregation.
5801 /* Compute aggregate route's as-path.
5803 bgp_compute_aggregate_aspath(aggregate
,
5806 /* Compute aggregate route's community.
5808 if (pi
->attr
->community
)
5809 bgp_compute_aggregate_community(
5811 pi
->attr
->community
);
5813 /* Compute aggregate route's extended community.
5815 if (pi
->attr
->ecommunity
)
5816 bgp_compute_aggregate_ecommunity(
5818 pi
->attr
->ecommunity
);
5820 /* Compute aggregate route's large community.
5822 if (pi
->attr
->lcommunity
)
5823 bgp_compute_aggregate_lcommunity(
5825 pi
->attr
->lcommunity
);
5828 bgp_process(bgp
, rn
, afi
, safi
);
5830 bgp_unlock_node(top
);
5833 if (aggregate
->incomplete_origin_count
> 0)
5834 origin
= BGP_ORIGIN_INCOMPLETE
;
5835 else if (aggregate
->egp_origin_count
> 0)
5836 origin
= BGP_ORIGIN_EGP
;
5838 if (aggregate
->as_set
) {
5839 if (aggregate
->aspath
)
5840 /* Retrieve aggregate route's as-path.
5842 aspath
= aspath_dup(aggregate
->aspath
);
5844 if (aggregate
->community
)
5845 /* Retrieve aggregate route's community.
5847 community
= community_dup(aggregate
->community
);
5849 if (aggregate
->ecommunity
)
5850 /* Retrieve aggregate route's ecommunity.
5852 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
5854 if (aggregate
->lcommunity
)
5855 /* Retrieve aggregate route's lcommunity.
5857 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
5860 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5861 ecommunity
, lcommunity
, atomic_aggregate
,
5865 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5866 safi_t safi
, struct bgp_aggregate
*aggregate
)
5868 struct bgp_table
*table
;
5869 struct bgp_node
*top
;
5870 struct bgp_node
*rn
;
5871 struct bgp_path_info
*pi
;
5872 unsigned long match
;
5874 table
= bgp
->rib
[afi
][safi
];
5876 /* If routes exists below this node, generate aggregate routes. */
5877 top
= bgp_node_get(table
, p
);
5878 for (rn
= bgp_node_get(table
, p
); rn
;
5879 rn
= bgp_route_next_until(rn
, top
)) {
5880 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5884 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5885 if (BGP_PATH_HOLDDOWN(pi
))
5888 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5891 if (aggregate
->summary_only
&& pi
->extra
) {
5892 pi
->extra
->suppress
--;
5894 if (pi
->extra
->suppress
== 0) {
5895 bgp_path_info_set_flag(
5896 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5902 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
5903 aggregate
->incomplete_origin_count
--;
5904 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
5905 aggregate
->egp_origin_count
--;
5907 if (aggregate
->as_set
) {
5908 /* Remove as-path from aggregate.
5910 bgp_remove_aspath_from_aggregate(
5914 if (pi
->attr
->community
)
5915 /* Remove community from aggregate.
5917 bgp_remove_community_from_aggregate(
5919 pi
->attr
->community
);
5921 if (pi
->attr
->ecommunity
)
5922 /* Remove ecommunity from aggregate.
5924 bgp_remove_ecommunity_from_aggregate(
5926 pi
->attr
->ecommunity
);
5928 if (pi
->attr
->lcommunity
)
5929 /* Remove lcommunity from aggregate.
5931 bgp_remove_lcommunity_from_aggregate(
5933 pi
->attr
->lcommunity
);
5938 /* If this node was suppressed, process the change. */
5940 bgp_process(bgp
, rn
, afi
, safi
);
5942 bgp_unlock_node(top
);
5945 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
5946 struct bgp_path_info
*pinew
, afi_t afi
,
5948 struct bgp_aggregate
*aggregate
)
5951 struct aspath
*aspath
= NULL
;
5952 uint8_t atomic_aggregate
= 0;
5953 struct community
*community
= NULL
;
5954 struct ecommunity
*ecommunity
= NULL
;
5955 struct lcommunity
*lcommunity
= NULL
;
5957 /* ORIGIN attribute: If at least one route among routes that are
5958 * aggregated has ORIGIN with the value INCOMPLETE, then the
5959 * aggregated route must have the ORIGIN attribute with the value
5960 * INCOMPLETE. Otherwise, if at least one route among routes that
5961 * are aggregated has ORIGIN with the value EGP, then the aggregated
5962 * route must have the origin attribute with the value EGP. In all
5963 * other case the value of the ORIGIN attribute of the aggregated
5964 * route is INTERNAL.
5966 origin
= BGP_ORIGIN_IGP
;
5970 if (aggregate
->summary_only
)
5971 (bgp_path_info_extra_get(pinew
))->suppress
++;
5973 switch (pinew
->attr
->origin
) {
5974 case BGP_ORIGIN_INCOMPLETE
:
5975 aggregate
->incomplete_origin_count
++;
5977 case BGP_ORIGIN_EGP
:
5978 aggregate
->egp_origin_count
++;
5986 if (aggregate
->incomplete_origin_count
> 0)
5987 origin
= BGP_ORIGIN_INCOMPLETE
;
5988 else if (aggregate
->egp_origin_count
> 0)
5989 origin
= BGP_ORIGIN_EGP
;
5991 if (aggregate
->as_set
) {
5992 /* Compute aggregate route's as-path.
5994 bgp_compute_aggregate_aspath(aggregate
,
5995 pinew
->attr
->aspath
);
5997 /* Compute aggregate route's community.
5999 if (pinew
->attr
->community
)
6000 bgp_compute_aggregate_community(
6002 pinew
->attr
->community
);
6004 /* Compute aggregate route's extended community.
6006 if (pinew
->attr
->ecommunity
)
6007 bgp_compute_aggregate_ecommunity(
6009 pinew
->attr
->ecommunity
);
6011 /* Compute aggregate route's large community.
6013 if (pinew
->attr
->lcommunity
)
6014 bgp_compute_aggregate_lcommunity(
6016 pinew
->attr
->lcommunity
);
6018 /* Retrieve aggregate route's as-path.
6020 if (aggregate
->aspath
)
6021 aspath
= aspath_dup(aggregate
->aspath
);
6023 /* Retrieve aggregate route's community.
6025 if (aggregate
->community
)
6026 community
= community_dup(aggregate
->community
);
6028 /* Retrieve aggregate route's ecommunity.
6030 if (aggregate
->ecommunity
)
6031 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6033 /* Retrieve aggregate route's lcommunity.
6035 if (aggregate
->lcommunity
)
6036 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6039 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6040 aspath
, community
, ecommunity
,
6041 lcommunity
, atomic_aggregate
, aggregate
);
6044 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6046 struct bgp_path_info
*pi
,
6047 struct bgp_aggregate
*aggregate
,
6048 struct prefix
*aggr_p
)
6051 struct aspath
*aspath
= NULL
;
6052 uint8_t atomic_aggregate
= 0;
6053 struct community
*community
= NULL
;
6054 struct ecommunity
*ecommunity
= NULL
;
6055 struct lcommunity
*lcommunity
= NULL
;
6056 unsigned long match
= 0;
6058 if (BGP_PATH_HOLDDOWN(pi
))
6061 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6064 if (aggregate
->summary_only
6066 && pi
->extra
->suppress
> 0) {
6067 pi
->extra
->suppress
--;
6069 if (pi
->extra
->suppress
== 0) {
6070 bgp_path_info_set_flag(pi
->net
, pi
,
6071 BGP_PATH_ATTR_CHANGED
);
6076 if (aggregate
->count
> 0)
6079 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6080 aggregate
->incomplete_origin_count
--;
6081 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6082 aggregate
->egp_origin_count
--;
6084 if (aggregate
->as_set
) {
6085 /* Remove as-path from aggregate.
6087 bgp_remove_aspath_from_aggregate(aggregate
,
6090 if (pi
->attr
->community
)
6091 /* Remove community from aggregate.
6093 bgp_remove_community_from_aggregate(
6095 pi
->attr
->community
);
6097 if (pi
->attr
->ecommunity
)
6098 /* Remove ecommunity from aggregate.
6100 bgp_remove_ecommunity_from_aggregate(
6102 pi
->attr
->ecommunity
);
6104 if (pi
->attr
->lcommunity
)
6105 /* Remove lcommunity from aggregate.
6107 bgp_remove_lcommunity_from_aggregate(
6109 pi
->attr
->lcommunity
);
6112 /* If this node was suppressed, process the change. */
6114 bgp_process(bgp
, pi
->net
, afi
, safi
);
6116 origin
= BGP_ORIGIN_IGP
;
6117 if (aggregate
->incomplete_origin_count
> 0)
6118 origin
= BGP_ORIGIN_INCOMPLETE
;
6119 else if (aggregate
->egp_origin_count
> 0)
6120 origin
= BGP_ORIGIN_EGP
;
6122 if (aggregate
->as_set
) {
6123 /* Retrieve aggregate route's as-path.
6125 if (aggregate
->aspath
)
6126 aspath
= aspath_dup(aggregate
->aspath
);
6128 /* Retrieve aggregate route's community.
6130 if (aggregate
->community
)
6131 community
= community_dup(aggregate
->community
);
6133 /* Retrieve aggregate route's ecommunity.
6135 if (aggregate
->ecommunity
)
6136 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6138 /* Retrieve aggregate route's lcommunity.
6140 if (aggregate
->lcommunity
)
6141 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6144 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6145 aspath
, community
, ecommunity
,
6146 lcommunity
, atomic_aggregate
, aggregate
);
6149 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6150 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6152 struct bgp_node
*child
;
6153 struct bgp_node
*rn
;
6154 struct bgp_aggregate
*aggregate
;
6155 struct bgp_table
*table
;
6157 table
= bgp
->aggregate
[afi
][safi
];
6159 /* No aggregates configured. */
6160 if (bgp_table_top_nolock(table
) == NULL
)
6163 if (p
->prefixlen
== 0)
6166 if (BGP_PATH_HOLDDOWN(pi
))
6169 child
= bgp_node_get(table
, p
);
6171 /* Aggregate address configuration check. */
6172 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6173 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6174 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6175 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6179 bgp_unlock_node(child
);
6182 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6183 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6185 struct bgp_node
*child
;
6186 struct bgp_node
*rn
;
6187 struct bgp_aggregate
*aggregate
;
6188 struct bgp_table
*table
;
6190 table
= bgp
->aggregate
[afi
][safi
];
6192 /* No aggregates configured. */
6193 if (bgp_table_top_nolock(table
) == NULL
)
6196 if (p
->prefixlen
== 0)
6199 child
= bgp_node_get(table
, p
);
6201 /* Aggregate address configuration check. */
6202 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6203 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6204 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6205 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6206 del
, aggregate
, &rn
->p
);
6209 bgp_unlock_node(child
);
6212 /* Aggregate route attribute. */
6213 #define AGGREGATE_SUMMARY_ONLY 1
6214 #define AGGREGATE_AS_SET 1
6216 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6217 afi_t afi
, safi_t safi
)
6219 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6222 struct bgp_node
*rn
;
6223 struct bgp_aggregate
*aggregate
;
6225 /* Convert string to prefix structure. */
6226 ret
= str2prefix(prefix_str
, &p
);
6228 vty_out(vty
, "Malformed prefix\n");
6229 return CMD_WARNING_CONFIG_FAILED
;
6233 /* Old configuration check. */
6234 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6237 "%% There is no aggregate-address configuration.\n");
6238 return CMD_WARNING_CONFIG_FAILED
;
6241 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6242 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6243 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6244 NULL
, NULL
, 0, aggregate
);
6246 /* Unlock aggregate address configuration. */
6247 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6249 if (aggregate
->community
)
6250 community_free(&aggregate
->community
);
6252 if (aggregate
->community_hash
) {
6253 /* Delete all communities in the hash.
6255 hash_clean(aggregate
->community_hash
,
6256 bgp_aggr_community_remove
);
6257 /* Free up the community_hash.
6259 hash_free(aggregate
->community_hash
);
6262 if (aggregate
->ecommunity
)
6263 ecommunity_free(&aggregate
->ecommunity
);
6265 if (aggregate
->ecommunity_hash
) {
6266 /* Delete all ecommunities in the hash.
6268 hash_clean(aggregate
->ecommunity_hash
,
6269 bgp_aggr_ecommunity_remove
);
6270 /* Free up the ecommunity_hash.
6272 hash_free(aggregate
->ecommunity_hash
);
6275 if (aggregate
->lcommunity
)
6276 lcommunity_free(&aggregate
->lcommunity
);
6278 if (aggregate
->lcommunity_hash
) {
6279 /* Delete all lcommunities in the hash.
6281 hash_clean(aggregate
->lcommunity_hash
,
6282 bgp_aggr_lcommunity_remove
);
6283 /* Free up the lcommunity_hash.
6285 hash_free(aggregate
->lcommunity_hash
);
6288 if (aggregate
->aspath
)
6289 aspath_free(aggregate
->aspath
);
6291 if (aggregate
->aspath_hash
) {
6292 /* Delete all as-paths in the hash.
6294 hash_clean(aggregate
->aspath_hash
,
6295 bgp_aggr_aspath_remove
);
6296 /* Free up the aspath_hash.
6298 hash_free(aggregate
->aspath_hash
);
6301 bgp_aggregate_free(aggregate
);
6302 bgp_unlock_node(rn
);
6303 bgp_unlock_node(rn
);
6308 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6309 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6311 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6314 struct bgp_node
*rn
;
6315 struct bgp_aggregate
*aggregate
;
6317 /* Convert string to prefix structure. */
6318 ret
= str2prefix(prefix_str
, &p
);
6320 vty_out(vty
, "Malformed prefix\n");
6321 return CMD_WARNING_CONFIG_FAILED
;
6325 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6326 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6327 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6329 return CMD_WARNING_CONFIG_FAILED
;
6332 /* Old configuration check. */
6333 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6335 if (bgp_node_has_bgp_path_info_data(rn
)) {
6336 vty_out(vty
, "There is already same aggregate network.\n");
6337 /* try to remove the old entry */
6338 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6340 vty_out(vty
, "Error deleting aggregate.\n");
6341 bgp_unlock_node(rn
);
6342 return CMD_WARNING_CONFIG_FAILED
;
6346 /* Make aggregate address structure. */
6347 aggregate
= bgp_aggregate_new();
6348 aggregate
->summary_only
= summary_only
;
6349 aggregate
->as_set
= as_set
;
6350 aggregate
->safi
= safi
;
6351 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6353 /* Aggregate address insert into BGP routing table. */
6354 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6359 DEFUN (aggregate_address
,
6360 aggregate_address_cmd
,
6361 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6362 "Configure BGP aggregate entries\n"
6363 "Aggregate prefix\n"
6364 "Generate AS set path information\n"
6365 "Filter more specific routes from updates\n"
6366 "Filter more specific routes from updates\n"
6367 "Generate AS set path information\n")
6370 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6371 char *prefix
= argv
[idx
]->arg
;
6373 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6375 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6376 ? AGGREGATE_SUMMARY_ONLY
6379 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6380 summary_only
, as_set
);
6383 DEFUN (aggregate_address_mask
,
6384 aggregate_address_mask_cmd
,
6385 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6386 "Configure BGP aggregate entries\n"
6387 "Aggregate address\n"
6389 "Generate AS set path information\n"
6390 "Filter more specific routes from updates\n"
6391 "Filter more specific routes from updates\n"
6392 "Generate AS set path information\n")
6395 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6396 char *prefix
= argv
[idx
]->arg
;
6397 char *mask
= argv
[idx
+ 1]->arg
;
6399 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6401 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6402 ? AGGREGATE_SUMMARY_ONLY
6405 char prefix_str
[BUFSIZ
];
6406 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6409 vty_out(vty
, "%% Inconsistent address and mask\n");
6410 return CMD_WARNING_CONFIG_FAILED
;
6413 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6414 summary_only
, as_set
);
6417 DEFUN (no_aggregate_address
,
6418 no_aggregate_address_cmd
,
6419 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6421 "Configure BGP aggregate entries\n"
6422 "Aggregate prefix\n"
6423 "Generate AS set path information\n"
6424 "Filter more specific routes from updates\n"
6425 "Filter more specific routes from updates\n"
6426 "Generate AS set path information\n")
6429 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6430 char *prefix
= argv
[idx
]->arg
;
6431 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6434 DEFUN (no_aggregate_address_mask
,
6435 no_aggregate_address_mask_cmd
,
6436 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6438 "Configure BGP aggregate entries\n"
6439 "Aggregate address\n"
6441 "Generate AS set path information\n"
6442 "Filter more specific routes from updates\n"
6443 "Filter more specific routes from updates\n"
6444 "Generate AS set path information\n")
6447 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6448 char *prefix
= argv
[idx
]->arg
;
6449 char *mask
= argv
[idx
+ 1]->arg
;
6451 char prefix_str
[BUFSIZ
];
6452 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6455 vty_out(vty
, "%% Inconsistent address and mask\n");
6456 return CMD_WARNING_CONFIG_FAILED
;
6459 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6462 DEFUN (ipv6_aggregate_address
,
6463 ipv6_aggregate_address_cmd
,
6464 "aggregate-address X:X::X:X/M [summary-only]",
6465 "Configure BGP aggregate entries\n"
6466 "Aggregate prefix\n"
6467 "Filter more specific routes from updates\n")
6470 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6471 char *prefix
= argv
[idx
]->arg
;
6472 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6473 ? AGGREGATE_SUMMARY_ONLY
6475 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6479 DEFUN (no_ipv6_aggregate_address
,
6480 no_ipv6_aggregate_address_cmd
,
6481 "no aggregate-address X:X::X:X/M [summary-only]",
6483 "Configure BGP aggregate entries\n"
6484 "Aggregate prefix\n"
6485 "Filter more specific routes from updates\n")
6488 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6489 char *prefix
= argv
[idx
]->arg
;
6490 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6493 /* Redistribute route treatment. */
6494 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6495 const union g_addr
*nexthop
, ifindex_t ifindex
,
6496 enum nexthop_types_t nhtype
, uint32_t metric
,
6497 uint8_t type
, unsigned short instance
,
6500 struct bgp_path_info
*new;
6501 struct bgp_path_info
*bpi
;
6502 struct bgp_path_info rmap_path
;
6503 struct bgp_node
*bn
;
6505 struct attr
*new_attr
;
6508 struct bgp_redist
*red
;
6510 /* Make default attribute. */
6511 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6514 case NEXTHOP_TYPE_IFINDEX
:
6516 case NEXTHOP_TYPE_IPV4
:
6517 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6518 attr
.nexthop
= nexthop
->ipv4
;
6520 case NEXTHOP_TYPE_IPV6
:
6521 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6522 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6523 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6525 case NEXTHOP_TYPE_BLACKHOLE
:
6526 switch (p
->family
) {
6528 attr
.nexthop
.s_addr
= INADDR_ANY
;
6531 memset(&attr
.mp_nexthop_global
, 0,
6532 sizeof(attr
.mp_nexthop_global
));
6533 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6538 attr
.nh_ifindex
= ifindex
;
6541 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6544 afi
= family2afi(p
->family
);
6546 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6548 struct attr attr_new
;
6550 /* Copy attribute for modification. */
6551 bgp_attr_dup(&attr_new
, &attr
);
6553 if (red
->redist_metric_flag
)
6554 attr_new
.med
= red
->redist_metric
;
6556 /* Apply route-map. */
6557 if (red
->rmap
.name
) {
6558 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6559 rmap_path
.peer
= bgp
->peer_self
;
6560 rmap_path
.attr
= &attr_new
;
6562 SET_FLAG(bgp
->peer_self
->rmap_type
,
6563 PEER_RMAP_TYPE_REDISTRIBUTE
);
6565 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6568 bgp
->peer_self
->rmap_type
= 0;
6570 if (ret
== RMAP_DENYMATCH
) {
6571 /* Free uninterned attribute. */
6572 bgp_attr_flush(&attr_new
);
6574 /* Unintern original. */
6575 aspath_unintern(&attr
.aspath
);
6576 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6581 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6582 bgp_attr_add_gshut_community(&attr_new
);
6584 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6585 SAFI_UNICAST
, p
, NULL
);
6587 new_attr
= bgp_attr_intern(&attr_new
);
6589 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6591 if (bpi
->peer
== bgp
->peer_self
6592 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6596 /* Ensure the (source route) type is updated. */
6598 if (attrhash_cmp(bpi
->attr
, new_attr
)
6599 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6600 bgp_attr_unintern(&new_attr
);
6601 aspath_unintern(&attr
.aspath
);
6602 bgp_unlock_node(bn
);
6605 /* The attribute is changed. */
6606 bgp_path_info_set_flag(bn
, bpi
,
6607 BGP_PATH_ATTR_CHANGED
);
6609 /* Rewrite BGP route information. */
6610 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6611 bgp_path_info_restore(bn
, bpi
);
6613 bgp_aggregate_decrement(
6614 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6615 bgp_attr_unintern(&bpi
->attr
);
6616 bpi
->attr
= new_attr
;
6617 bpi
->uptime
= bgp_clock();
6619 /* Process change. */
6620 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6622 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6623 bgp_unlock_node(bn
);
6624 aspath_unintern(&attr
.aspath
);
6626 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6628 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6630 vpn_leak_from_vrf_update(
6631 bgp_get_default(), bgp
, bpi
);
6637 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6638 bgp
->peer_self
, new_attr
, bn
);
6639 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6641 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6642 bgp_path_info_add(bn
, new);
6643 bgp_unlock_node(bn
);
6644 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6646 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6647 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6649 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6653 /* Unintern original. */
6654 aspath_unintern(&attr
.aspath
);
6657 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6658 unsigned short instance
)
6661 struct bgp_node
*rn
;
6662 struct bgp_path_info
*pi
;
6663 struct bgp_redist
*red
;
6665 afi
= family2afi(p
->family
);
6667 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6669 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6670 SAFI_UNICAST
, p
, NULL
);
6672 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6673 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6677 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6678 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6680 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6683 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6684 bgp_path_info_delete(rn
, pi
);
6685 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6687 bgp_unlock_node(rn
);
6691 /* Withdraw specified route type's route. */
6692 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6693 unsigned short instance
)
6695 struct bgp_node
*rn
;
6696 struct bgp_path_info
*pi
;
6697 struct bgp_table
*table
;
6699 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6701 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6702 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6703 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6704 && pi
->instance
== instance
)
6708 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6709 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6711 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6714 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6716 bgp_path_info_delete(rn
, pi
);
6717 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6722 /* Static function to display route. */
6723 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6730 if (p
->family
== AF_INET
) {
6734 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6737 json_object_string_add(json
, "prefix",
6738 inet_ntop(p
->family
,
6741 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6742 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6743 json_object_string_add(json
, "network", buf2
);
6745 } else if (p
->family
== AF_ETHERNET
) {
6746 prefix2str(p
, buf
, PREFIX_STRLEN
);
6747 len
= vty_out(vty
, "%s", buf
);
6748 } else if (p
->family
== AF_EVPN
) {
6752 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6755 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6756 } else if (p
->family
== AF_FLOWSPEC
) {
6757 route_vty_out_flowspec(vty
, p
, NULL
,
6759 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6760 NLRI_STRING_FORMAT_MIN
, json
);
6765 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6768 json_object_string_add(json
, "prefix",
6769 inet_ntop(p
->family
,
6772 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6773 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6774 json_object_string_add(json
, "network", buf2
);
6781 vty_out(vty
, "\n%*s", 20, " ");
6783 vty_out(vty
, "%*s", len
, " ");
6787 enum bgp_display_type
{
6791 /* Print the short form route status for a bgp_path_info */
6792 static void route_vty_short_status_out(struct vty
*vty
,
6793 struct bgp_path_info
*path
,
6794 json_object
*json_path
)
6798 /* Route status display. */
6799 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6800 json_object_boolean_true_add(json_path
, "removed");
6802 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6803 json_object_boolean_true_add(json_path
, "stale");
6805 if (path
->extra
&& path
->extra
->suppress
)
6806 json_object_boolean_true_add(json_path
, "suppressed");
6808 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6809 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6810 json_object_boolean_true_add(json_path
, "valid");
6813 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6814 json_object_boolean_true_add(json_path
, "history");
6816 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6817 json_object_boolean_true_add(json_path
, "damped");
6819 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6820 json_object_boolean_true_add(json_path
, "bestpath");
6822 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6823 json_object_boolean_true_add(json_path
, "multipath");
6825 /* Internal route. */
6826 if ((path
->peer
->as
)
6827 && (path
->peer
->as
== path
->peer
->local_as
))
6828 json_object_string_add(json_path
, "pathFrom",
6831 json_object_string_add(json_path
, "pathFrom",
6837 /* Route status display. */
6838 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6840 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6842 else if (path
->extra
&& path
->extra
->suppress
)
6844 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6845 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6851 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6853 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6855 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6857 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6862 /* Internal route. */
6863 if (path
->peer
&& (path
->peer
->as
)
6864 && (path
->peer
->as
== path
->peer
->local_as
))
6870 /* called from terminal list command */
6871 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6872 struct bgp_path_info
*path
, int display
, safi_t safi
,
6873 json_object
*json_paths
)
6876 json_object
*json_path
= NULL
;
6877 json_object
*json_nexthops
= NULL
;
6878 json_object
*json_nexthop_global
= NULL
;
6879 json_object
*json_nexthop_ll
= NULL
;
6880 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6882 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6883 bool nexthop_othervrf
= false;
6884 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6885 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6888 json_path
= json_object_new_object();
6890 /* short status lead text */
6891 route_vty_short_status_out(vty
, path
, json_path
);
6894 /* print prefix and mask */
6896 route_vty_out_route(p
, vty
, json_path
);
6898 vty_out(vty
, "%*s", 17, " ");
6900 route_vty_out_route(p
, vty
, json_path
);
6903 /* Print attribute */
6907 json_object_array_add(json_paths
, json_path
);
6915 * If vrf id of nexthop is different from that of prefix,
6916 * set up printable string to append
6918 if (path
->extra
&& path
->extra
->bgp_orig
) {
6919 const char *self
= "";
6924 nexthop_othervrf
= true;
6925 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6927 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6928 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6929 "@%s%s", VRFID_NONE_STR
, self
);
6931 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6932 path
->extra
->bgp_orig
->vrf_id
, self
);
6934 if (path
->extra
->bgp_orig
->inst_type
6935 != BGP_INSTANCE_TYPE_DEFAULT
)
6937 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6939 const char *self
= "";
6944 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6948 * For ENCAP and EVPN routes, nexthop address family is not
6949 * neccessarily the same as the prefix address family.
6950 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6951 * EVPN routes are also exchanged with a MP nexthop. Currently,
6953 * is only IPv4, the value will be present in either
6955 * attr->mp_nexthop_global_in
6957 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6960 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6964 sprintf(nexthop
, "%s",
6965 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6969 sprintf(nexthop
, "%s",
6970 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6974 sprintf(nexthop
, "?");
6979 json_nexthop_global
= json_object_new_object();
6981 json_object_string_add(json_nexthop_global
, "afi",
6982 (af
== AF_INET
) ? "ip" : "ipv6");
6983 json_object_string_add(json_nexthop_global
,
6984 (af
== AF_INET
) ? "ip" : "ipv6",
6986 json_object_boolean_true_add(json_nexthop_global
,
6989 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6990 } else if (safi
== SAFI_EVPN
) {
6992 json_nexthop_global
= json_object_new_object();
6994 json_object_string_add(json_nexthop_global
, "ip",
6995 inet_ntoa(attr
->nexthop
));
6996 json_object_string_add(json_nexthop_global
, "afi",
6998 json_object_boolean_true_add(json_nexthop_global
,
7001 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
7003 } else if (safi
== SAFI_FLOWSPEC
) {
7004 if (attr
->nexthop
.s_addr
!= 0) {
7006 json_nexthop_global
= json_object_new_object();
7007 json_object_string_add(
7008 json_nexthop_global
, "ip",
7009 inet_ntoa(attr
->nexthop
));
7010 json_object_string_add(json_nexthop_global
,
7012 json_object_boolean_true_add(
7013 json_nexthop_global
,
7016 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
7019 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7021 json_nexthop_global
= json_object_new_object();
7023 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
7024 json_object_string_add(
7025 json_nexthop_global
, "ip",
7026 inet_ntoa(attr
->mp_nexthop_global_in
));
7028 json_object_string_add(
7029 json_nexthop_global
, "ip",
7030 inet_ntoa(attr
->nexthop
));
7032 json_object_string_add(json_nexthop_global
, "afi",
7034 json_object_boolean_true_add(json_nexthop_global
,
7039 snprintf(buf
, sizeof(buf
), "%s%s",
7040 inet_ntoa(attr
->nexthop
), vrf_id_str
);
7041 vty_out(vty
, "%-16s", buf
);
7046 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7051 json_nexthop_global
= json_object_new_object();
7052 json_object_string_add(
7053 json_nexthop_global
, "ip",
7054 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7056 json_object_string_add(json_nexthop_global
, "afi",
7058 json_object_string_add(json_nexthop_global
, "scope",
7061 /* We display both LL & GL if both have been
7063 if ((attr
->mp_nexthop_len
== 32)
7064 || (path
->peer
->conf_if
)) {
7065 json_nexthop_ll
= json_object_new_object();
7066 json_object_string_add(
7067 json_nexthop_ll
, "ip",
7069 &attr
->mp_nexthop_local
, buf
,
7071 json_object_string_add(json_nexthop_ll
, "afi",
7073 json_object_string_add(json_nexthop_ll
, "scope",
7076 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7077 &attr
->mp_nexthop_local
)
7079 && !attr
->mp_nexthop_prefer_global
)
7080 json_object_boolean_true_add(
7081 json_nexthop_ll
, "used");
7083 json_object_boolean_true_add(
7084 json_nexthop_global
, "used");
7086 json_object_boolean_true_add(
7087 json_nexthop_global
, "used");
7089 /* Display LL if LL/Global both in table unless
7090 * prefer-global is set */
7091 if (((attr
->mp_nexthop_len
== 32)
7092 && !attr
->mp_nexthop_prefer_global
)
7093 || (path
->peer
->conf_if
)) {
7094 if (path
->peer
->conf_if
) {
7095 len
= vty_out(vty
, "%s",
7096 path
->peer
->conf_if
);
7097 len
= 16 - len
; /* len of IPv6
7103 vty_out(vty
, "\n%*s", 36, " ");
7105 vty_out(vty
, "%*s", len
, " ");
7111 &attr
->mp_nexthop_local
,
7117 vty_out(vty
, "\n%*s", 36, " ");
7119 vty_out(vty
, "%*s", len
, " ");
7125 &attr
->mp_nexthop_global
, buf
,
7131 vty_out(vty
, "\n%*s", 36, " ");
7133 vty_out(vty
, "%*s", len
, " ");
7139 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7143 * Adding "metric" field to match with corresponding
7144 * CLI. "med" will be deprecated in future.
7146 json_object_int_add(json_path
, "med", attr
->med
);
7147 json_object_int_add(json_path
, "metric", attr
->med
);
7149 vty_out(vty
, "%10u", attr
->med
);
7150 else if (!json_paths
)
7154 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7158 * Adding "locPrf" field to match with corresponding
7159 * CLI. "localPref" will be deprecated in future.
7161 json_object_int_add(json_path
, "localpref",
7163 json_object_int_add(json_path
, "locPrf",
7166 vty_out(vty
, "%7u", attr
->local_pref
);
7167 else if (!json_paths
)
7171 json_object_int_add(json_path
, "weight", attr
->weight
);
7173 vty_out(vty
, "%7u ", attr
->weight
);
7177 json_object_string_add(
7178 json_path
, "peerId",
7179 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7187 * Adding "path" field to match with corresponding
7188 * CLI. "aspath" will be deprecated in future.
7190 json_object_string_add(json_path
, "aspath",
7192 json_object_string_add(json_path
, "path",
7195 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7200 json_object_string_add(json_path
, "origin",
7201 bgp_origin_long_str
[attr
->origin
]);
7203 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7207 json_object_boolean_true_add(json_path
,
7208 "announceNexthopSelf");
7209 if (nexthop_othervrf
) {
7210 json_object_string_add(json_path
, "nhVrfName",
7213 json_object_int_add(json_path
, "nhVrfId",
7214 ((nexthop_vrfid
== VRF_UNKNOWN
)
7216 : (int)nexthop_vrfid
));
7221 if (json_nexthop_global
|| json_nexthop_ll
) {
7222 json_nexthops
= json_object_new_array();
7224 if (json_nexthop_global
)
7225 json_object_array_add(json_nexthops
,
7226 json_nexthop_global
);
7228 if (json_nexthop_ll
)
7229 json_object_array_add(json_nexthops
,
7232 json_object_object_add(json_path
, "nexthops",
7236 json_object_array_add(json_paths
, json_path
);
7240 /* prints an additional line, indented, with VNC info, if
7242 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7243 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7248 /* called from terminal list command */
7249 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7250 safi_t safi
, bool use_json
, json_object
*json_ar
)
7252 json_object
*json_status
= NULL
;
7253 json_object
*json_net
= NULL
;
7256 /* Route status display. */
7258 json_status
= json_object_new_object();
7259 json_net
= json_object_new_object();
7266 /* print prefix and mask */
7268 json_object_string_add(
7269 json_net
, "addrPrefix",
7270 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
7271 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
7272 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7273 json_object_string_add(json_net
, "network", buf2
);
7275 route_vty_out_route(p
, vty
, NULL
);
7277 /* Print attribute */
7280 if (p
->family
== AF_INET
7281 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7282 || safi
== SAFI_EVPN
7283 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7284 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7285 || safi
== SAFI_EVPN
)
7286 json_object_string_add(
7287 json_net
, "nextHop",
7289 attr
->mp_nexthop_global_in
));
7291 json_object_string_add(
7292 json_net
, "nextHop",
7293 inet_ntoa(attr
->nexthop
));
7294 } else if (p
->family
== AF_INET6
7295 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7298 json_object_string_add(
7299 json_net
, "nextHopGlobal",
7301 &attr
->mp_nexthop_global
, buf
,
7306 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7307 json_object_int_add(json_net
, "metric",
7310 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7313 * Adding "locPrf" field to match with
7314 * corresponding CLI. "localPref" will be
7315 * deprecated in future.
7317 json_object_int_add(json_net
, "localPref",
7319 json_object_int_add(json_net
, "locPrf",
7323 json_object_int_add(json_net
, "weight", attr
->weight
);
7329 * Adding "path" field to match with
7330 * corresponding CLI. "localPref" will be
7331 * deprecated in future.
7333 json_object_string_add(json_net
, "asPath",
7335 json_object_string_add(json_net
, "path",
7340 json_object_string_add(json_net
, "bgpOriginCode",
7341 bgp_origin_str
[attr
->origin
]);
7343 if (p
->family
== AF_INET
7344 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7345 || safi
== SAFI_EVPN
7346 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7347 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7348 || safi
== SAFI_EVPN
)
7349 vty_out(vty
, "%-16s",
7351 attr
->mp_nexthop_global_in
));
7353 vty_out(vty
, "%-16s",
7354 inet_ntoa(attr
->nexthop
));
7355 } else if (p
->family
== AF_INET6
7356 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7363 &attr
->mp_nexthop_global
, buf
,
7367 vty_out(vty
, "\n%*s", 36, " ");
7369 vty_out(vty
, "%*s", len
, " ");
7372 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7373 vty_out(vty
, "%10u", attr
->med
);
7377 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7378 vty_out(vty
, "%7u", attr
->local_pref
);
7382 vty_out(vty
, "%7u ", attr
->weight
);
7386 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7389 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7393 json_object_boolean_true_add(json_status
, "*");
7394 json_object_boolean_true_add(json_status
, ">");
7395 json_object_object_add(json_net
, "appliedStatusSymbols",
7397 char buf_cut
[BUFSIZ
];
7398 json_object_object_add(
7400 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7406 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7407 struct bgp_path_info
*path
, int display
, safi_t safi
,
7410 json_object
*json_out
= NULL
;
7412 mpls_label_t label
= MPLS_INVALID_LABEL
;
7418 json_out
= json_object_new_object();
7420 /* short status lead text */
7421 route_vty_short_status_out(vty
, path
, json_out
);
7423 /* print prefix and mask */
7426 route_vty_out_route(p
, vty
, NULL
);
7428 vty_out(vty
, "%*s", 17, " ");
7431 /* Print attribute */
7434 if (((p
->family
== AF_INET
)
7435 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7436 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7437 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7438 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7439 || safi
== SAFI_EVPN
) {
7441 json_object_string_add(
7442 json_out
, "mpNexthopGlobalIn",
7444 attr
->mp_nexthop_global_in
));
7446 vty_out(vty
, "%-16s",
7448 attr
->mp_nexthop_global_in
));
7451 json_object_string_add(
7452 json_out
, "nexthop",
7453 inet_ntoa(attr
->nexthop
));
7455 vty_out(vty
, "%-16s",
7456 inet_ntoa(attr
->nexthop
));
7458 } else if (((p
->family
== AF_INET6
)
7459 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7460 || (safi
== SAFI_EVPN
7461 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7462 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7466 if (attr
->mp_nexthop_len
7467 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7469 json_object_string_add(
7470 json_out
, "mpNexthopGlobalIn",
7473 &attr
->mp_nexthop_global
,
7474 buf_a
, sizeof(buf_a
)));
7479 &attr
->mp_nexthop_global
,
7480 buf_a
, sizeof(buf_a
)));
7481 } else if (attr
->mp_nexthop_len
7482 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7485 &attr
->mp_nexthop_global
,
7486 buf_a
, sizeof(buf_a
));
7488 &attr
->mp_nexthop_local
,
7489 buf_b
, sizeof(buf_b
));
7490 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7491 json_object_string_add(
7493 "mpNexthopGlobalLocal", buf_c
);
7495 vty_out(vty
, "%s(%s)",
7498 &attr
->mp_nexthop_global
,
7499 buf_a
, sizeof(buf_a
)),
7502 &attr
->mp_nexthop_local
,
7503 buf_b
, sizeof(buf_b
)));
7508 label
= decode_label(&path
->extra
->label
[0]);
7510 if (bgp_is_valid_label(&label
)) {
7512 json_object_int_add(json_out
, "notag", label
);
7513 json_object_array_add(json
, json_out
);
7515 vty_out(vty
, "notag/%d", label
);
7521 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7522 struct bgp_path_info
*path
, int display
,
7523 json_object
*json_paths
)
7527 json_object
*json_path
= NULL
;
7530 json_path
= json_object_new_object();
7535 /* short status lead text */
7536 route_vty_short_status_out(vty
, path
, json_path
);
7538 /* print prefix and mask */
7540 route_vty_out_route(p
, vty
, NULL
);
7542 vty_out(vty
, "%*s", 17, " ");
7544 /* Print attribute */
7548 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7552 vty_out(vty
, "%-16s",
7553 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7557 vty_out(vty
, "%s(%s)",
7558 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7560 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7567 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7569 vty_out(vty
, "%s", str
);
7570 XFREE(MTYPE_TMP
, str
);
7572 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7574 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7575 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7578 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7581 if (attr
->ecommunity
) {
7583 struct ecommunity_val
*routermac
= ecommunity_lookup(
7584 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7585 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7587 mac
= ecom_mac2str((char *)routermac
->val
);
7589 vty_out(vty
, "/%s", (char *)mac
);
7590 XFREE(MTYPE_TMP
, mac
);
7598 /* dampening route */
7599 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7600 struct bgp_path_info
*path
, int display
,
7601 safi_t safi
, bool use_json
, json_object
*json
)
7605 char timebuf
[BGP_UPTIME_LEN
];
7607 /* short status lead text */
7608 route_vty_short_status_out(vty
, path
, json
);
7610 /* print prefix and mask */
7613 route_vty_out_route(p
, vty
, NULL
);
7615 vty_out(vty
, "%*s", 17, " ");
7618 len
= vty_out(vty
, "%s", path
->peer
->host
);
7622 vty_out(vty
, "\n%*s", 34, " ");
7625 json_object_int_add(json
, "peerHost", len
);
7627 vty_out(vty
, "%*s", len
, " ");
7631 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7635 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7636 BGP_UPTIME_LEN
, use_json
,
7639 /* Print attribute */
7645 json_object_string_add(json
, "asPath",
7648 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7653 json_object_string_add(json
, "origin",
7654 bgp_origin_str
[attr
->origin
]);
7656 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7663 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7664 struct bgp_path_info
*path
, int display
,
7665 safi_t safi
, bool use_json
, json_object
*json
)
7668 struct bgp_damp_info
*bdi
;
7669 char timebuf
[BGP_UPTIME_LEN
];
7675 bdi
= path
->extra
->damp_info
;
7677 /* short status lead text */
7678 route_vty_short_status_out(vty
, path
, json
);
7680 /* print prefix and mask */
7683 route_vty_out_route(p
, vty
, NULL
);
7685 vty_out(vty
, "%*s", 17, " ");
7688 len
= vty_out(vty
, "%s", path
->peer
->host
);
7692 vty_out(vty
, "\n%*s", 33, " ");
7695 json_object_int_add(json
, "peerHost", len
);
7697 vty_out(vty
, "%*s", len
, " ");
7700 len
= vty_out(vty
, "%d", bdi
->flap
);
7707 json_object_int_add(json
, "bdiFlap", len
);
7709 vty_out(vty
, "%*s", len
, " ");
7713 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7716 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7717 BGP_UPTIME_LEN
, 0, NULL
));
7719 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7720 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7722 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7723 BGP_UPTIME_LEN
, use_json
, json
);
7726 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7731 vty_out(vty
, "%*s ", 8, " ");
7734 /* Print attribute */
7740 json_object_string_add(json
, "asPath",
7743 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7748 json_object_string_add(json
, "origin",
7749 bgp_origin_str
[attr
->origin
]);
7751 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7757 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7758 int *first
, const char *header
,
7759 json_object
*json_adv_to
)
7761 char buf1
[INET6_ADDRSTRLEN
];
7762 json_object
*json_peer
= NULL
;
7765 /* 'advertised-to' is a dictionary of peers we have advertised
7767 * prefix too. The key is the peer's IP or swpX, the value is
7769 * hostname if we know it and "" if not.
7771 json_peer
= json_object_new_object();
7774 json_object_string_add(json_peer
, "hostname",
7778 json_object_object_add(json_adv_to
, peer
->conf_if
,
7781 json_object_object_add(
7783 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7787 vty_out(vty
, "%s", header
);
7792 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7794 vty_out(vty
, " %s(%s)", peer
->hostname
,
7797 vty_out(vty
, " %s(%s)", peer
->hostname
,
7798 sockunion2str(&peer
->su
, buf1
,
7802 vty_out(vty
, " %s", peer
->conf_if
);
7805 sockunion2str(&peer
->su
, buf1
,
7811 static void route_vty_out_tx_ids(struct vty
*vty
,
7812 struct bgp_addpath_info_data
*d
)
7816 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7817 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7818 d
->addpath_tx_id
[i
],
7819 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7823 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7824 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7825 json_object
*json_paths
)
7827 char buf
[INET6_ADDRSTRLEN
];
7829 char buf2
[EVPN_ROUTE_STRLEN
];
7831 int sockunion_vty_out(struct vty
*, union sockunion
*);
7833 json_object
*json_bestpath
= NULL
;
7834 json_object
*json_cluster_list
= NULL
;
7835 json_object
*json_cluster_list_list
= NULL
;
7836 json_object
*json_ext_community
= NULL
;
7837 json_object
*json_last_update
= NULL
;
7838 json_object
*json_pmsi
= NULL
;
7839 json_object
*json_nexthop_global
= NULL
;
7840 json_object
*json_nexthop_ll
= NULL
;
7841 json_object
*json_nexthops
= NULL
;
7842 json_object
*json_path
= NULL
;
7843 json_object
*json_peer
= NULL
;
7844 json_object
*json_string
= NULL
;
7845 json_object
*json_adv_to
= NULL
;
7847 struct listnode
*node
, *nnode
;
7849 int addpath_capable
;
7851 unsigned int first_as
;
7853 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7857 json_path
= json_object_new_object();
7858 json_peer
= json_object_new_object();
7859 json_nexthop_global
= json_object_new_object();
7862 if (!json_paths
&& safi
== SAFI_EVPN
) {
7865 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7866 vty_out(vty
, " Route %s", buf2
);
7868 if (path
->extra
&& path
->extra
->num_labels
) {
7869 bgp_evpn_label2str(path
->extra
->label
,
7870 path
->extra
->num_labels
, tag_buf
,
7872 vty_out(vty
, " VNI %s", tag_buf
);
7875 if (path
->extra
&& path
->extra
->parent
) {
7876 struct bgp_path_info
*parent_ri
;
7877 struct bgp_node
*rn
, *prn
;
7879 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7880 rn
= parent_ri
->net
;
7881 if (rn
&& rn
->prn
) {
7883 vty_out(vty
, " Imported from %s:%s\n",
7885 (struct prefix_rd
*)&prn
->p
,
7886 buf1
, sizeof(buf1
)),
7895 /* Line1 display AS-path, Aggregator */
7898 if (!attr
->aspath
->json
)
7899 aspath_str_update(attr
->aspath
, true);
7900 json_object_lock(attr
->aspath
->json
);
7901 json_object_object_add(json_path
, "aspath",
7902 attr
->aspath
->json
);
7904 if (attr
->aspath
->segments
)
7905 aspath_print_vty(vty
, " %s",
7908 vty_out(vty
, " Local");
7912 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7914 json_object_boolean_true_add(json_path
,
7917 vty_out(vty
, ", (removed)");
7920 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7922 json_object_boolean_true_add(json_path
,
7925 vty_out(vty
, ", (stale)");
7928 if (CHECK_FLAG(attr
->flag
,
7929 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7931 json_object_int_add(json_path
, "aggregatorAs",
7932 attr
->aggregator_as
);
7933 json_object_string_add(
7934 json_path
, "aggregatorId",
7935 inet_ntoa(attr
->aggregator_addr
));
7937 vty_out(vty
, ", (aggregated by %u %s)",
7938 attr
->aggregator_as
,
7939 inet_ntoa(attr
->aggregator_addr
));
7943 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7944 PEER_FLAG_REFLECTOR_CLIENT
)) {
7946 json_object_boolean_true_add(
7947 json_path
, "rxedFromRrClient");
7949 vty_out(vty
, ", (Received from a RR-client)");
7952 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7953 PEER_FLAG_RSERVER_CLIENT
)) {
7955 json_object_boolean_true_add(
7956 json_path
, "rxedFromRsClient");
7958 vty_out(vty
, ", (Received from a RS-client)");
7961 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7963 json_object_boolean_true_add(
7964 json_path
, "dampeningHistoryEntry");
7966 vty_out(vty
, ", (history entry)");
7967 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
7969 json_object_boolean_true_add(
7970 json_path
, "dampeningSuppressed");
7972 vty_out(vty
, ", (suppressed due to dampening)");
7978 /* Line2 display Next-hop, Neighbor, Router-id */
7979 /* Display the nexthop */
7980 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7981 || p
->family
== AF_EVPN
)
7982 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7983 || safi
== SAFI_EVPN
7984 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7985 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7986 || safi
== SAFI_EVPN
) {
7988 json_object_string_add(
7989 json_nexthop_global
, "ip",
7991 attr
->mp_nexthop_global_in
));
7995 attr
->mp_nexthop_global_in
));
7998 json_object_string_add(
7999 json_nexthop_global
, "ip",
8000 inet_ntoa(attr
->nexthop
));
8003 inet_ntoa(attr
->nexthop
));
8007 json_object_string_add(json_nexthop_global
,
8011 json_object_string_add(
8012 json_nexthop_global
, "ip",
8014 &attr
->mp_nexthop_global
, buf
,
8016 json_object_string_add(json_nexthop_global
,
8018 json_object_string_add(json_nexthop_global
,
8023 &attr
->mp_nexthop_global
, buf
,
8028 /* Display the IGP cost or 'inaccessible' */
8029 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8031 json_object_boolean_false_add(
8032 json_nexthop_global
, "accessible");
8034 vty_out(vty
, " (inaccessible)");
8036 if (path
->extra
&& path
->extra
->igpmetric
) {
8038 json_object_int_add(
8039 json_nexthop_global
, "metric",
8040 path
->extra
->igpmetric
);
8042 vty_out(vty
, " (metric %u)",
8043 path
->extra
->igpmetric
);
8046 /* IGP cost is 0, display this only for json */
8049 json_object_int_add(json_nexthop_global
,
8054 json_object_boolean_true_add(
8055 json_nexthop_global
, "accessible");
8058 /* Display peer "from" output */
8059 /* This path was originated locally */
8060 if (path
->peer
== bgp
->peer_self
) {
8062 if (safi
== SAFI_EVPN
8063 || (p
->family
== AF_INET
8064 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8066 json_object_string_add(
8067 json_peer
, "peerId", "0.0.0.0");
8069 vty_out(vty
, " from 0.0.0.0 ");
8072 json_object_string_add(json_peer
,
8075 vty_out(vty
, " from :: ");
8079 json_object_string_add(
8080 json_peer
, "routerId",
8081 inet_ntoa(bgp
->router_id
));
8083 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8086 /* We RXed this path from one of our peers */
8090 json_object_string_add(
8091 json_peer
, "peerId",
8092 sockunion2str(&path
->peer
->su
, buf
,
8094 json_object_string_add(
8095 json_peer
, "routerId",
8097 &path
->peer
->remote_id
, buf1
,
8100 if (path
->peer
->hostname
)
8101 json_object_string_add(
8102 json_peer
, "hostname",
8103 path
->peer
->hostname
);
8105 if (path
->peer
->domainname
)
8106 json_object_string_add(
8107 json_peer
, "domainname",
8108 path
->peer
->domainname
);
8110 if (path
->peer
->conf_if
)
8111 json_object_string_add(
8112 json_peer
, "interface",
8113 path
->peer
->conf_if
);
8115 if (path
->peer
->conf_if
) {
8116 if (path
->peer
->hostname
8119 BGP_FLAG_SHOW_HOSTNAME
))
8120 vty_out(vty
, " from %s(%s)",
8121 path
->peer
->hostname
,
8122 path
->peer
->conf_if
);
8124 vty_out(vty
, " from %s",
8125 path
->peer
->conf_if
);
8127 if (path
->peer
->hostname
8130 BGP_FLAG_SHOW_HOSTNAME
))
8131 vty_out(vty
, " from %s(%s)",
8132 path
->peer
->hostname
,
8135 vty_out(vty
, " from %s",
8143 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8144 vty_out(vty
, " (%s)",
8145 inet_ntoa(attr
->originator_id
));
8147 vty_out(vty
, " (%s)",
8150 &path
->peer
->remote_id
,
8151 buf1
, sizeof(buf1
)));
8156 * Note when vrfid of nexthop is different from that of prefix
8158 if (path
->extra
&& path
->extra
->bgp_orig
) {
8159 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8164 if (path
->extra
->bgp_orig
->inst_type
8165 == BGP_INSTANCE_TYPE_DEFAULT
)
8167 vn
= VRF_DEFAULT_NAME
;
8169 vn
= path
->extra
->bgp_orig
->name
;
8171 json_object_string_add(json_path
, "nhVrfName",
8174 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8175 json_object_int_add(json_path
,
8178 json_object_int_add(json_path
,
8179 "nhVrfId", (int)nexthop_vrfid
);
8182 if (nexthop_vrfid
== VRF_UNKNOWN
)
8183 vty_out(vty
, " vrf ?");
8185 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8191 json_object_boolean_true_add(json_path
,
8192 "announceNexthopSelf");
8194 vty_out(vty
, " announce-nh-self");
8201 /* display the link-local nexthop */
8202 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8204 json_nexthop_ll
= json_object_new_object();
8205 json_object_string_add(
8206 json_nexthop_ll
, "ip",
8208 &attr
->mp_nexthop_local
, buf
,
8210 json_object_string_add(json_nexthop_ll
, "afi",
8212 json_object_string_add(json_nexthop_ll
, "scope",
8215 json_object_boolean_true_add(json_nexthop_ll
,
8218 if (!attr
->mp_nexthop_prefer_global
)
8219 json_object_boolean_true_add(
8220 json_nexthop_ll
, "used");
8222 json_object_boolean_true_add(
8223 json_nexthop_global
, "used");
8225 vty_out(vty
, " (%s) %s\n",
8227 &attr
->mp_nexthop_local
, buf
,
8229 attr
->mp_nexthop_prefer_global
8234 /* If we do not have a link-local nexthop then we must flag the
8238 json_object_boolean_true_add(
8239 json_nexthop_global
, "used");
8242 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8243 * Int/Ext/Local, Atomic, best */
8245 json_object_string_add(
8246 json_path
, "origin",
8247 bgp_origin_long_str
[attr
->origin
]);
8249 vty_out(vty
, " Origin %s",
8250 bgp_origin_long_str
[attr
->origin
]);
8252 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8256 * Adding "metric" field to match with
8257 * corresponding CLI. "med" will be
8258 * deprecated in future.
8260 json_object_int_add(json_path
, "med",
8262 json_object_int_add(json_path
, "metric",
8265 vty_out(vty
, ", metric %u", attr
->med
);
8268 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8270 json_object_int_add(json_path
, "localpref",
8273 vty_out(vty
, ", localpref %u",
8277 if (attr
->weight
!= 0) {
8279 json_object_int_add(json_path
, "weight",
8282 vty_out(vty
, ", weight %u", attr
->weight
);
8285 if (attr
->tag
!= 0) {
8287 json_object_int_add(json_path
, "tag",
8290 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8294 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8296 json_object_boolean_false_add(json_path
,
8299 vty_out(vty
, ", invalid");
8300 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8302 json_object_boolean_true_add(json_path
,
8305 vty_out(vty
, ", valid");
8308 if (path
->peer
!= bgp
->peer_self
) {
8309 if (path
->peer
->as
== path
->peer
->local_as
) {
8310 if (CHECK_FLAG(bgp
->config
,
8311 BGP_CONFIG_CONFEDERATION
)) {
8313 json_object_string_add(
8318 ", confed-internal");
8321 json_object_string_add(
8325 vty_out(vty
, ", internal");
8328 if (bgp_confederation_peers_check(
8329 bgp
, path
->peer
->as
)) {
8331 json_object_string_add(
8336 ", confed-external");
8339 json_object_string_add(
8343 vty_out(vty
, ", external");
8346 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8348 json_object_boolean_true_add(json_path
,
8350 json_object_boolean_true_add(json_path
,
8353 vty_out(vty
, ", aggregated, local");
8355 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8357 json_object_boolean_true_add(json_path
,
8360 vty_out(vty
, ", sourced");
8363 json_object_boolean_true_add(json_path
,
8365 json_object_boolean_true_add(json_path
,
8368 vty_out(vty
, ", sourced, local");
8372 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8374 json_object_boolean_true_add(json_path
,
8377 vty_out(vty
, ", atomic-aggregate");
8380 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8381 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8382 && bgp_path_info_mpath_count(path
))) {
8384 json_object_boolean_true_add(json_path
,
8387 vty_out(vty
, ", multipath");
8390 // Mark the bestpath(s)
8391 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8392 first_as
= aspath_get_first_as(attr
->aspath
);
8397 json_object_new_object();
8398 json_object_int_add(json_bestpath
,
8399 "bestpathFromAs", first_as
);
8402 vty_out(vty
, ", bestpath-from-AS %u",
8406 ", bestpath-from-AS Local");
8410 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8414 json_object_new_object();
8415 json_object_boolean_true_add(json_bestpath
,
8418 vty_out(vty
, ", best");
8422 json_object_object_add(json_path
, "bestpath",
8428 /* Line 4 display Community */
8429 if (attr
->community
) {
8431 if (!attr
->community
->json
)
8432 community_str(attr
->community
, true);
8433 json_object_lock(attr
->community
->json
);
8434 json_object_object_add(json_path
, "community",
8435 attr
->community
->json
);
8437 vty_out(vty
, " Community: %s\n",
8438 attr
->community
->str
);
8442 /* Line 5 display Extended-community */
8443 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8445 json_ext_community
= json_object_new_object();
8446 json_object_string_add(json_ext_community
,
8448 attr
->ecommunity
->str
);
8449 json_object_object_add(json_path
,
8450 "extendedCommunity",
8451 json_ext_community
);
8453 vty_out(vty
, " Extended Community: %s\n",
8454 attr
->ecommunity
->str
);
8458 /* Line 6 display Large community */
8459 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8461 if (!attr
->lcommunity
->json
)
8462 lcommunity_str(attr
->lcommunity
, true);
8463 json_object_lock(attr
->lcommunity
->json
);
8464 json_object_object_add(json_path
,
8466 attr
->lcommunity
->json
);
8468 vty_out(vty
, " Large Community: %s\n",
8469 attr
->lcommunity
->str
);
8473 /* Line 7 display Originator, Cluster-id */
8474 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8475 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8477 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8479 json_object_string_add(
8480 json_path
, "originatorId",
8481 inet_ntoa(attr
->originator_id
));
8483 vty_out(vty
, " Originator: %s",
8484 inet_ntoa(attr
->originator_id
));
8487 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8492 json_object_new_object();
8493 json_cluster_list_list
=
8494 json_object_new_array();
8497 i
< attr
->cluster
->length
/ 4;
8499 json_string
= json_object_new_string(
8503 json_object_array_add(
8504 json_cluster_list_list
,
8508 /* struct cluster_list does not have
8510 * aspath and community do. Add this
8513 json_object_string_add(json_cluster_list,
8514 "string", attr->cluster->str);
8516 json_object_object_add(
8517 json_cluster_list
, "list",
8518 json_cluster_list_list
);
8519 json_object_object_add(
8520 json_path
, "clusterList",
8523 vty_out(vty
, ", Cluster list: ");
8526 i
< attr
->cluster
->length
/ 4;
8540 if (path
->extra
&& path
->extra
->damp_info
)
8541 bgp_damp_info_vty(vty
, path
, json_path
);
8544 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8545 && safi
!= SAFI_EVPN
) {
8546 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8549 json_object_int_add(json_path
, "remoteLabel",
8552 vty_out(vty
, " Remote label: %d\n", label
);
8556 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8558 json_object_int_add(json_path
, "labelIndex",
8561 vty_out(vty
, " Label Index: %d\n",
8565 /* Line 8 display Addpath IDs */
8566 if (path
->addpath_rx_id
8567 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8569 json_object_int_add(json_path
, "addpathRxId",
8570 path
->addpath_rx_id
);
8572 /* Keep backwards compatibility with the old API
8573 * by putting TX All's ID in the old field
8575 json_object_int_add(
8576 json_path
, "addpathTxId",
8577 path
->tx_addpath
.addpath_tx_id
8580 /* ... but create a specific field for each
8583 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8584 json_object_int_add(
8586 bgp_addpath_names(i
)
8592 vty_out(vty
, " AddPath ID: RX %u, ",
8593 path
->addpath_rx_id
);
8595 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8599 /* If we used addpath to TX a non-bestpath we need to display
8600 * "Advertised to" on a path-by-path basis
8602 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8605 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8607 bgp_addpath_encode_tx(peer
, afi
, safi
);
8608 has_adj
= bgp_adj_out_lookup(
8610 bgp_addpath_id_for_peer(
8612 &path
->tx_addpath
));
8614 if ((addpath_capable
&& has_adj
)
8615 || (!addpath_capable
&& has_adj
8616 && CHECK_FLAG(path
->flags
,
8617 BGP_PATH_SELECTED
))) {
8618 if (json_path
&& !json_adv_to
)
8620 json_object_new_object();
8622 route_vty_out_advertised_to(
8631 json_object_object_add(json_path
,
8642 /* Line 9 display Uptime */
8643 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8645 json_last_update
= json_object_new_object();
8646 json_object_int_add(json_last_update
, "epoch", tbuf
);
8647 json_object_string_add(json_last_update
, "string",
8649 json_object_object_add(json_path
, "lastUpdate",
8652 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8654 /* Line 10 display PMSI tunnel attribute, if present */
8655 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8656 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8657 attr
->pmsi_tnl_type
,
8658 PMSI_TNLTYPE_STR_DEFAULT
);
8661 json_pmsi
= json_object_new_object();
8662 json_object_string_add(json_pmsi
,
8664 json_object_int_add(json_pmsi
,
8666 label2vni(&attr
->label
));
8667 json_object_object_add(json_path
, "pmsi",
8671 " PMSI Tunnel Type: %s, label: %d\n",
8672 str
, label2vni(&attr
->label
));
8677 /* We've constructed the json object for this path, add it to the json
8681 if (json_nexthop_global
|| json_nexthop_ll
) {
8682 json_nexthops
= json_object_new_array();
8684 if (json_nexthop_global
)
8685 json_object_array_add(json_nexthops
,
8686 json_nexthop_global
);
8688 if (json_nexthop_ll
)
8689 json_object_array_add(json_nexthops
,
8692 json_object_object_add(json_path
, "nexthops",
8696 json_object_object_add(json_path
, "peer", json_peer
);
8697 json_object_array_add(json_paths
, json_path
);
8702 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8703 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8704 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8706 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8707 const char *prefix_list_str
, afi_t afi
,
8708 safi_t safi
, enum bgp_show_type type
);
8709 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8710 const char *filter
, afi_t afi
, safi_t safi
,
8711 enum bgp_show_type type
);
8712 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8713 const char *rmap_str
, afi_t afi
, safi_t safi
,
8714 enum bgp_show_type type
);
8715 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8716 const char *com
, int exact
, afi_t afi
,
8718 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8719 const char *prefix
, afi_t afi
, safi_t safi
,
8720 enum bgp_show_type type
);
8721 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8722 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8723 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8724 const char *comstr
, int exact
, afi_t afi
,
8725 safi_t safi
, bool use_json
);
8728 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8729 struct bgp_table
*table
, enum bgp_show_type type
,
8730 void *output_arg
, bool use_json
, char *rd
,
8731 int is_last
, unsigned long *output_cum
,
8732 unsigned long *total_cum
,
8733 unsigned long *json_header_depth
)
8735 struct bgp_path_info
*pi
;
8736 struct bgp_node
*rn
;
8739 unsigned long output_count
= 0;
8740 unsigned long total_count
= 0;
8743 json_object
*json_paths
= NULL
;
8746 if (output_cum
&& *output_cum
!= 0)
8749 if (use_json
&& !*json_header_depth
) {
8751 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8752 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8753 " \"localAS\": %u,\n \"routes\": { ",
8754 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8755 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8758 table
->version
, inet_ntoa(bgp
->router_id
),
8759 bgp
->default_local_pref
, bgp
->as
);
8760 *json_header_depth
= 2;
8762 vty_out(vty
, " \"routeDistinguishers\" : {");
8763 ++*json_header_depth
;
8767 if (use_json
&& rd
) {
8768 vty_out(vty
, " \"%s\" : { ", rd
);
8771 /* Start processing of routes. */
8772 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8773 pi
= bgp_node_get_bgp_path_info(rn
);
8779 json_paths
= json_object_new_array();
8783 for (; pi
; pi
= pi
->next
) {
8785 if (type
== bgp_show_type_flap_statistics
8786 || type
== bgp_show_type_flap_neighbor
8787 || type
== bgp_show_type_dampend_paths
8788 || type
== bgp_show_type_damp_neighbor
) {
8789 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8792 if (type
== bgp_show_type_regexp
) {
8793 regex_t
*regex
= output_arg
;
8795 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8799 if (type
== bgp_show_type_prefix_list
) {
8800 struct prefix_list
*plist
= output_arg
;
8802 if (prefix_list_apply(plist
, &rn
->p
)
8806 if (type
== bgp_show_type_filter_list
) {
8807 struct as_list
*as_list
= output_arg
;
8809 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8810 != AS_FILTER_PERMIT
)
8813 if (type
== bgp_show_type_route_map
) {
8814 struct route_map
*rmap
= output_arg
;
8815 struct bgp_path_info path
;
8816 struct attr dummy_attr
;
8819 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8821 path
.peer
= pi
->peer
;
8822 path
.attr
= &dummy_attr
;
8824 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8826 if (ret
== RMAP_DENYMATCH
)
8829 if (type
== bgp_show_type_neighbor
8830 || type
== bgp_show_type_flap_neighbor
8831 || type
== bgp_show_type_damp_neighbor
) {
8832 union sockunion
*su
= output_arg
;
8834 if (pi
->peer
== NULL
8835 || pi
->peer
->su_remote
== NULL
8836 || !sockunion_same(pi
->peer
->su_remote
, su
))
8839 if (type
== bgp_show_type_cidr_only
) {
8840 uint32_t destination
;
8842 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8843 if (IN_CLASSC(destination
)
8844 && rn
->p
.prefixlen
== 24)
8846 if (IN_CLASSB(destination
)
8847 && rn
->p
.prefixlen
== 16)
8849 if (IN_CLASSA(destination
)
8850 && rn
->p
.prefixlen
== 8)
8853 if (type
== bgp_show_type_prefix_longer
) {
8855 if (!prefix_match(p
, &rn
->p
))
8858 if (type
== bgp_show_type_community_all
) {
8859 if (!pi
->attr
->community
)
8862 if (type
== bgp_show_type_community
) {
8863 struct community
*com
= output_arg
;
8865 if (!pi
->attr
->community
8866 || !community_match(pi
->attr
->community
,
8870 if (type
== bgp_show_type_community_exact
) {
8871 struct community
*com
= output_arg
;
8873 if (!pi
->attr
->community
8874 || !community_cmp(pi
->attr
->community
, com
))
8877 if (type
== bgp_show_type_community_list
) {
8878 struct community_list
*list
= output_arg
;
8880 if (!community_list_match(pi
->attr
->community
,
8884 if (type
== bgp_show_type_community_list_exact
) {
8885 struct community_list
*list
= output_arg
;
8887 if (!community_list_exact_match(
8888 pi
->attr
->community
, list
))
8891 if (type
== bgp_show_type_lcommunity
) {
8892 struct lcommunity
*lcom
= output_arg
;
8894 if (!pi
->attr
->lcommunity
8895 || !lcommunity_match(pi
->attr
->lcommunity
,
8899 if (type
== bgp_show_type_lcommunity_list
) {
8900 struct community_list
*list
= output_arg
;
8902 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8906 if (type
== bgp_show_type_lcommunity_all
) {
8907 if (!pi
->attr
->lcommunity
)
8910 if (type
== bgp_show_type_dampend_paths
8911 || type
== bgp_show_type_damp_neighbor
) {
8912 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8913 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8917 if (!use_json
&& header
) {
8918 vty_out(vty
, "BGP table version is %" PRIu64
8919 ", local router ID is %s, vrf id ",
8921 inet_ntoa(bgp
->router_id
));
8922 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8923 vty_out(vty
, "%s", VRFID_NONE_STR
);
8925 vty_out(vty
, "%u", bgp
->vrf_id
);
8927 vty_out(vty
, "Default local pref %u, ",
8928 bgp
->default_local_pref
);
8929 vty_out(vty
, "local AS %u\n", bgp
->as
);
8930 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8931 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8932 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8933 if (type
== bgp_show_type_dampend_paths
8934 || type
== bgp_show_type_damp_neighbor
)
8935 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8936 else if (type
== bgp_show_type_flap_statistics
8937 || type
== bgp_show_type_flap_neighbor
)
8938 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8940 vty_out(vty
, BGP_SHOW_HEADER
);
8943 if (rd
!= NULL
&& !display
&& !output_count
) {
8946 "Route Distinguisher: %s\n",
8949 if (type
== bgp_show_type_dampend_paths
8950 || type
== bgp_show_type_damp_neighbor
)
8951 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
8952 safi
, use_json
, json_paths
);
8953 else if (type
== bgp_show_type_flap_statistics
8954 || type
== bgp_show_type_flap_neighbor
)
8955 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
8956 safi
, use_json
, json_paths
);
8958 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
8970 if (p
->family
== AF_FLOWSPEC
) {
8971 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
8973 bgp_fs_nlri_get_string((unsigned char *)
8974 p
->u
.prefix_flowspec
.ptr
,
8975 p
->u
.prefix_flowspec
8978 NLRI_STRING_FORMAT_MIN
,
8981 vty_out(vty
, "\"%s/%d\": ",
8983 p
->u
.prefix_flowspec
.prefixlen
);
8985 vty_out(vty
, ",\"%s/%d\": ",
8987 p
->u
.prefix_flowspec
.prefixlen
);
8989 prefix2str(p
, buf2
, sizeof(buf2
));
8991 vty_out(vty
, "\"%s\": ", buf2
);
8993 vty_out(vty
, ",\"%s\": ", buf2
);
8996 json_object_to_json_string(json_paths
));
8997 json_object_free(json_paths
);
9004 output_count
+= *output_cum
;
9005 *output_cum
= output_count
;
9008 total_count
+= *total_cum
;
9009 *total_cum
= total_count
;
9013 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9017 for (i
= 0; i
< *json_header_depth
; ++i
)
9018 vty_out(vty
, " } ");
9022 /* No route is displayed */
9023 if (output_count
== 0) {
9024 if (type
== bgp_show_type_normal
)
9026 "No BGP prefixes displayed, %ld exist\n",
9030 "\nDisplayed %ld routes and %ld total paths\n",
9031 output_count
, total_count
);
9038 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9039 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9040 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9042 struct bgp_node
*rn
, *next
;
9043 unsigned long output_cum
= 0;
9044 unsigned long total_cum
= 0;
9045 unsigned long json_header_depth
= 0;
9046 struct bgp_table
*itable
;
9049 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9051 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9052 next
= bgp_route_next(rn
);
9053 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9056 itable
= bgp_node_get_bgp_table_info(rn
);
9057 if (itable
!= NULL
) {
9058 struct prefix_rd prd
;
9059 char rd
[RD_ADDRSTRLEN
];
9061 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9062 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9063 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9064 use_json
, rd
, next
== NULL
, &output_cum
,
9065 &total_cum
, &json_header_depth
);
9071 if (output_cum
== 0)
9072 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9076 "\nDisplayed %ld routes and %ld total paths\n",
9077 output_cum
, total_cum
);
9081 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9082 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9084 struct bgp_table
*table
;
9085 unsigned long json_header_depth
= 0;
9088 bgp
= bgp_get_default();
9093 vty_out(vty
, "No BGP process is configured\n");
9095 vty_out(vty
, "{}\n");
9099 table
= bgp
->rib
[afi
][safi
];
9100 /* use MPLS and ENCAP specific shows until they are merged */
9101 if (safi
== SAFI_MPLS_VPN
) {
9102 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9103 output_arg
, use_json
);
9106 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9107 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9108 output_arg
, use_json
,
9111 /* labeled-unicast routes live in the unicast table */
9112 else if (safi
== SAFI_LABELED_UNICAST
)
9113 safi
= SAFI_UNICAST
;
9115 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9116 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9119 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9120 safi_t safi
, bool use_json
)
9122 struct listnode
*node
, *nnode
;
9125 bool route_output
= false;
9128 vty_out(vty
, "{\n");
9130 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9131 route_output
= true;
9134 vty_out(vty
, ",\n");
9138 vty_out(vty
, "\"%s\":",
9139 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9143 vty_out(vty
, "\nInstance %s:\n",
9144 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9148 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9153 vty_out(vty
, "}\n");
9154 else if (!route_output
)
9155 vty_out(vty
, "%% BGP instance not found\n");
9158 /* Header of detailed BGP route information */
9159 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9160 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9161 afi_t afi
, safi_t safi
, json_object
*json
)
9163 struct bgp_path_info
*pi
;
9166 struct listnode
*node
, *nnode
;
9167 char buf1
[RD_ADDRSTRLEN
];
9168 char buf2
[INET6_ADDRSTRLEN
];
9169 char buf3
[EVPN_ROUTE_STRLEN
];
9170 char prefix_str
[BUFSIZ
];
9175 int route_filter_translated_v4
= 0;
9176 int route_filter_v4
= 0;
9177 int route_filter_translated_v6
= 0;
9178 int route_filter_v6
= 0;
9181 int accept_own_nexthop
= 0;
9184 int no_advertise
= 0;
9188 int has_valid_label
= 0;
9189 mpls_label_t label
= 0;
9190 json_object
*json_adv_to
= NULL
;
9193 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9195 if (has_valid_label
)
9196 label
= label_pton(&rn
->local_label
);
9199 if (has_valid_label
)
9200 json_object_int_add(json
, "localLabel", label
);
9202 json_object_string_add(
9204 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9206 if (safi
== SAFI_EVPN
)
9207 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9208 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9211 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9212 buf3
, sizeof(buf3
)));
9214 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9215 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9216 ? prefix_rd2str(prd
, buf1
,
9219 safi
== SAFI_MPLS_VPN
? ":" : "",
9220 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9224 if (has_valid_label
)
9225 vty_out(vty
, "Local label: %d\n", label
);
9226 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9227 vty_out(vty
, "not allocated\n");
9230 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9232 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9234 if (pi
->extra
&& pi
->extra
->suppress
)
9237 if (pi
->attr
->community
== NULL
)
9240 no_advertise
+= community_include(
9241 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9242 no_export
+= community_include(pi
->attr
->community
,
9243 COMMUNITY_NO_EXPORT
);
9244 local_as
+= community_include(pi
->attr
->community
,
9245 COMMUNITY_LOCAL_AS
);
9246 accept_own
+= community_include(pi
->attr
->community
,
9247 COMMUNITY_ACCEPT_OWN
);
9248 route_filter_translated_v4
+= community_include(
9249 pi
->attr
->community
,
9250 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9251 route_filter_translated_v6
+= community_include(
9252 pi
->attr
->community
,
9253 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9254 route_filter_v4
+= community_include(
9255 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9256 route_filter_v6
+= community_include(
9257 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9258 llgr_stale
+= community_include(pi
->attr
->community
,
9259 COMMUNITY_LLGR_STALE
);
9260 no_llgr
+= community_include(pi
->attr
->community
,
9262 accept_own_nexthop
+=
9263 community_include(pi
->attr
->community
,
9264 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9265 blackhole
+= community_include(pi
->attr
->community
,
9266 COMMUNITY_BLACKHOLE
);
9267 no_peer
+= community_include(pi
->attr
->community
,
9273 vty_out(vty
, "Paths: (%d available", count
);
9275 vty_out(vty
, ", best #%d", best
);
9276 if (safi
== SAFI_UNICAST
)
9277 vty_out(vty
, ", table %s",
9279 == BGP_INSTANCE_TYPE_DEFAULT
)
9283 vty_out(vty
, ", no best path");
9287 ", accept own local route exported and imported in different VRF");
9288 else if (route_filter_translated_v4
)
9290 ", mark translated RTs for VPNv4 route filtering");
9291 else if (route_filter_v4
)
9293 ", attach RT as-is for VPNv4 route filtering");
9294 else if (route_filter_translated_v6
)
9296 ", mark translated RTs for VPNv6 route filtering");
9297 else if (route_filter_v6
)
9299 ", attach RT as-is for VPNv6 route filtering");
9300 else if (llgr_stale
)
9302 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9305 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9306 else if (accept_own_nexthop
)
9308 ", accept local nexthop");
9310 vty_out(vty
, ", inform peer to blackhole prefix");
9312 vty_out(vty
, ", not advertised to EBGP peer");
9313 else if (no_advertise
)
9314 vty_out(vty
, ", not advertised to any peer");
9316 vty_out(vty
, ", not advertised outside local AS");
9319 ", inform EBGP peer not to advertise to their EBGP peers");
9323 ", Advertisements suppressed by an aggregate.");
9324 vty_out(vty
, ")\n");
9327 /* If we are not using addpath then we can display Advertised to and
9329 * show what peers we advertised the bestpath to. If we are using
9331 * though then we must display Advertised to on a path-by-path basis. */
9332 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9333 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9334 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9335 if (json
&& !json_adv_to
)
9336 json_adv_to
= json_object_new_object();
9338 route_vty_out_advertised_to(
9340 " Advertised to non peer-group peers:\n ",
9347 json_object_object_add(json
, "advertisedTo",
9352 vty_out(vty
, " Not advertised to any peer");
9358 /* Display specified route of BGP table. */
9359 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9360 struct bgp_table
*rib
, const char *ip_str
,
9361 afi_t afi
, safi_t safi
,
9362 struct prefix_rd
*prd
, int prefix_check
,
9363 enum bgp_path_type pathtype
, bool use_json
)
9368 struct prefix match
;
9369 struct bgp_node
*rn
;
9370 struct bgp_node
*rm
;
9371 struct bgp_path_info
*pi
;
9372 struct bgp_table
*table
;
9373 json_object
*json
= NULL
;
9374 json_object
*json_paths
= NULL
;
9376 /* Check IP address argument. */
9377 ret
= str2prefix(ip_str
, &match
);
9379 vty_out(vty
, "address is malformed\n");
9383 match
.family
= afi2family(afi
);
9386 json
= json_object_new_object();
9387 json_paths
= json_object_new_array();
9390 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9391 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9392 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9394 table
= bgp_node_get_bgp_table_info(rn
);
9400 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9404 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9405 bgp_unlock_node(rm
);
9409 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9412 route_vty_out_detail_header(
9414 (struct prefix_rd
*)&rn
->p
,
9415 AFI_IP
, safi
, json
);
9420 if (pathtype
== BGP_PATH_SHOW_ALL
9421 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9422 && CHECK_FLAG(pi
->flags
,
9424 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9425 && (CHECK_FLAG(pi
->flags
,
9427 || CHECK_FLAG(pi
->flags
,
9428 BGP_PATH_SELECTED
))))
9429 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9434 bgp_unlock_node(rm
);
9436 } else if (safi
== SAFI_FLOWSPEC
) {
9437 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9438 &match
, prefix_check
,
9445 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9447 || rn
->p
.prefixlen
== match
.prefixlen
) {
9448 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9451 route_vty_out_detail_header(
9452 vty
, bgp
, rn
, NULL
, afi
,
9458 if (pathtype
== BGP_PATH_SHOW_ALL
9460 == BGP_PATH_SHOW_BESTPATH
9465 == BGP_PATH_SHOW_MULTIPATH
9471 BGP_PATH_SELECTED
))))
9472 route_vty_out_detail(
9473 vty
, bgp
, &rn
->p
, pi
,
9474 afi
, safi
, json_paths
);
9478 bgp_unlock_node(rn
);
9484 json_object_object_add(json
, "paths", json_paths
);
9486 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9487 json
, JSON_C_TO_STRING_PRETTY
));
9488 json_object_free(json
);
9491 vty_out(vty
, "%% Network not in table\n");
9499 /* Display specified route of Main RIB */
9500 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9501 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9502 int prefix_check
, enum bgp_path_type pathtype
,
9506 bgp
= bgp_get_default();
9509 vty_out(vty
, "No BGP process is configured\n");
9511 vty_out(vty
, "{}\n");
9516 /* labeled-unicast routes live in the unicast table */
9517 if (safi
== SAFI_LABELED_UNICAST
)
9518 safi
= SAFI_UNICAST
;
9520 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9521 afi
, safi
, prd
, prefix_check
, pathtype
,
9525 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9526 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9529 struct lcommunity
*lcom
;
9535 b
= buffer_new(1024);
9536 for (i
= 0; i
< argc
; i
++) {
9538 buffer_putc(b
, ' ');
9540 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9542 buffer_putstr(b
, argv
[i
]->arg
);
9546 buffer_putc(b
, '\0');
9548 str
= buffer_getstr(b
);
9551 lcom
= lcommunity_str2com(str
);
9552 XFREE(MTYPE_TMP
, str
);
9554 vty_out(vty
, "%% Large-community malformed\n");
9558 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9562 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9563 const char *lcom
, afi_t afi
, safi_t safi
,
9566 struct community_list
*list
;
9568 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9569 LARGE_COMMUNITY_LIST_MASTER
);
9571 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9576 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9580 DEFUN (show_ip_bgp_large_community_list
,
9581 show_ip_bgp_large_community_list_cmd
,
9582 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9586 BGP_INSTANCE_HELP_STR
9588 BGP_SAFI_WITH_LABEL_HELP_STR
9589 "Display routes matching the large-community-list\n"
9590 "large-community-list number\n"
9591 "large-community-list name\n"
9595 afi_t afi
= AFI_IP6
;
9596 safi_t safi
= SAFI_UNICAST
;
9599 if (argv_find(argv
, argc
, "ip", &idx
))
9601 if (argv_find(argv
, argc
, "view", &idx
)
9602 || argv_find(argv
, argc
, "vrf", &idx
))
9603 vrf
= argv
[++idx
]->arg
;
9604 if (argv_find(argv
, argc
, "ipv4", &idx
)
9605 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9606 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9607 if (argv_find(argv
, argc
, "unicast", &idx
)
9608 || argv_find(argv
, argc
, "multicast", &idx
))
9609 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9612 bool uj
= use_json(argc
, argv
);
9614 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9616 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9620 argv_find(argv
, argc
, "large-community-list", &idx
);
9621 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9624 DEFUN (show_ip_bgp_large_community
,
9625 show_ip_bgp_large_community_cmd
,
9626 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9630 BGP_INSTANCE_HELP_STR
9632 BGP_SAFI_WITH_LABEL_HELP_STR
9633 "Display routes matching the large-communities\n"
9634 "List of large-community numbers\n"
9638 afi_t afi
= AFI_IP6
;
9639 safi_t safi
= SAFI_UNICAST
;
9642 if (argv_find(argv
, argc
, "ip", &idx
))
9644 if (argv_find(argv
, argc
, "view", &idx
)
9645 || argv_find(argv
, argc
, "vrf", &idx
))
9646 vrf
= argv
[++idx
]->arg
;
9647 if (argv_find(argv
, argc
, "ipv4", &idx
)
9648 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9649 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9650 if (argv_find(argv
, argc
, "unicast", &idx
)
9651 || argv_find(argv
, argc
, "multicast", &idx
))
9652 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9655 bool uj
= use_json(argc
, argv
);
9657 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9659 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9663 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9664 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9666 return bgp_show(vty
, bgp
, afi
, safi
,
9667 bgp_show_type_lcommunity_all
, NULL
, uj
);
9670 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9674 /* BGP route print out function without JSON */
9677 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9678 <dampening <parameters>\
9683 |community-list <(1-500)|WORD> [exact-match]\
9684 |A.B.C.D/M longer-prefixes\
9685 |X:X::X:X/M longer-prefixes\
9690 BGP_INSTANCE_HELP_STR
9692 BGP_SAFI_WITH_LABEL_HELP_STR
9693 "Display detailed information about dampening\n"
9694 "Display detail of configured dampening parameters\n"
9695 "Display routes matching the route-map\n"
9696 "A route-map to match on\n"
9697 "Display routes conforming to the prefix-list\n"
9698 "Prefix-list name\n"
9699 "Display routes conforming to the filter-list\n"
9700 "Regular expression access list name\n"
9701 "BGP RIB advertisement statistics\n"
9702 "Display routes matching the community-list\n"
9703 "community-list number\n"
9704 "community-list name\n"
9705 "Exact match of the communities\n"
9707 "Display route and more specific routes\n"
9709 "Display route and more specific routes\n")
9711 afi_t afi
= AFI_IP6
;
9712 safi_t safi
= SAFI_UNICAST
;
9713 int exact_match
= 0;
9714 struct bgp
*bgp
= NULL
;
9717 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9722 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9723 if (argv_find(argv
, argc
, "parameters", &idx
))
9724 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9727 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9728 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9729 safi
, bgp_show_type_prefix_list
);
9731 if (argv_find(argv
, argc
, "filter-list", &idx
))
9732 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9733 safi
, bgp_show_type_filter_list
);
9735 if (argv_find(argv
, argc
, "statistics", &idx
))
9736 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9738 if (argv_find(argv
, argc
, "route-map", &idx
))
9739 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9740 safi
, bgp_show_type_route_map
);
9742 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9743 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9744 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9746 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9747 exact_match
, afi
, safi
);
9750 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9751 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9752 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9754 bgp_show_type_prefix_longer
);
9759 /* BGP route print out function with JSON */
9760 DEFUN (show_ip_bgp_json
,
9761 show_ip_bgp_json_cmd
,
9762 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9764 |dampening <flap-statistics|dampened-paths>\
9765 |community [AA:NN|local-AS|no-advertise|no-export\
9766 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9767 |accept-own|accept-own-nexthop|route-filter-v6\
9768 |route-filter-v4|route-filter-translated-v6\
9769 |route-filter-translated-v4] [exact-match]\
9774 BGP_INSTANCE_HELP_STR
9776 BGP_SAFI_WITH_LABEL_HELP_STR
9777 "Display only routes with non-natural netmasks\n"
9778 "Display detailed information about dampening\n"
9779 "Display flap statistics of routes\n"
9780 "Display paths suppressed due to dampening\n"
9781 "Display routes matching the communities\n"
9783 "Do not send outside local AS (well-known community)\n"
9784 "Do not advertise to any peer (well-known community)\n"
9785 "Do not export to next AS (well-known community)\n"
9786 "Graceful shutdown (well-known community)\n"
9787 "Do not export to any peer (well-known community)\n"
9788 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9789 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9790 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9791 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9792 "Should accept VPN route with local nexthop (well-known community)\n"
9793 "RT VPNv6 route filtering (well-known community)\n"
9794 "RT VPNv4 route filtering (well-known community)\n"
9795 "RT translated VPNv6 route filtering (well-known community)\n"
9796 "RT translated VPNv4 route filtering (well-known community)\n"
9797 "Exact match of the communities\n"
9800 afi_t afi
= AFI_IP6
;
9801 safi_t safi
= SAFI_UNICAST
;
9802 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9803 struct bgp
*bgp
= NULL
;
9805 int exact_match
= 0;
9806 bool uj
= use_json(argc
, argv
);
9811 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9816 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9817 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9820 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9821 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9822 return bgp_show(vty
, bgp
, afi
, safi
,
9823 bgp_show_type_dampend_paths
, NULL
, uj
);
9824 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9825 return bgp_show(vty
, bgp
, afi
, safi
,
9826 bgp_show_type_flap_statistics
, NULL
,
9830 if (argv_find(argv
, argc
, "community", &idx
)) {
9831 char *maybecomm
= NULL
;
9832 char *community
= NULL
;
9834 if (idx
+ 1 < argc
) {
9835 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
9836 maybecomm
= argv
[idx
+ 1]->arg
;
9838 maybecomm
= argv
[idx
+ 1]->text
;
9841 if (maybecomm
&& !strmatch(maybecomm
, "json")
9842 && !strmatch(maybecomm
, "exact-match"))
9843 community
= maybecomm
;
9845 if (argv_find(argv
, argc
, "exact-match", &idx
))
9849 return bgp_show_community(vty
, bgp
, community
,
9850 exact_match
, afi
, safi
, uj
);
9852 return (bgp_show(vty
, bgp
, afi
, safi
,
9853 bgp_show_type_community_all
, NULL
,
9857 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9860 DEFUN (show_ip_bgp_route
,
9861 show_ip_bgp_route_cmd
,
9862 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9863 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9867 BGP_INSTANCE_HELP_STR
9869 BGP_SAFI_WITH_LABEL_HELP_STR
9870 "Network in the BGP routing table to display\n"
9872 "Network in the BGP routing table to display\n"
9874 "Display only the bestpath\n"
9875 "Display only multipaths\n"
9878 int prefix_check
= 0;
9880 afi_t afi
= AFI_IP6
;
9881 safi_t safi
= SAFI_UNICAST
;
9882 char *prefix
= NULL
;
9883 struct bgp
*bgp
= NULL
;
9884 enum bgp_path_type path_type
;
9885 bool uj
= use_json(argc
, argv
);
9889 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9896 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9900 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9901 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9902 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9904 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9905 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9908 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9909 && afi
!= AFI_IP6
) {
9911 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9914 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9917 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9921 prefix
= argv
[idx
]->arg
;
9923 /* [<bestpath|multipath>] */
9924 if (argv_find(argv
, argc
, "bestpath", &idx
))
9925 path_type
= BGP_PATH_SHOW_BESTPATH
;
9926 else if (argv_find(argv
, argc
, "multipath", &idx
))
9927 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9929 path_type
= BGP_PATH_SHOW_ALL
;
9931 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9935 DEFUN (show_ip_bgp_regexp
,
9936 show_ip_bgp_regexp_cmd
,
9937 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9941 BGP_INSTANCE_HELP_STR
9943 BGP_SAFI_WITH_LABEL_HELP_STR
9944 "Display routes matching the AS path regular expression\n"
9945 "A regular-expression to match the BGP AS paths\n")
9947 afi_t afi
= AFI_IP6
;
9948 safi_t safi
= SAFI_UNICAST
;
9949 struct bgp
*bgp
= NULL
;
9952 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9957 // get index of regex
9958 argv_find(argv
, argc
, "regexp", &idx
);
9961 char *regstr
= argv_concat(argv
, argc
, idx
);
9962 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9963 bgp_show_type_regexp
);
9964 XFREE(MTYPE_TMP
, regstr
);
9968 DEFUN (show_ip_bgp_instance_all
,
9969 show_ip_bgp_instance_all_cmd
,
9970 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9974 BGP_INSTANCE_ALL_HELP_STR
9976 BGP_SAFI_WITH_LABEL_HELP_STR
9980 safi_t safi
= SAFI_UNICAST
;
9981 struct bgp
*bgp
= NULL
;
9983 bool uj
= use_json(argc
, argv
);
9988 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9993 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9997 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9998 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10003 regex
= bgp_regcomp(regstr
);
10005 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10006 return CMD_WARNING
;
10009 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10010 bgp_regex_free(regex
);
10014 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10015 const char *prefix_list_str
, afi_t afi
,
10016 safi_t safi
, enum bgp_show_type type
)
10018 struct prefix_list
*plist
;
10020 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10021 if (plist
== NULL
) {
10022 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10024 return CMD_WARNING
;
10027 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10030 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10031 const char *filter
, afi_t afi
, safi_t safi
,
10032 enum bgp_show_type type
)
10034 struct as_list
*as_list
;
10036 as_list
= as_list_lookup(filter
);
10037 if (as_list
== NULL
) {
10038 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10040 return CMD_WARNING
;
10043 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10046 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10047 const char *rmap_str
, afi_t afi
, safi_t safi
,
10048 enum bgp_show_type type
)
10050 struct route_map
*rmap
;
10052 rmap
= route_map_lookup_by_name(rmap_str
);
10054 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10055 return CMD_WARNING
;
10058 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10061 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10062 const char *comstr
, int exact
, afi_t afi
,
10063 safi_t safi
, bool use_json
)
10065 struct community
*com
;
10068 com
= community_str2com(comstr
);
10070 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10071 return CMD_WARNING
;
10074 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10075 (exact
? bgp_show_type_community_exact
10076 : bgp_show_type_community
),
10078 community_free(&com
);
10083 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10084 const char *com
, int exact
, afi_t afi
,
10087 struct community_list
*list
;
10089 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10090 if (list
== NULL
) {
10091 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10092 return CMD_WARNING
;
10095 return bgp_show(vty
, bgp
, afi
, safi
,
10096 (exact
? bgp_show_type_community_list_exact
10097 : bgp_show_type_community_list
),
10101 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10102 const char *prefix
, afi_t afi
, safi_t safi
,
10103 enum bgp_show_type type
)
10110 ret
= str2prefix(prefix
, p
);
10112 vty_out(vty
, "%% Malformed Prefix\n");
10113 return CMD_WARNING
;
10116 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10121 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
10122 const char *ip_str
, bool use_json
)
10126 union sockunion su
;
10128 /* Get peer sockunion. */
10129 ret
= str2sockunion(ip_str
, &su
);
10131 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
10133 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
10137 json_object
*json_no
= NULL
;
10138 json_no
= json_object_new_object();
10139 json_object_string_add(
10141 "malformedAddressOrName",
10143 vty_out(vty
, "%s\n",
10144 json_object_to_json_string_ext(
10146 JSON_C_TO_STRING_PRETTY
));
10147 json_object_free(json_no
);
10150 "%% Malformed address or name: %s\n",
10158 /* Peer structure lookup. */
10159 peer
= peer_lookup(bgp
, &su
);
10162 json_object
*json_no
= NULL
;
10163 json_no
= json_object_new_object();
10164 json_object_string_add(json_no
, "warning",
10165 "No such neighbor in this view/vrf");
10166 vty_out(vty
, "%s\n",
10167 json_object_to_json_string_ext(
10168 json_no
, JSON_C_TO_STRING_PRETTY
));
10169 json_object_free(json_no
);
10171 vty_out(vty
, "No such neighbor in this view/vrf\n");
10179 BGP_STATS_MAXBITLEN
= 0,
10181 BGP_STATS_PREFIXES
,
10183 BGP_STATS_UNAGGREGATEABLE
,
10184 BGP_STATS_MAX_AGGREGATEABLE
,
10185 BGP_STATS_AGGREGATES
,
10187 BGP_STATS_ASPATH_COUNT
,
10188 BGP_STATS_ASPATH_MAXHOPS
,
10189 BGP_STATS_ASPATH_TOTHOPS
,
10190 BGP_STATS_ASPATH_MAXSIZE
,
10191 BGP_STATS_ASPATH_TOTSIZE
,
10192 BGP_STATS_ASN_HIGHEST
,
10196 static const char *table_stats_strs
[] = {
10197 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10198 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10199 [BGP_STATS_RIB
] = "Total Advertisements",
10200 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10201 [BGP_STATS_MAX_AGGREGATEABLE
] =
10202 "Maximum aggregateable prefixes",
10203 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10204 [BGP_STATS_SPACE
] = "Address space advertised",
10205 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10206 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10207 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10208 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10209 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10210 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10211 [BGP_STATS_MAX
] = NULL
,
10214 struct bgp_table_stats
{
10215 struct bgp_table
*table
;
10216 unsigned long long counts
[BGP_STATS_MAX
];
10217 double total_space
;
10221 #define TALLY_SIGFIG 100000
10222 static unsigned long
10223 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10225 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10226 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10227 unsigned long ret
= newtot
/ count
;
10229 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10236 static int bgp_table_stats_walker(struct thread
*t
)
10238 struct bgp_node
*rn
;
10239 struct bgp_node
*top
;
10240 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10241 unsigned int space
= 0;
10243 if (!(top
= bgp_table_top(ts
->table
)))
10246 switch (top
->p
.family
) {
10248 space
= IPV4_MAX_BITLEN
;
10251 space
= IPV6_MAX_BITLEN
;
10255 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10257 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10258 struct bgp_path_info
*pi
;
10259 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10260 unsigned int pinum
= 0;
10265 if (!bgp_node_has_bgp_path_info_data(rn
))
10268 ts
->counts
[BGP_STATS_PREFIXES
]++;
10269 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10272 ts
->counts
[BGP_STATS_AVGPLEN
]
10273 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10274 ts
->counts
[BGP_STATS_AVGPLEN
],
10278 /* check if the prefix is included by any other announcements */
10279 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10280 prn
= bgp_node_parent_nolock(prn
);
10282 if (prn
== NULL
|| prn
== top
) {
10283 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10284 /* announced address space */
10287 pow(2.0, space
- rn
->p
.prefixlen
);
10288 } else if (bgp_node_has_bgp_path_info_data(prn
))
10289 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10291 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10293 ts
->counts
[BGP_STATS_RIB
]++;
10296 && (CHECK_FLAG(pi
->attr
->flag
,
10298 BGP_ATTR_ATOMIC_AGGREGATE
))))
10299 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10301 /* as-path stats */
10302 if (pi
->attr
&& pi
->attr
->aspath
) {
10303 unsigned int hops
=
10304 aspath_count_hops(pi
->attr
->aspath
);
10305 unsigned int size
=
10306 aspath_size(pi
->attr
->aspath
);
10307 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10309 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10311 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10312 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
10315 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10316 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
10319 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10320 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10322 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10323 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10324 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10326 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10327 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10328 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10331 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10332 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
10340 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10343 struct bgp_table_stats ts
;
10346 if (!bgp
->rib
[afi
][safi
]) {
10347 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10349 return CMD_WARNING
;
10352 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10354 /* labeled-unicast routes live in the unicast table */
10355 if (safi
== SAFI_LABELED_UNICAST
)
10356 safi
= SAFI_UNICAST
;
10358 memset(&ts
, 0, sizeof(ts
));
10359 ts
.table
= bgp
->rib
[afi
][safi
];
10360 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10362 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10363 if (!table_stats_strs
[i
])
10368 case BGP_STATS_ASPATH_AVGHOPS
:
10369 case BGP_STATS_ASPATH_AVGSIZE
:
10370 case BGP_STATS_AVGPLEN
:
10371 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10372 vty_out (vty
, "%12.2f",
10373 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10376 case BGP_STATS_ASPATH_TOTHOPS
:
10377 case BGP_STATS_ASPATH_TOTSIZE
:
10378 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10379 vty_out(vty
, "%12.2f",
10381 ? (float)ts
.counts
[i
]
10383 [BGP_STATS_ASPATH_COUNT
]
10386 case BGP_STATS_TOTPLEN
:
10387 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10388 vty_out(vty
, "%12.2f",
10390 ? (float)ts
.counts
[i
]
10392 [BGP_STATS_PREFIXES
]
10395 case BGP_STATS_SPACE
:
10396 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10397 vty_out(vty
, "%12g\n", ts
.total_space
);
10399 if (afi
== AFI_IP6
) {
10400 vty_out(vty
, "%30s: ", "/32 equivalent ");
10401 vty_out(vty
, "%12g\n",
10402 ts
.total_space
* pow(2.0, -128 + 32));
10403 vty_out(vty
, "%30s: ", "/48 equivalent ");
10404 vty_out(vty
, "%12g\n",
10405 ts
.total_space
* pow(2.0, -128 + 48));
10407 vty_out(vty
, "%30s: ", "% announced ");
10408 vty_out(vty
, "%12.2f\n",
10409 ts
.total_space
* 100. * pow(2.0, -32));
10410 vty_out(vty
, "%30s: ", "/8 equivalent ");
10411 vty_out(vty
, "%12.2f\n",
10412 ts
.total_space
* pow(2.0, -32 + 8));
10413 vty_out(vty
, "%30s: ", "/24 equivalent ");
10414 vty_out(vty
, "%12.2f\n",
10415 ts
.total_space
* pow(2.0, -32 + 24));
10419 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10420 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10423 vty_out(vty
, "\n");
10425 return CMD_SUCCESS
;
10437 PCOUNT_PFCNT
, /* the figure we display to users */
10441 static const char *pcount_strs
[] = {
10442 [PCOUNT_ADJ_IN
] = "Adj-in",
10443 [PCOUNT_DAMPED
] = "Damped",
10444 [PCOUNT_REMOVED
] = "Removed",
10445 [PCOUNT_HISTORY
] = "History",
10446 [PCOUNT_STALE
] = "Stale",
10447 [PCOUNT_VALID
] = "Valid",
10448 [PCOUNT_ALL
] = "All RIB",
10449 [PCOUNT_COUNTED
] = "PfxCt counted",
10450 [PCOUNT_PFCNT
] = "Useable",
10451 [PCOUNT_MAX
] = NULL
,
10454 struct peer_pcounts
{
10455 unsigned int count
[PCOUNT_MAX
];
10456 const struct peer
*peer
;
10457 const struct bgp_table
*table
;
10460 static int bgp_peer_count_walker(struct thread
*t
)
10462 struct bgp_node
*rn
;
10463 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10464 const struct peer
*peer
= pc
->peer
;
10466 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10467 struct bgp_adj_in
*ain
;
10468 struct bgp_path_info
*pi
;
10470 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10471 if (ain
->peer
== peer
)
10472 pc
->count
[PCOUNT_ADJ_IN
]++;
10474 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10476 if (pi
->peer
!= peer
)
10479 pc
->count
[PCOUNT_ALL
]++;
10481 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10482 pc
->count
[PCOUNT_DAMPED
]++;
10483 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10484 pc
->count
[PCOUNT_HISTORY
]++;
10485 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10486 pc
->count
[PCOUNT_REMOVED
]++;
10487 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10488 pc
->count
[PCOUNT_STALE
]++;
10489 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10490 pc
->count
[PCOUNT_VALID
]++;
10491 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10492 pc
->count
[PCOUNT_PFCNT
]++;
10494 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10495 pc
->count
[PCOUNT_COUNTED
]++;
10496 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10498 EC_LIB_DEVELOPMENT
,
10499 "Attempting to count but flags say it is unusable");
10501 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10503 EC_LIB_DEVELOPMENT
,
10504 "Not counted but flags say we should");
10511 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10512 safi_t safi
, bool use_json
)
10514 struct peer_pcounts pcounts
= {.peer
= peer
};
10516 json_object
*json
= NULL
;
10517 json_object
*json_loop
= NULL
;
10520 json
= json_object_new_object();
10521 json_loop
= json_object_new_object();
10524 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10525 || !peer
->bgp
->rib
[afi
][safi
]) {
10527 json_object_string_add(
10529 "No such neighbor or address family");
10530 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10531 json_object_free(json
);
10533 vty_out(vty
, "%% No such neighbor or address family\n");
10535 return CMD_WARNING
;
10538 memset(&pcounts
, 0, sizeof(pcounts
));
10539 pcounts
.peer
= peer
;
10540 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10542 /* in-place call via thread subsystem so as to record execution time
10543 * stats for the thread-walk (i.e. ensure this can't be blamed on
10544 * on just vty_read()).
10546 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10549 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10550 json_object_string_add(json
, "multiProtocol",
10551 afi_safi_print(afi
, safi
));
10552 json_object_int_add(json
, "pfxCounter",
10553 peer
->pcount
[afi
][safi
]);
10555 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10556 json_object_int_add(json_loop
, pcount_strs
[i
],
10559 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10561 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10562 json_object_string_add(json
, "pfxctDriftFor",
10564 json_object_string_add(
10565 json
, "recommended",
10566 "Please report this bug, with the above command output");
10568 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10569 json
, JSON_C_TO_STRING_PRETTY
));
10570 json_object_free(json
);
10574 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10575 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10576 peer
->hostname
, peer
->host
,
10577 afi_safi_print(afi
, safi
));
10579 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10580 afi_safi_print(afi
, safi
));
10583 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10584 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10586 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10587 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10590 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10591 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10593 "Please report this bug, with the above command output\n");
10597 return CMD_SUCCESS
;
10600 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10601 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10602 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10603 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10607 BGP_INSTANCE_HELP_STR
10610 "Detailed information on TCP and BGP neighbor connections\n"
10611 "Neighbor to display information about\n"
10612 "Neighbor to display information about\n"
10613 "Neighbor on BGP configured interface\n"
10614 "Display detailed prefix count information\n"
10617 afi_t afi
= AFI_IP6
;
10618 safi_t safi
= SAFI_UNICAST
;
10621 struct bgp
*bgp
= NULL
;
10622 bool uj
= use_json(argc
, argv
);
10627 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10630 return CMD_WARNING
;
10632 argv_find(argv
, argc
, "neighbors", &idx
);
10633 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10635 return CMD_WARNING
;
10637 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10640 #ifdef KEEP_OLD_VPN_COMMANDS
10641 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10642 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10643 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10648 "Display information about all VPNv4 NLRIs\n"
10649 "Detailed information on TCP and BGP neighbor connections\n"
10650 "Neighbor to display information about\n"
10651 "Neighbor to display information about\n"
10652 "Neighbor on BGP configured interface\n"
10653 "Display detailed prefix count information\n"
10658 bool uj
= use_json(argc
, argv
);
10660 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10662 return CMD_WARNING
;
10664 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10667 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10668 show_ip_bgp_vpn_all_route_prefix_cmd
,
10669 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10674 "Display information about all VPNv4 NLRIs\n"
10675 "Network in the BGP routing table to display\n"
10676 "Network in the BGP routing table to display\n"
10680 char *network
= NULL
;
10681 struct bgp
*bgp
= bgp_get_default();
10683 vty_out(vty
, "Can't find default instance\n");
10684 return CMD_WARNING
;
10687 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10688 network
= argv
[idx
]->arg
;
10689 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10690 network
= argv
[idx
]->arg
;
10692 vty_out(vty
, "Unable to figure out Network\n");
10693 return CMD_WARNING
;
10696 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10697 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10699 #endif /* KEEP_OLD_VPN_COMMANDS */
10701 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10702 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10703 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10709 "Display information about all EVPN NLRIs\n"
10710 "Network in the BGP routing table to display\n"
10711 "Network in the BGP routing table to display\n"
10715 char *network
= NULL
;
10717 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10718 network
= argv
[idx
]->arg
;
10719 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10720 network
= argv
[idx
]->arg
;
10722 vty_out(vty
, "Unable to figure out Network\n");
10723 return CMD_WARNING
;
10725 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10726 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10729 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10730 safi_t safi
, enum bgp_show_adj_route_type type
,
10731 const char *rmap_name
, bool use_json
,
10734 struct bgp_table
*table
;
10735 struct bgp_adj_in
*ain
;
10736 struct bgp_adj_out
*adj
;
10737 unsigned long output_count
;
10738 unsigned long filtered_count
;
10739 struct bgp_node
*rn
;
10745 struct update_subgroup
*subgrp
;
10746 json_object
*json_scode
= NULL
;
10747 json_object
*json_ocode
= NULL
;
10748 json_object
*json_ar
= NULL
;
10749 struct peer_af
*paf
;
10750 bool route_filtered
;
10753 json_scode
= json_object_new_object();
10754 json_ocode
= json_object_new_object();
10755 json_ar
= json_object_new_object();
10757 json_object_string_add(json_scode
, "suppressed", "s");
10758 json_object_string_add(json_scode
, "damped", "d");
10759 json_object_string_add(json_scode
, "history", "h");
10760 json_object_string_add(json_scode
, "valid", "*");
10761 json_object_string_add(json_scode
, "best", ">");
10762 json_object_string_add(json_scode
, "multipath", "=");
10763 json_object_string_add(json_scode
, "internal", "i");
10764 json_object_string_add(json_scode
, "ribFailure", "r");
10765 json_object_string_add(json_scode
, "stale", "S");
10766 json_object_string_add(json_scode
, "removed", "R");
10768 json_object_string_add(json_ocode
, "igp", "i");
10769 json_object_string_add(json_ocode
, "egp", "e");
10770 json_object_string_add(json_ocode
, "incomplete", "?");
10777 json_object_string_add(json
, "alert", "no BGP");
10778 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10779 json_object_free(json
);
10781 vty_out(vty
, "%% No bgp\n");
10785 table
= bgp
->rib
[afi
][safi
];
10787 output_count
= filtered_count
= 0;
10788 subgrp
= peer_subgroup(peer
, afi
, safi
);
10790 if (type
== bgp_show_adj_route_advertised
&& subgrp
10791 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10793 json_object_int_add(json
, "bgpTableVersion",
10795 json_object_string_add(json
, "bgpLocalRouterId",
10796 inet_ntoa(bgp
->router_id
));
10797 json_object_int_add(json
, "defaultLocPrf",
10798 bgp
->default_local_pref
);
10799 json_object_int_add(json
, "localAS", bgp
->as
);
10800 json_object_object_add(json
, "bgpStatusCodes",
10802 json_object_object_add(json
, "bgpOriginCodes",
10804 json_object_string_add(
10805 json
, "bgpOriginatingDefaultNetwork",
10806 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10808 vty_out(vty
, "BGP table version is %" PRIu64
10809 ", local router ID is %s, vrf id ",
10810 table
->version
, inet_ntoa(bgp
->router_id
));
10811 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10812 vty_out(vty
, "%s", VRFID_NONE_STR
);
10814 vty_out(vty
, "%u", bgp
->vrf_id
);
10815 vty_out(vty
, "\n");
10816 vty_out(vty
, "Default local pref %u, ",
10817 bgp
->default_local_pref
);
10818 vty_out(vty
, "local AS %u\n", bgp
->as
);
10819 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10820 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10821 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10823 vty_out(vty
, "Originating default network %s\n\n",
10824 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10829 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10830 if (type
== bgp_show_adj_route_received
10831 || type
== bgp_show_adj_route_filtered
) {
10832 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10833 if (ain
->peer
!= peer
|| !ain
->attr
)
10838 json_object_int_add(
10839 json
, "bgpTableVersion",
10841 json_object_string_add(
10843 "bgpLocalRouterId",
10846 json_object_int_add(json
,
10848 bgp
->default_local_pref
);
10849 json_object_int_add(json
,
10850 "localAS", bgp
->as
);
10851 json_object_object_add(
10852 json
, "bgpStatusCodes",
10854 json_object_object_add(
10855 json
, "bgpOriginCodes",
10859 "BGP table version is 0, local router ID is %s, vrf id ",
10862 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10868 vty_out(vty
, "\n");
10870 "Default local pref %u, ",
10871 bgp
->default_local_pref
);
10872 vty_out(vty
, "local AS %u\n",
10875 BGP_SHOW_SCODE_HEADER
);
10877 BGP_SHOW_NCODE_HEADER
);
10879 BGP_SHOW_OCODE_HEADER
);
10885 vty_out(vty
, BGP_SHOW_HEADER
);
10889 bgp_attr_dup(&attr
, ain
->attr
);
10890 route_filtered
= false;
10892 /* Filter prefix using distribute list,
10893 * filter list or prefix list
10895 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10896 safi
)) == FILTER_DENY
)
10897 route_filtered
= true;
10899 /* Filter prefix using route-map */
10900 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10901 afi
, safi
, rmap_name
);
10903 if (type
== bgp_show_adj_route_filtered
&&
10904 !route_filtered
&& ret
!= RMAP_DENY
) {
10905 bgp_attr_undup(&attr
, ain
->attr
);
10909 if (type
== bgp_show_adj_route_received
&&
10910 (route_filtered
|| ret
== RMAP_DENY
))
10913 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10914 use_json
, json_ar
);
10915 bgp_attr_undup(&attr
, ain
->attr
);
10918 } else if (type
== bgp_show_adj_route_advertised
) {
10919 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
10920 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10921 if (paf
->peer
!= peer
|| !adj
->attr
)
10926 json_object_int_add(
10930 json_object_string_add(
10932 "bgpLocalRouterId",
10935 json_object_int_add(
10936 json
, "defaultLocPrf",
10937 bgp
->default_local_pref
10939 json_object_int_add(
10942 json_object_object_add(
10946 json_object_object_add(
10952 "BGP table version is %" PRIu64
10953 ", local router ID is %s, vrf id ",
10966 vty_out(vty
, "\n");
10968 "Default local pref %u, ",
10969 bgp
->default_local_pref
10975 BGP_SHOW_SCODE_HEADER
);
10977 BGP_SHOW_NCODE_HEADER
);
10979 BGP_SHOW_OCODE_HEADER
);
10990 bgp_attr_dup(&attr
, adj
->attr
);
10991 ret
= bgp_output_modifier(
10992 peer
, &rn
->p
, &attr
, afi
, safi
,
10995 if (ret
!= RMAP_DENY
) {
10996 route_vty_out_tmp(vty
, &rn
->p
,
11005 bgp_attr_undup(&attr
, adj
->attr
);
11011 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11012 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11013 json_object_int_add(json
, "filteredPrefixCounter",
11016 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11017 json
, JSON_C_TO_STRING_PRETTY
));
11018 json_object_free(json
);
11019 } else if (output_count
> 0) {
11020 if (filtered_count
> 0)
11022 "\nTotal number of prefixes %ld (%ld filtered)\n",
11023 output_count
, filtered_count
);
11025 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11030 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11031 safi_t safi
, enum bgp_show_adj_route_type type
,
11032 const char *rmap_name
, bool use_json
)
11034 json_object
*json
= NULL
;
11037 json
= json_object_new_object();
11039 /* labeled-unicast routes live in the unicast table */
11040 if (safi
== SAFI_LABELED_UNICAST
)
11041 safi
= SAFI_UNICAST
;
11043 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11045 json_object_string_add(
11047 "No such neighbor or address family");
11048 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11049 json_object_free(json
);
11051 vty_out(vty
, "%% No such neighbor or address family\n");
11053 return CMD_WARNING
;
11056 if ((type
== bgp_show_adj_route_received
11057 || type
== bgp_show_adj_route_filtered
)
11058 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11059 PEER_FLAG_SOFT_RECONFIG
)) {
11061 json_object_string_add(
11063 "Inbound soft reconfiguration not enabled");
11064 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11065 json_object_free(json
);
11068 "%% Inbound soft reconfiguration not enabled\n");
11070 return CMD_WARNING
;
11073 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11075 return CMD_SUCCESS
;
11078 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11079 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11080 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11081 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11085 BGP_INSTANCE_HELP_STR
11087 BGP_SAFI_WITH_LABEL_HELP_STR
11088 "Detailed information on TCP and BGP neighbor connections\n"
11089 "Neighbor to display information about\n"
11090 "Neighbor to display information about\n"
11091 "Neighbor on BGP configured interface\n"
11092 "Display the routes advertised to a BGP neighbor\n"
11093 "Display the received routes from neighbor\n"
11094 "Display the filtered routes received from neighbor\n"
11095 "Route-map to modify the attributes\n"
11096 "Name of the route map\n"
11099 afi_t afi
= AFI_IP6
;
11100 safi_t safi
= SAFI_UNICAST
;
11101 char *rmap_name
= NULL
;
11102 char *peerstr
= NULL
;
11103 struct bgp
*bgp
= NULL
;
11105 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11107 bool uj
= use_json(argc
, argv
);
11112 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11115 return CMD_WARNING
;
11117 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11118 argv_find(argv
, argc
, "neighbors", &idx
);
11119 peerstr
= argv
[++idx
]->arg
;
11121 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11123 return CMD_WARNING
;
11125 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11126 type
= bgp_show_adj_route_advertised
;
11127 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11128 type
= bgp_show_adj_route_received
;
11129 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11130 type
= bgp_show_adj_route_filtered
;
11132 if (argv_find(argv
, argc
, "route-map", &idx
))
11133 rmap_name
= argv
[++idx
]->arg
;
11135 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11138 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11139 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11140 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11146 "Address Family modifier\n"
11147 "Detailed information on TCP and BGP neighbor connections\n"
11148 "Neighbor to display information about\n"
11149 "Neighbor to display information about\n"
11150 "Neighbor on BGP configured interface\n"
11151 "Display information received from a BGP neighbor\n"
11152 "Display the prefixlist filter\n"
11155 afi_t afi
= AFI_IP6
;
11156 safi_t safi
= SAFI_UNICAST
;
11157 char *peerstr
= NULL
;
11160 union sockunion su
;
11166 /* show [ip] bgp */
11167 if (argv_find(argv
, argc
, "ip", &idx
))
11169 /* [<ipv4|ipv6> [unicast]] */
11170 if (argv_find(argv
, argc
, "ipv4", &idx
))
11172 if (argv_find(argv
, argc
, "ipv6", &idx
))
11174 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11175 argv_find(argv
, argc
, "neighbors", &idx
);
11176 peerstr
= argv
[++idx
]->arg
;
11178 bool uj
= use_json(argc
, argv
);
11180 ret
= str2sockunion(peerstr
, &su
);
11182 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11185 vty_out(vty
, "{}\n");
11188 "%% Malformed address or name: %s\n",
11190 return CMD_WARNING
;
11193 peer
= peer_lookup(NULL
, &su
);
11196 vty_out(vty
, "{}\n");
11198 vty_out(vty
, "No peer\n");
11199 return CMD_WARNING
;
11203 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11204 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11207 vty_out(vty
, "Address Family: %s\n",
11208 afi_safi_print(afi
, safi
));
11209 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11212 vty_out(vty
, "{}\n");
11214 vty_out(vty
, "No functional output\n");
11217 return CMD_SUCCESS
;
11220 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11221 afi_t afi
, safi_t safi
,
11222 enum bgp_show_type type
, bool use_json
)
11224 /* labeled-unicast routes live in the unicast table */
11225 if (safi
== SAFI_LABELED_UNICAST
)
11226 safi
= SAFI_UNICAST
;
11228 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11230 json_object
*json_no
= NULL
;
11231 json_no
= json_object_new_object();
11232 json_object_string_add(
11233 json_no
, "warning",
11234 "No such neighbor or address family");
11235 vty_out(vty
, "%s\n",
11236 json_object_to_json_string(json_no
));
11237 json_object_free(json_no
);
11239 vty_out(vty
, "%% No such neighbor or address family\n");
11240 return CMD_WARNING
;
11243 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11246 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11247 show_ip_bgp_flowspec_routes_detailed_cmd
,
11248 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11252 BGP_INSTANCE_HELP_STR
11255 "Detailed information on flowspec entries\n"
11258 afi_t afi
= AFI_IP
;
11259 safi_t safi
= SAFI_UNICAST
;
11260 struct bgp
*bgp
= NULL
;
11262 bool uj
= use_json(argc
, argv
);
11267 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11270 return CMD_WARNING
;
11272 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11275 DEFUN (show_ip_bgp_neighbor_routes
,
11276 show_ip_bgp_neighbor_routes_cmd
,
11277 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11278 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11282 BGP_INSTANCE_HELP_STR
11284 BGP_SAFI_WITH_LABEL_HELP_STR
11285 "Detailed information on TCP and BGP neighbor connections\n"
11286 "Neighbor to display information about\n"
11287 "Neighbor to display information about\n"
11288 "Neighbor on BGP configured interface\n"
11289 "Display flap statistics of the routes learned from neighbor\n"
11290 "Display the dampened routes received from neighbor\n"
11291 "Display routes learned from neighbor\n"
11294 char *peerstr
= NULL
;
11295 struct bgp
*bgp
= NULL
;
11296 afi_t afi
= AFI_IP6
;
11297 safi_t safi
= SAFI_UNICAST
;
11299 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11301 bool uj
= use_json(argc
, argv
);
11306 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11309 return CMD_WARNING
;
11311 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11312 argv_find(argv
, argc
, "neighbors", &idx
);
11313 peerstr
= argv
[++idx
]->arg
;
11315 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11317 return CMD_WARNING
;
11319 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11320 sh_type
= bgp_show_type_flap_neighbor
;
11321 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11322 sh_type
= bgp_show_type_damp_neighbor
;
11323 else if (argv_find(argv
, argc
, "routes", &idx
))
11324 sh_type
= bgp_show_type_neighbor
;
11326 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11329 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11331 struct bgp_distance
{
11332 /* Distance value for the IP source prefix. */
11335 /* Name of the access-list to be matched. */
11339 DEFUN (show_bgp_afi_vpn_rd_route
,
11340 show_bgp_afi_vpn_rd_route_cmd
,
11341 "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]",
11345 "Address Family modifier\n"
11346 "Display information for a route distinguisher\n"
11347 "Route Distinguisher\n"
11348 "Network in the BGP routing table to display\n"
11349 "Network in the BGP routing table to display\n"
11353 struct prefix_rd prd
;
11354 afi_t afi
= AFI_MAX
;
11357 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11358 vty_out(vty
, "%% Malformed Address Family\n");
11359 return CMD_WARNING
;
11362 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11364 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11365 return CMD_WARNING
;
11368 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11369 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11372 static struct bgp_distance
*bgp_distance_new(void)
11374 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11377 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11379 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11382 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11383 const char *ip_str
, const char *access_list_str
)
11390 struct bgp_node
*rn
;
11391 struct bgp_distance
*bdistance
;
11393 afi
= bgp_node_afi(vty
);
11394 safi
= bgp_node_safi(vty
);
11396 ret
= str2prefix(ip_str
, &p
);
11398 vty_out(vty
, "Malformed prefix\n");
11399 return CMD_WARNING_CONFIG_FAILED
;
11402 distance
= atoi(distance_str
);
11404 /* Get BGP distance node. */
11405 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11406 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11408 bgp_unlock_node(rn
);
11410 bdistance
= bgp_distance_new();
11411 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11414 /* Set distance value. */
11415 bdistance
->distance
= distance
;
11417 /* Reset access-list configuration. */
11418 if (bdistance
->access_list
) {
11419 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11420 bdistance
->access_list
= NULL
;
11422 if (access_list_str
)
11423 bdistance
->access_list
=
11424 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11426 return CMD_SUCCESS
;
11429 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11430 const char *ip_str
, const char *access_list_str
)
11437 struct bgp_node
*rn
;
11438 struct bgp_distance
*bdistance
;
11440 afi
= bgp_node_afi(vty
);
11441 safi
= bgp_node_safi(vty
);
11443 ret
= str2prefix(ip_str
, &p
);
11445 vty_out(vty
, "Malformed prefix\n");
11446 return CMD_WARNING_CONFIG_FAILED
;
11449 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11450 (struct prefix
*)&p
);
11452 vty_out(vty
, "Can't find specified prefix\n");
11453 return CMD_WARNING_CONFIG_FAILED
;
11456 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11457 distance
= atoi(distance_str
);
11459 if (bdistance
->distance
!= distance
) {
11460 vty_out(vty
, "Distance does not match configured\n");
11461 return CMD_WARNING_CONFIG_FAILED
;
11464 if (bdistance
->access_list
)
11465 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11466 bgp_distance_free(bdistance
);
11468 bgp_node_set_bgp_path_info(rn
, NULL
);
11469 bgp_unlock_node(rn
);
11470 bgp_unlock_node(rn
);
11472 return CMD_SUCCESS
;
11475 /* Apply BGP information to distance method. */
11476 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11477 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11479 struct bgp_node
*rn
;
11482 struct bgp_distance
*bdistance
;
11483 struct access_list
*alist
;
11484 struct bgp_static
*bgp_static
;
11489 peer
= pinfo
->peer
;
11491 /* Check source address. */
11492 sockunion2hostprefix(&peer
->su
, &q
);
11493 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11495 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11496 bgp_unlock_node(rn
);
11498 if (bdistance
->access_list
) {
11499 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11501 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11502 return bdistance
->distance
;
11504 return bdistance
->distance
;
11507 /* Backdoor check. */
11508 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11510 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11511 bgp_unlock_node(rn
);
11513 if (bgp_static
->backdoor
) {
11514 if (bgp
->distance_local
[afi
][safi
])
11515 return bgp
->distance_local
[afi
][safi
];
11517 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11521 if (peer
->sort
== BGP_PEER_EBGP
) {
11522 if (bgp
->distance_ebgp
[afi
][safi
])
11523 return bgp
->distance_ebgp
[afi
][safi
];
11524 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11526 if (bgp
->distance_ibgp
[afi
][safi
])
11527 return bgp
->distance_ibgp
[afi
][safi
];
11528 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11532 DEFUN (bgp_distance
,
11534 "distance bgp (1-255) (1-255) (1-255)",
11535 "Define an administrative distance\n"
11537 "Distance for routes external to the AS\n"
11538 "Distance for routes internal to the AS\n"
11539 "Distance for local routes\n")
11541 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11542 int idx_number
= 2;
11543 int idx_number_2
= 3;
11544 int idx_number_3
= 4;
11548 afi
= bgp_node_afi(vty
);
11549 safi
= bgp_node_safi(vty
);
11551 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11552 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11553 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11554 return CMD_SUCCESS
;
11557 DEFUN (no_bgp_distance
,
11558 no_bgp_distance_cmd
,
11559 "no distance bgp [(1-255) (1-255) (1-255)]",
11561 "Define an administrative distance\n"
11563 "Distance for routes external to the AS\n"
11564 "Distance for routes internal to the AS\n"
11565 "Distance for local routes\n")
11567 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11571 afi
= bgp_node_afi(vty
);
11572 safi
= bgp_node_safi(vty
);
11574 bgp
->distance_ebgp
[afi
][safi
] = 0;
11575 bgp
->distance_ibgp
[afi
][safi
] = 0;
11576 bgp
->distance_local
[afi
][safi
] = 0;
11577 return CMD_SUCCESS
;
11581 DEFUN (bgp_distance_source
,
11582 bgp_distance_source_cmd
,
11583 "distance (1-255) A.B.C.D/M",
11584 "Define an administrative distance\n"
11585 "Administrative distance\n"
11586 "IP source prefix\n")
11588 int idx_number
= 1;
11589 int idx_ipv4_prefixlen
= 2;
11590 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11591 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11592 return CMD_SUCCESS
;
11595 DEFUN (no_bgp_distance_source
,
11596 no_bgp_distance_source_cmd
,
11597 "no distance (1-255) A.B.C.D/M",
11599 "Define an administrative distance\n"
11600 "Administrative distance\n"
11601 "IP source prefix\n")
11603 int idx_number
= 2;
11604 int idx_ipv4_prefixlen
= 3;
11605 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11606 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11607 return CMD_SUCCESS
;
11610 DEFUN (bgp_distance_source_access_list
,
11611 bgp_distance_source_access_list_cmd
,
11612 "distance (1-255) A.B.C.D/M WORD",
11613 "Define an administrative distance\n"
11614 "Administrative distance\n"
11615 "IP source prefix\n"
11616 "Access list name\n")
11618 int idx_number
= 1;
11619 int idx_ipv4_prefixlen
= 2;
11621 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11622 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11623 return CMD_SUCCESS
;
11626 DEFUN (no_bgp_distance_source_access_list
,
11627 no_bgp_distance_source_access_list_cmd
,
11628 "no distance (1-255) A.B.C.D/M WORD",
11630 "Define an administrative distance\n"
11631 "Administrative distance\n"
11632 "IP source prefix\n"
11633 "Access list name\n")
11635 int idx_number
= 2;
11636 int idx_ipv4_prefixlen
= 3;
11638 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11639 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11640 return CMD_SUCCESS
;
11643 DEFUN (ipv6_bgp_distance_source
,
11644 ipv6_bgp_distance_source_cmd
,
11645 "distance (1-255) X:X::X:X/M",
11646 "Define an administrative distance\n"
11647 "Administrative distance\n"
11648 "IP source prefix\n")
11650 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11651 return CMD_SUCCESS
;
11654 DEFUN (no_ipv6_bgp_distance_source
,
11655 no_ipv6_bgp_distance_source_cmd
,
11656 "no distance (1-255) X:X::X:X/M",
11658 "Define an administrative distance\n"
11659 "Administrative distance\n"
11660 "IP source prefix\n")
11662 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11663 return CMD_SUCCESS
;
11666 DEFUN (ipv6_bgp_distance_source_access_list
,
11667 ipv6_bgp_distance_source_access_list_cmd
,
11668 "distance (1-255) X:X::X:X/M WORD",
11669 "Define an administrative distance\n"
11670 "Administrative distance\n"
11671 "IP source prefix\n"
11672 "Access list name\n")
11674 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11675 return CMD_SUCCESS
;
11678 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11679 no_ipv6_bgp_distance_source_access_list_cmd
,
11680 "no distance (1-255) X:X::X:X/M WORD",
11682 "Define an administrative distance\n"
11683 "Administrative distance\n"
11684 "IP source prefix\n"
11685 "Access list name\n")
11687 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11688 return CMD_SUCCESS
;
11691 DEFUN (bgp_damp_set
,
11693 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11694 "BGP Specific commands\n"
11695 "Enable route-flap dampening\n"
11696 "Half-life time for the penalty\n"
11697 "Value to start reusing a route\n"
11698 "Value to start suppressing a route\n"
11699 "Maximum duration to suppress a stable route\n")
11701 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11702 int idx_half_life
= 2;
11704 int idx_suppress
= 4;
11705 int idx_max_suppress
= 5;
11706 int half
= DEFAULT_HALF_LIFE
* 60;
11707 int reuse
= DEFAULT_REUSE
;
11708 int suppress
= DEFAULT_SUPPRESS
;
11709 int max
= 4 * half
;
11712 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11713 reuse
= atoi(argv
[idx_reuse
]->arg
);
11714 suppress
= atoi(argv
[idx_suppress
]->arg
);
11715 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11716 } else if (argc
== 3) {
11717 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11721 if (suppress
< reuse
) {
11723 "Suppress value cannot be less than reuse value \n");
11727 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11728 reuse
, suppress
, max
);
11731 DEFUN (bgp_damp_unset
,
11732 bgp_damp_unset_cmd
,
11733 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11735 "BGP Specific commands\n"
11736 "Enable route-flap dampening\n"
11737 "Half-life time for the penalty\n"
11738 "Value to start reusing a route\n"
11739 "Value to start suppressing a route\n"
11740 "Maximum duration to suppress a stable route\n")
11742 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11743 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11746 /* Display specified route of BGP table. */
11747 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11748 const char *ip_str
, afi_t afi
, safi_t safi
,
11749 struct prefix_rd
*prd
, int prefix_check
)
11752 struct prefix match
;
11753 struct bgp_node
*rn
;
11754 struct bgp_node
*rm
;
11755 struct bgp_path_info
*pi
;
11756 struct bgp_path_info
*pi_temp
;
11758 struct bgp_table
*table
;
11760 /* BGP structure lookup. */
11762 bgp
= bgp_lookup_by_name(view_name
);
11764 vty_out(vty
, "%% Can't find BGP instance %s\n",
11766 return CMD_WARNING
;
11769 bgp
= bgp_get_default();
11771 vty_out(vty
, "%% No BGP process is configured\n");
11772 return CMD_WARNING
;
11776 /* Check IP address argument. */
11777 ret
= str2prefix(ip_str
, &match
);
11779 vty_out(vty
, "%% address is malformed\n");
11780 return CMD_WARNING
;
11783 match
.family
= afi2family(afi
);
11785 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11786 || (safi
== SAFI_EVPN
)) {
11787 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11788 rn
= bgp_route_next(rn
)) {
11789 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11791 table
= bgp_node_get_bgp_table_info(rn
);
11794 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11798 || rm
->p
.prefixlen
== match
.prefixlen
) {
11799 pi
= bgp_node_get_bgp_path_info(rm
);
11801 if (pi
->extra
&& pi
->extra
->damp_info
) {
11802 pi_temp
= pi
->next
;
11803 bgp_damp_info_free(
11804 pi
->extra
->damp_info
,
11812 bgp_unlock_node(rm
);
11815 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11818 || rn
->p
.prefixlen
== match
.prefixlen
) {
11819 pi
= bgp_node_get_bgp_path_info(rn
);
11821 if (pi
->extra
&& pi
->extra
->damp_info
) {
11822 pi_temp
= pi
->next
;
11823 bgp_damp_info_free(
11824 pi
->extra
->damp_info
,
11832 bgp_unlock_node(rn
);
11836 return CMD_SUCCESS
;
11839 DEFUN (clear_ip_bgp_dampening
,
11840 clear_ip_bgp_dampening_cmd
,
11841 "clear ip bgp dampening",
11845 "Clear route flap dampening information\n")
11847 bgp_damp_info_clean();
11848 return CMD_SUCCESS
;
11851 DEFUN (clear_ip_bgp_dampening_prefix
,
11852 clear_ip_bgp_dampening_prefix_cmd
,
11853 "clear ip bgp dampening A.B.C.D/M",
11857 "Clear route flap dampening information\n"
11860 int idx_ipv4_prefixlen
= 4;
11861 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11862 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11865 DEFUN (clear_ip_bgp_dampening_address
,
11866 clear_ip_bgp_dampening_address_cmd
,
11867 "clear ip bgp dampening A.B.C.D",
11871 "Clear route flap dampening information\n"
11872 "Network to clear damping information\n")
11875 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11876 SAFI_UNICAST
, NULL
, 0);
11879 DEFUN (clear_ip_bgp_dampening_address_mask
,
11880 clear_ip_bgp_dampening_address_mask_cmd
,
11881 "clear ip bgp dampening A.B.C.D A.B.C.D",
11885 "Clear route flap dampening information\n"
11886 "Network to clear damping information\n"
11890 int idx_ipv4_2
= 5;
11892 char prefix_str
[BUFSIZ
];
11894 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11897 vty_out(vty
, "%% Inconsistent address and mask\n");
11898 return CMD_WARNING
;
11901 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11905 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
11907 struct vty
*vty
= arg
;
11908 struct peer
*peer
= bucket
->data
;
11909 char buf
[SU_ADDRSTRLEN
];
11911 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
11912 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
11915 DEFUN (show_bgp_peerhash
,
11916 show_bgp_peerhash_cmd
,
11917 "show bgp peerhash",
11920 "Display information about the BGP peerhash\n")
11922 struct list
*instances
= bm
->bgp
;
11923 struct listnode
*node
;
11926 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
11927 vty_out(vty
, "BGP: %s\n", bgp
->name
);
11928 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
11932 return CMD_SUCCESS
;
11935 /* also used for encap safi */
11936 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11937 afi_t afi
, safi_t safi
)
11939 struct bgp_node
*prn
;
11940 struct bgp_node
*rn
;
11941 struct bgp_table
*table
;
11943 struct prefix_rd
*prd
;
11944 struct bgp_static
*bgp_static
;
11945 mpls_label_t label
;
11946 char buf
[SU_ADDRSTRLEN
];
11947 char rdbuf
[RD_ADDRSTRLEN
];
11949 /* Network configuration. */
11950 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11951 prn
= bgp_route_next(prn
)) {
11952 table
= bgp_node_get_bgp_table_info(prn
);
11956 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11957 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11958 if (bgp_static
== NULL
)
11962 prd
= (struct prefix_rd
*)&prn
->p
;
11964 /* "network" configuration display. */
11965 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11966 label
= decode_label(&bgp_static
->label
);
11968 vty_out(vty
, " network %s/%d rd %s",
11969 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11971 p
->prefixlen
, rdbuf
);
11972 if (safi
== SAFI_MPLS_VPN
)
11973 vty_out(vty
, " label %u", label
);
11975 if (bgp_static
->rmap
.name
)
11976 vty_out(vty
, " route-map %s",
11977 bgp_static
->rmap
.name
);
11979 if (bgp_static
->backdoor
)
11980 vty_out(vty
, " backdoor");
11982 vty_out(vty
, "\n");
11987 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11988 afi_t afi
, safi_t safi
)
11990 struct bgp_node
*prn
;
11991 struct bgp_node
*rn
;
11992 struct bgp_table
*table
;
11994 struct prefix_rd
*prd
;
11995 struct bgp_static
*bgp_static
;
11996 char buf
[PREFIX_STRLEN
* 2];
11997 char buf2
[SU_ADDRSTRLEN
];
11998 char rdbuf
[RD_ADDRSTRLEN
];
12000 /* Network configuration. */
12001 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12002 prn
= bgp_route_next(prn
)) {
12003 table
= bgp_node_get_bgp_table_info(prn
);
12007 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12008 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12009 if (bgp_static
== NULL
)
12012 char *macrouter
= NULL
;
12015 if (bgp_static
->router_mac
)
12016 macrouter
= prefix_mac2str(
12017 bgp_static
->router_mac
, NULL
, 0);
12018 if (bgp_static
->eth_s_id
)
12019 esi
= esi2str(bgp_static
->eth_s_id
);
12021 prd
= (struct prefix_rd
*)&prn
->p
;
12023 /* "network" configuration display. */
12024 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12025 if (p
->u
.prefix_evpn
.route_type
== 5) {
12026 char local_buf
[PREFIX_STRLEN
];
12027 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12028 struct prefix_evpn
*)p
)
12032 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12033 local_buf
, PREFIX_STRLEN
);
12034 sprintf(buf
, "%s/%u", local_buf
,
12035 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12037 prefix2str(p
, buf
, sizeof(buf
));
12040 if (bgp_static
->gatewayIp
.family
== AF_INET
12041 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12042 inet_ntop(bgp_static
->gatewayIp
.family
,
12043 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12046 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12048 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12049 decode_label(&bgp_static
->label
), esi
, buf2
,
12053 XFREE(MTYPE_TMP
, macrouter
);
12055 XFREE(MTYPE_TMP
, esi
);
12060 /* Configuration of static route announcement and aggregate
12062 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12065 struct bgp_node
*rn
;
12067 struct bgp_static
*bgp_static
;
12068 struct bgp_aggregate
*bgp_aggregate
;
12069 char buf
[SU_ADDRSTRLEN
];
12071 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12072 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12076 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12077 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12081 /* Network configuration. */
12082 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12083 rn
= bgp_route_next(rn
)) {
12084 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12085 if (bgp_static
== NULL
)
12090 /* "network" configuration display. */
12091 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
12092 uint32_t destination
;
12093 struct in_addr netmask
;
12095 destination
= ntohl(p
->u
.prefix4
.s_addr
);
12096 masklen2ip(p
->prefixlen
, &netmask
);
12097 vty_out(vty
, " network %s",
12098 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12101 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
12102 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
12103 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
12104 || p
->u
.prefix4
.s_addr
== 0) {
12105 /* Natural mask is not display. */
12107 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
12109 vty_out(vty
, " network %s/%d",
12110 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12115 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12116 vty_out(vty
, " label-index %u",
12117 bgp_static
->label_index
);
12119 if (bgp_static
->rmap
.name
)
12120 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12122 if (bgp_static
->backdoor
)
12123 vty_out(vty
, " backdoor");
12125 vty_out(vty
, "\n");
12128 /* Aggregate-address configuration. */
12129 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12130 rn
= bgp_route_next(rn
)) {
12131 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12132 if (bgp_aggregate
== NULL
)
12137 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
12138 struct in_addr netmask
;
12140 masklen2ip(p
->prefixlen
, &netmask
);
12141 vty_out(vty
, " aggregate-address %s %s",
12142 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12144 inet_ntoa(netmask
));
12146 vty_out(vty
, " aggregate-address %s/%d",
12147 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12152 if (bgp_aggregate
->as_set
)
12153 vty_out(vty
, " as-set");
12155 if (bgp_aggregate
->summary_only
)
12156 vty_out(vty
, " summary-only");
12158 vty_out(vty
, "\n");
12162 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12165 struct bgp_node
*rn
;
12166 struct bgp_distance
*bdistance
;
12168 /* Distance configuration. */
12169 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12170 && bgp
->distance_local
[afi
][safi
]
12171 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12172 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12173 || bgp
->distance_local
[afi
][safi
]
12174 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12175 vty_out(vty
, " distance bgp %d %d %d\n",
12176 bgp
->distance_ebgp
[afi
][safi
],
12177 bgp
->distance_ibgp
[afi
][safi
],
12178 bgp
->distance_local
[afi
][safi
]);
12181 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12182 rn
= bgp_route_next(rn
)) {
12183 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12184 if (bdistance
!= NULL
) {
12185 char buf
[PREFIX_STRLEN
];
12187 vty_out(vty
, " distance %d %s %s\n",
12188 bdistance
->distance
,
12189 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12190 bdistance
->access_list
? bdistance
->access_list
12196 /* Allocate routing table structure and install commands. */
12197 void bgp_route_init(void)
12202 /* Init BGP distance table. */
12203 FOREACH_AFI_SAFI (afi
, safi
)
12204 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12206 /* IPv4 BGP commands. */
12207 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12208 install_element(BGP_NODE
, &bgp_network_cmd
);
12209 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12211 install_element(BGP_NODE
, &aggregate_address_cmd
);
12212 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12213 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12214 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12216 /* IPv4 unicast configuration. */
12217 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12218 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12219 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12221 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12222 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12223 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12224 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12226 /* IPv4 multicast configuration. */
12227 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12228 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12229 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12230 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12231 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12232 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12233 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12235 /* IPv4 labeled-unicast configuration. */
12236 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12237 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12238 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12239 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12240 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12242 install_element(VIEW_NODE
,
12243 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12244 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12245 install_element(VIEW_NODE
,
12246 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12247 #ifdef KEEP_OLD_VPN_COMMANDS
12248 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12249 #endif /* KEEP_OLD_VPN_COMMANDS */
12250 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12251 install_element(VIEW_NODE
,
12252 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
12254 /* BGP dampening clear commands */
12255 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12256 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12258 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12259 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12262 install_element(ENABLE_NODE
,
12263 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12264 #ifdef KEEP_OLD_VPN_COMMANDS
12265 install_element(ENABLE_NODE
,
12266 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12267 #endif /* KEEP_OLD_VPN_COMMANDS */
12269 /* New config IPv6 BGP commands. */
12270 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12271 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12272 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12274 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12275 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12277 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12279 install_element(BGP_NODE
, &bgp_distance_cmd
);
12280 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12281 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12282 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12283 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12284 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12285 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12286 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12287 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12288 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12289 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12290 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12291 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12292 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12293 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12294 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12295 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12296 install_element(BGP_IPV4M_NODE
,
12297 &no_bgp_distance_source_access_list_cmd
);
12298 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12299 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12300 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12301 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12302 install_element(BGP_IPV6_NODE
,
12303 &ipv6_bgp_distance_source_access_list_cmd
);
12304 install_element(BGP_IPV6_NODE
,
12305 &no_ipv6_bgp_distance_source_access_list_cmd
);
12306 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12307 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12308 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12309 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12310 install_element(BGP_IPV6M_NODE
,
12311 &ipv6_bgp_distance_source_access_list_cmd
);
12312 install_element(BGP_IPV6M_NODE
,
12313 &no_ipv6_bgp_distance_source_access_list_cmd
);
12315 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12316 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12317 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12318 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12320 /* IPv4 Multicast Mode */
12321 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12322 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12324 /* Large Communities */
12325 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12326 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12328 /* show bgp ipv4 flowspec detailed */
12329 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12331 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12334 void bgp_route_finish(void)
12339 FOREACH_AFI_SAFI (afi
, safi
) {
12340 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12341 bgp_distance_table
[afi
][safi
] = NULL
;