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
, num_labels
* sizeof(mpls_label_t
));
3459 extra
->num_labels
= num_labels
;
3461 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3462 bgp_set_valid_label(&extra
->label
[0]);
3465 /* Update Overlay Index */
3466 if (afi
== AFI_L2VPN
) {
3467 overlay_index_update(new->attr
,
3468 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3469 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3471 /* Nexthop reachability check. */
3472 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3473 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3474 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3475 && !CHECK_FLAG(peer
->flags
,
3476 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3477 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3482 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3483 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3484 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3486 if (BGP_DEBUG(nht
, NHT
)) {
3487 char buf1
[INET6_ADDRSTRLEN
];
3489 (const void *)&attr_new
->nexthop
,
3490 buf1
, INET6_ADDRSTRLEN
);
3491 zlog_debug("%s(%s): NH unresolved",
3492 __FUNCTION__
, buf1
);
3494 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3497 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3500 new->addpath_rx_id
= addpath_id
;
3502 /* Increment prefix */
3503 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3505 /* Register new BGP information. */
3506 bgp_path_info_add(rn
, new);
3508 /* route_node_get lock */
3509 bgp_unlock_node(rn
);
3512 if (safi
== SAFI_MPLS_VPN
) {
3513 struct bgp_node
*prn
= NULL
;
3514 struct bgp_table
*table
= NULL
;
3516 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3517 if (bgp_node_has_bgp_path_info_data(prn
)) {
3518 table
= bgp_node_get_bgp_table_info(prn
);
3520 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3521 bgp
, prd
, table
, p
, new);
3523 bgp_unlock_node(prn
);
3527 /* If maximum prefix count is configured and current prefix
3529 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3532 /* If this is an EVPN route, process for import. */
3533 if (safi
== SAFI_EVPN
)
3534 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3536 /* Process change. */
3537 bgp_process(bgp
, rn
, afi
, safi
);
3539 if (SAFI_UNICAST
== safi
3540 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3541 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3542 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3544 if ((SAFI_MPLS_VPN
== safi
)
3545 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3547 vpn_leak_to_vrf_update(bgp
, new);
3550 if (SAFI_MPLS_VPN
== safi
) {
3551 mpls_label_t label_decoded
= decode_label(label
);
3553 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3554 sub_type
, &label_decoded
);
3556 if (SAFI_ENCAP
== safi
) {
3557 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3564 /* This BGP update is filtered. Log the reason then update BGP
3567 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3568 if (!peer
->rcvd_attr_printed
) {
3569 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3570 peer
->rcvd_attr_str
);
3571 peer
->rcvd_attr_printed
= 1;
3574 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3575 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3577 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3578 peer
->host
, pfx_buf
, reason
);
3582 /* If this is an EVPN route, un-import it as it is now filtered.
3584 if (safi
== SAFI_EVPN
)
3585 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3587 if (SAFI_UNICAST
== safi
3588 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3589 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3591 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3593 if ((SAFI_MPLS_VPN
== safi
)
3594 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3596 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3599 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3602 bgp_unlock_node(rn
);
3606 * Filtered update is treated as an implicit withdrawal (see
3608 * a few lines above)
3610 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3611 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3619 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3620 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3621 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3622 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3625 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3626 struct bgp_node
*rn
;
3627 struct bgp_path_info
*pi
;
3630 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3631 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3639 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3641 /* If peer is soft reconfiguration enabled. Record input packet for
3642 * further calculation.
3644 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3645 * routes that are filtered. This tanks out Quagga RS pretty badly due
3647 * the iteration over all RS clients.
3648 * Since we need to remove the entry from adj_in anyway, do that first
3650 * if there was no entry, we don't need to do anything more.
3652 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3653 && peer
!= bgp
->peer_self
)
3654 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3655 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3656 bgp_debug_rdpfxpath2str(
3657 afi
, safi
, prd
, p
, label
, num_labels
,
3658 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3661 "%s withdrawing route %s not in adj-in",
3662 peer
->host
, pfx_buf
);
3664 bgp_unlock_node(rn
);
3668 /* Lookup withdrawn route. */
3669 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3670 if (pi
->peer
== peer
&& pi
->type
== type
3671 && pi
->sub_type
== sub_type
3672 && pi
->addpath_rx_id
== addpath_id
)
3676 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3677 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3678 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3680 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3684 /* Withdraw specified route from routing table. */
3685 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3686 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3687 if (SAFI_UNICAST
== safi
3688 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3689 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3690 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3692 if ((SAFI_MPLS_VPN
== safi
)
3693 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3695 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3697 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3698 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3699 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3701 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3704 /* Unlock bgp_node_get() lock. */
3705 bgp_unlock_node(rn
);
3710 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3713 struct update_subgroup
*subgrp
;
3714 subgrp
= peer_subgroup(peer
, afi
, safi
);
3715 subgroup_default_originate(subgrp
, withdraw
);
3720 * bgp_stop_announce_route_timer
3722 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3724 if (!paf
->t_announce_route
)
3727 THREAD_TIMER_OFF(paf
->t_announce_route
);
3731 * bgp_announce_route_timer_expired
3733 * Callback that is invoked when the route announcement timer for a
3736 static int bgp_announce_route_timer_expired(struct thread
*t
)
3738 struct peer_af
*paf
;
3741 paf
= THREAD_ARG(t
);
3744 if (peer
->status
!= Established
)
3747 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3750 peer_af_announce_route(paf
, 1);
3755 * bgp_announce_route
3757 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3759 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3761 struct peer_af
*paf
;
3762 struct update_subgroup
*subgrp
;
3764 paf
= peer_af_find(peer
, afi
, safi
);
3767 subgrp
= PAF_SUBGRP(paf
);
3770 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3771 * or a refresh has already been triggered.
3773 if (!subgrp
|| paf
->t_announce_route
)
3777 * Start a timer to stagger/delay the announce. This serves
3778 * two purposes - announcement can potentially be combined for
3779 * multiple peers and the announcement doesn't happen in the
3782 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3783 (subgrp
->peer_count
== 1)
3784 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3785 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3786 &paf
->t_announce_route
);
3790 * Announce routes from all AF tables to a peer.
3792 * This should ONLY be called when there is a need to refresh the
3793 * routes to the peer based on a policy change for this peer alone
3794 * or a route refresh request received from the peer.
3795 * The operation will result in splitting the peer from its existing
3796 * subgroups and putting it in new subgroups.
3798 void bgp_announce_route_all(struct peer
*peer
)
3803 FOREACH_AFI_SAFI (afi
, safi
)
3804 bgp_announce_route(peer
, afi
, safi
);
3807 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3808 struct bgp_table
*table
,
3809 struct prefix_rd
*prd
)
3812 struct bgp_node
*rn
;
3813 struct bgp_adj_in
*ain
;
3816 table
= peer
->bgp
->rib
[afi
][safi
];
3818 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3819 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3820 if (ain
->peer
!= peer
)
3823 struct bgp_path_info
*pi
=
3824 bgp_node_get_bgp_path_info(rn
);
3825 uint32_t num_labels
= 0;
3826 mpls_label_t
*label_pnt
= NULL
;
3827 struct bgp_route_evpn evpn
;
3829 if (pi
&& pi
->extra
)
3830 num_labels
= pi
->extra
->num_labels
;
3832 label_pnt
= &pi
->extra
->label
[0];
3834 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3837 memset(&evpn
, 0, sizeof(evpn
));
3839 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3840 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3841 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3842 num_labels
, 1, &evpn
);
3845 bgp_unlock_node(rn
);
3851 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3853 struct bgp_node
*rn
;
3854 struct bgp_table
*table
;
3856 if (peer
->status
!= Established
)
3859 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3860 && (safi
!= SAFI_EVPN
))
3861 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3863 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3864 rn
= bgp_route_next(rn
)) {
3865 table
= bgp_node_get_bgp_table_info(rn
);
3866 if (table
!= NULL
) {
3867 struct prefix_rd prd
;
3869 prd
.family
= AF_UNSPEC
;
3871 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3873 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3880 struct bgp_clear_node_queue
{
3881 struct bgp_node
*rn
;
3884 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3886 struct bgp_clear_node_queue
*cnq
= data
;
3887 struct bgp_node
*rn
= cnq
->rn
;
3888 struct peer
*peer
= wq
->spec
.data
;
3889 struct bgp_path_info
*pi
;
3891 afi_t afi
= bgp_node_table(rn
)->afi
;
3892 safi_t safi
= bgp_node_table(rn
)->safi
;
3897 /* It is possible that we have multiple paths for a prefix from a peer
3898 * if that peer is using AddPath.
3900 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3901 if (pi
->peer
!= peer
)
3904 /* graceful restart STALE flag set. */
3905 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3906 && peer
->nsf
[afi
][safi
]
3907 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3908 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3909 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3911 /* If this is an EVPN route, process for
3913 if (safi
== SAFI_EVPN
)
3914 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3916 /* Handle withdraw for VRF route-leaking and L3VPN */
3917 if (SAFI_UNICAST
== safi
3918 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3919 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3920 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3923 if (SAFI_MPLS_VPN
== safi
&&
3924 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3925 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3928 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3934 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3936 struct bgp_clear_node_queue
*cnq
= data
;
3937 struct bgp_node
*rn
= cnq
->rn
;
3938 struct bgp_table
*table
= bgp_node_table(rn
);
3940 bgp_unlock_node(rn
);
3941 bgp_table_unlock(table
);
3942 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3945 static void bgp_clear_node_complete(struct work_queue
*wq
)
3947 struct peer
*peer
= wq
->spec
.data
;
3949 /* Tickle FSM to start moving again */
3950 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3952 peer_unlock(peer
); /* bgp_clear_route */
3955 static void bgp_clear_node_queue_init(struct peer
*peer
)
3957 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3959 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3960 #undef CLEAR_QUEUE_NAME_LEN
3962 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3963 peer
->clear_node_queue
->spec
.hold
= 10;
3964 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3965 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3966 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3967 peer
->clear_node_queue
->spec
.max_retries
= 0;
3969 /* we only 'lock' this peer reference when the queue is actually active
3971 peer
->clear_node_queue
->spec
.data
= peer
;
3974 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3975 struct bgp_table
*table
)
3977 struct bgp_node
*rn
;
3978 int force
= bm
->process_main_queue
? 0 : 1;
3981 table
= peer
->bgp
->rib
[afi
][safi
];
3983 /* If still no table => afi/safi isn't configured at all or smth. */
3987 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3988 struct bgp_path_info
*pi
, *next
;
3989 struct bgp_adj_in
*ain
;
3990 struct bgp_adj_in
*ain_next
;
3992 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3993 * queued for every clearing peer, regardless of whether it is
3994 * relevant to the peer at hand.
3996 * Overview: There are 3 different indices which need to be
3997 * scrubbed, potentially, when a peer is removed:
3999 * 1 peer's routes visible via the RIB (ie accepted routes)
4000 * 2 peer's routes visible by the (optional) peer's adj-in index
4001 * 3 other routes visible by the peer's adj-out index
4003 * 3 there is no hurry in scrubbing, once the struct peer is
4004 * removed from bgp->peer, we could just GC such deleted peer's
4005 * adj-outs at our leisure.
4007 * 1 and 2 must be 'scrubbed' in some way, at least made
4008 * invisible via RIB index before peer session is allowed to be
4009 * brought back up. So one needs to know when such a 'search' is
4014 * - there'd be a single global queue or a single RIB walker
4015 * - rather than tracking which route_nodes still need to be
4016 * examined on a peer basis, we'd track which peers still
4019 * Given that our per-peer prefix-counts now should be reliable,
4020 * this may actually be achievable. It doesn't seem to be a huge
4021 * problem at this time,
4023 * It is possible that we have multiple paths for a prefix from
4025 * if that peer is using AddPath.
4029 ain_next
= ain
->next
;
4031 if (ain
->peer
== peer
) {
4032 bgp_adj_in_remove(rn
, ain
);
4033 bgp_unlock_node(rn
);
4039 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4041 if (pi
->peer
!= peer
)
4045 bgp_path_info_reap(rn
, pi
);
4047 struct bgp_clear_node_queue
*cnq
;
4049 /* both unlocked in bgp_clear_node_queue_del */
4050 bgp_table_lock(bgp_node_table(rn
));
4053 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4054 sizeof(struct bgp_clear_node_queue
));
4056 work_queue_add(peer
->clear_node_queue
, cnq
);
4064 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4066 struct bgp_node
*rn
;
4067 struct bgp_table
*table
;
4069 if (peer
->clear_node_queue
== NULL
)
4070 bgp_clear_node_queue_init(peer
);
4072 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4073 * Idle until it receives a Clearing_Completed event. This protects
4074 * against peers which flap faster than we can we clear, which could
4077 * a) race with routes from the new session being installed before
4078 * clear_route_node visits the node (to delete the route of that
4080 * b) resource exhaustion, clear_route_node likely leads to an entry
4081 * on the process_main queue. Fast-flapping could cause that queue
4085 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4086 * the unlock will happen upon work-queue completion; other wise, the
4087 * unlock happens at the end of this function.
4089 if (!peer
->clear_node_queue
->thread
)
4092 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4093 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4095 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4096 rn
= bgp_route_next(rn
)) {
4097 table
= bgp_node_get_bgp_table_info(rn
);
4101 bgp_clear_route_table(peer
, afi
, safi
, table
);
4104 /* unlock if no nodes got added to the clear-node-queue. */
4105 if (!peer
->clear_node_queue
->thread
)
4109 void bgp_clear_route_all(struct peer
*peer
)
4114 FOREACH_AFI_SAFI (afi
, safi
)
4115 bgp_clear_route(peer
, afi
, safi
);
4118 rfapiProcessPeerDown(peer
);
4122 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4124 struct bgp_table
*table
;
4125 struct bgp_node
*rn
;
4126 struct bgp_adj_in
*ain
;
4127 struct bgp_adj_in
*ain_next
;
4129 table
= peer
->bgp
->rib
[afi
][safi
];
4131 /* It is possible that we have multiple paths for a prefix from a peer
4132 * if that peer is using AddPath.
4134 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4138 ain_next
= ain
->next
;
4140 if (ain
->peer
== peer
) {
4141 bgp_adj_in_remove(rn
, ain
);
4142 bgp_unlock_node(rn
);
4150 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4152 struct bgp_node
*rn
;
4153 struct bgp_path_info
*pi
;
4154 struct bgp_table
*table
;
4156 if (safi
== SAFI_MPLS_VPN
) {
4157 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4158 rn
= bgp_route_next(rn
)) {
4159 struct bgp_node
*rm
;
4161 /* look for neighbor in tables */
4162 table
= bgp_node_get_bgp_table_info(rn
);
4166 for (rm
= bgp_table_top(table
); rm
;
4167 rm
= bgp_route_next(rm
))
4168 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4170 if (pi
->peer
!= peer
)
4172 if (!CHECK_FLAG(pi
->flags
,
4176 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4181 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4182 rn
= bgp_route_next(rn
))
4183 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4185 if (pi
->peer
!= peer
)
4187 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4189 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4195 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4197 if (peer
->sort
== BGP_PEER_EBGP
4198 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4199 || FILTER_LIST_OUT_NAME(filter
)
4200 || DISTRIBUTE_OUT_NAME(filter
)))
4205 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4207 if (peer
->sort
== BGP_PEER_EBGP
4208 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4209 || FILTER_LIST_IN_NAME(filter
)
4210 || DISTRIBUTE_IN_NAME(filter
)))
4215 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4218 struct bgp_node
*rn
;
4219 struct bgp_path_info
*pi
;
4220 struct bgp_path_info
*next
;
4222 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4223 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4225 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4226 && pi
->type
== ZEBRA_ROUTE_BGP
4227 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4228 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4229 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4231 if (bgp_fibupd_safi(safi
))
4232 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4234 bgp_path_info_reap(rn
, pi
);
4239 /* Delete all kernel routes. */
4240 void bgp_cleanup_routes(struct bgp
*bgp
)
4243 struct bgp_node
*rn
;
4244 struct bgp_table
*table
;
4246 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4247 if (afi
== AFI_L2VPN
)
4249 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4252 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4254 if (afi
!= AFI_L2VPN
) {
4256 safi
= SAFI_MPLS_VPN
;
4257 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4258 rn
= bgp_route_next(rn
)) {
4259 table
= bgp_node_get_bgp_table_info(rn
);
4260 if (table
!= NULL
) {
4261 bgp_cleanup_table(bgp
, table
, safi
);
4262 bgp_table_finish(&table
);
4263 bgp_node_set_bgp_table_info(rn
, NULL
);
4264 bgp_unlock_node(rn
);
4268 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4269 rn
= bgp_route_next(rn
)) {
4270 table
= bgp_node_get_bgp_table_info(rn
);
4271 if (table
!= NULL
) {
4272 bgp_cleanup_table(bgp
, table
, safi
);
4273 bgp_table_finish(&table
);
4274 bgp_node_set_bgp_table_info(rn
, NULL
);
4275 bgp_unlock_node(rn
);
4280 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4281 rn
= bgp_route_next(rn
)) {
4282 table
= bgp_node_get_bgp_table_info(rn
);
4283 if (table
!= NULL
) {
4284 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4285 bgp_table_finish(&table
);
4286 bgp_node_set_bgp_table_info(rn
, NULL
);
4287 bgp_unlock_node(rn
);
4292 void bgp_reset(void)
4295 bgp_zclient_reset();
4296 access_list_reset();
4297 prefix_list_reset();
4300 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4302 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4303 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4304 PEER_CAP_ADDPATH_AF_TX_RCV
));
4307 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4309 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4310 struct bgp_nlri
*packet
)
4319 int addpath_encoded
;
4320 uint32_t addpath_id
;
4323 lim
= pnt
+ packet
->length
;
4325 safi
= packet
->safi
;
4327 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4329 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4330 syntactic validity. If the field is syntactically incorrect,
4331 then the Error Subcode is set to Invalid Network Field. */
4332 for (; pnt
< lim
; pnt
+= psize
) {
4333 /* Clear prefix structure. */
4334 memset(&p
, 0, sizeof(struct prefix
));
4336 if (addpath_encoded
) {
4338 /* When packet overflow occurs return immediately. */
4339 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4342 addpath_id
= ntohl(*((uint32_t *)pnt
));
4343 pnt
+= BGP_ADDPATH_ID_LEN
;
4346 /* Fetch prefix length. */
4347 p
.prefixlen
= *pnt
++;
4348 /* afi/safi validity already verified by caller,
4349 * bgp_update_receive */
4350 p
.family
= afi2family(afi
);
4352 /* Prefix length check. */
4353 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4356 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4357 peer
->host
, p
.prefixlen
, packet
->afi
);
4361 /* Packet size overflow check. */
4362 psize
= PSIZE(p
.prefixlen
);
4364 /* When packet overflow occur return immediately. */
4365 if (pnt
+ psize
> lim
) {
4368 "%s [Error] Update packet error (prefix length %d overflows packet)",
4369 peer
->host
, p
.prefixlen
);
4373 /* Defensive coding, double-check the psize fits in a struct
4375 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4378 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4379 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4383 /* Fetch prefix from NLRI packet. */
4384 memcpy(p
.u
.val
, pnt
, psize
);
4386 /* Check address. */
4387 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4388 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4389 /* From RFC4271 Section 6.3:
4391 * If a prefix in the NLRI field is semantically
4393 * (e.g., an unexpected multicast IP address),
4395 * be logged locally, and the prefix SHOULD be
4400 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4401 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4406 /* Check address. */
4407 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4408 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4413 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4415 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4420 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4425 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4427 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4434 /* Normal process. */
4436 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4437 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4438 NULL
, NULL
, 0, 0, NULL
);
4440 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4441 safi
, ZEBRA_ROUTE_BGP
,
4442 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4445 /* Address family configuration mismatch or maximum-prefix count
4451 /* Packet length consistency check. */
4455 "%s [Error] Update packet error (prefix length mismatch with total length)",
4463 static struct bgp_static
*bgp_static_new(void)
4465 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4468 static void bgp_static_free(struct bgp_static
*bgp_static
)
4470 if (bgp_static
->rmap
.name
)
4471 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4472 route_map_counter_decrement(bgp_static
->rmap
.map
);
4474 if (bgp_static
->eth_s_id
)
4475 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4476 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4479 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4480 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4482 struct bgp_node
*rn
;
4483 struct bgp_path_info
*pi
;
4484 struct bgp_path_info
*new;
4485 struct bgp_path_info rmap_path
;
4487 struct attr
*attr_new
;
4490 int vnc_implicit_withdraw
= 0;
4497 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4499 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4501 attr
.nexthop
= bgp_static
->igpnexthop
;
4502 attr
.med
= bgp_static
->igpmetric
;
4503 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4505 if (bgp_static
->atomic
)
4506 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4508 /* Store label index, if required. */
4509 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4510 attr
.label_index
= bgp_static
->label_index
;
4511 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4514 /* Apply route-map. */
4515 if (bgp_static
->rmap
.name
) {
4516 struct attr attr_tmp
= attr
;
4518 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4519 rmap_path
.peer
= bgp
->peer_self
;
4520 rmap_path
.attr
= &attr_tmp
;
4522 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4524 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4527 bgp
->peer_self
->rmap_type
= 0;
4529 if (ret
== RMAP_DENYMATCH
) {
4530 /* Free uninterned attribute. */
4531 bgp_attr_flush(&attr_tmp
);
4533 /* Unintern original. */
4534 aspath_unintern(&attr
.aspath
);
4535 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4539 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4540 bgp_attr_add_gshut_community(&attr_tmp
);
4542 attr_new
= bgp_attr_intern(&attr_tmp
);
4545 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4546 bgp_attr_add_gshut_community(&attr
);
4548 attr_new
= bgp_attr_intern(&attr
);
4551 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4552 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4553 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4557 if (attrhash_cmp(pi
->attr
, attr_new
)
4558 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4559 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4560 bgp_unlock_node(rn
);
4561 bgp_attr_unintern(&attr_new
);
4562 aspath_unintern(&attr
.aspath
);
4565 /* The attribute is changed. */
4566 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4568 /* Rewrite BGP route information. */
4569 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4570 bgp_path_info_restore(rn
, pi
);
4572 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4574 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4575 && (safi
== SAFI_UNICAST
)) {
4576 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4578 * Implicit withdraw case.
4579 * We have to do this before pi is
4582 ++vnc_implicit_withdraw
;
4583 vnc_import_bgp_del_route(bgp
, p
, pi
);
4584 vnc_import_bgp_exterior_del_route(
4589 bgp_attr_unintern(&pi
->attr
);
4590 pi
->attr
= attr_new
;
4591 pi
->uptime
= bgp_clock();
4593 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4594 && (safi
== SAFI_UNICAST
)) {
4595 if (vnc_implicit_withdraw
) {
4596 vnc_import_bgp_add_route(bgp
, p
, pi
);
4597 vnc_import_bgp_exterior_add_route(
4603 /* Nexthop reachability check. */
4604 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4605 && (safi
== SAFI_UNICAST
4606 || safi
== SAFI_LABELED_UNICAST
)) {
4608 struct bgp
*bgp_nexthop
= bgp
;
4610 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4611 bgp_nexthop
= pi
->extra
->bgp_orig
;
4613 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4615 bgp_path_info_set_flag(rn
, pi
,
4618 if (BGP_DEBUG(nht
, NHT
)) {
4619 char buf1
[INET6_ADDRSTRLEN
];
4620 inet_ntop(p
->family
,
4624 "%s(%s): Route not in table, not advertising",
4625 __FUNCTION__
, buf1
);
4627 bgp_path_info_unset_flag(
4628 rn
, pi
, BGP_PATH_VALID
);
4631 /* Delete the NHT structure if any, if we're
4633 * enabling/disabling import check. We
4634 * deregister the route
4635 * from NHT to avoid overloading NHT and the
4636 * process interaction
4638 bgp_unlink_nexthop(pi
);
4639 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4641 /* Process change. */
4642 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4643 bgp_process(bgp
, rn
, afi
, safi
);
4645 if (SAFI_UNICAST
== safi
4646 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4648 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4649 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4653 bgp_unlock_node(rn
);
4654 aspath_unintern(&attr
.aspath
);
4659 /* Make new BGP info. */
4660 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4662 /* Nexthop reachability check. */
4663 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4664 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4665 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4666 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4668 if (BGP_DEBUG(nht
, NHT
)) {
4669 char buf1
[INET6_ADDRSTRLEN
];
4670 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4673 "%s(%s): Route not in table, not advertising",
4674 __FUNCTION__
, buf1
);
4676 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4679 /* Delete the NHT structure if any, if we're toggling between
4680 * enabling/disabling import check. We deregister the route
4681 * from NHT to avoid overloading NHT and the process interaction
4683 bgp_unlink_nexthop(new);
4685 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4688 /* Aggregate address increment. */
4689 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4691 /* Register new BGP information. */
4692 bgp_path_info_add(rn
, new);
4694 /* route_node_get lock */
4695 bgp_unlock_node(rn
);
4697 /* Process change. */
4698 bgp_process(bgp
, rn
, afi
, safi
);
4700 if (SAFI_UNICAST
== safi
4701 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4702 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4703 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4706 /* Unintern original. */
4707 aspath_unintern(&attr
.aspath
);
4710 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4713 struct bgp_node
*rn
;
4714 struct bgp_path_info
*pi
;
4716 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4718 /* Check selected route and self inserted route. */
4719 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4720 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4721 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4724 /* Withdraw static BGP route from routing table. */
4726 if (SAFI_UNICAST
== safi
4727 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4728 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4729 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4731 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4732 bgp_unlink_nexthop(pi
);
4733 bgp_path_info_delete(rn
, pi
);
4734 bgp_process(bgp
, rn
, afi
, safi
);
4737 /* Unlock bgp_node_lookup. */
4738 bgp_unlock_node(rn
);
4742 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4744 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4745 afi_t afi
, safi_t safi
,
4746 struct prefix_rd
*prd
)
4748 struct bgp_node
*rn
;
4749 struct bgp_path_info
*pi
;
4751 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4753 /* Check selected route and self inserted route. */
4754 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4755 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4756 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4759 /* Withdraw static BGP route from routing table. */
4762 rfapiProcessWithdraw(
4763 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4764 1); /* Kill, since it is an administrative change */
4766 if (SAFI_MPLS_VPN
== safi
4767 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4768 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4770 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4771 bgp_path_info_delete(rn
, pi
);
4772 bgp_process(bgp
, rn
, afi
, safi
);
4775 /* Unlock bgp_node_lookup. */
4776 bgp_unlock_node(rn
);
4779 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4780 struct bgp_static
*bgp_static
, afi_t afi
,
4783 struct bgp_node
*rn
;
4784 struct bgp_path_info
*new;
4785 struct attr
*attr_new
;
4786 struct attr attr
= {0};
4787 struct bgp_path_info
*pi
;
4789 mpls_label_t label
= 0;
4791 uint32_t num_labels
= 0;
4796 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4798 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4801 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4803 attr
.nexthop
= bgp_static
->igpnexthop
;
4804 attr
.med
= bgp_static
->igpmetric
;
4805 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4807 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4808 || (safi
== SAFI_ENCAP
)) {
4809 if (afi
== AFI_IP
) {
4810 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4811 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4814 if (afi
== AFI_L2VPN
) {
4815 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4817 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4818 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4819 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4820 sizeof(struct in6_addr
));
4821 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4822 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4823 struct bgp_encap_type_vxlan bet
;
4824 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4825 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4826 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4828 if (bgp_static
->router_mac
) {
4829 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4832 /* Apply route-map. */
4833 if (bgp_static
->rmap
.name
) {
4834 struct attr attr_tmp
= attr
;
4835 struct bgp_path_info rmap_path
;
4838 rmap_path
.peer
= bgp
->peer_self
;
4839 rmap_path
.attr
= &attr_tmp
;
4841 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4843 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4846 bgp
->peer_self
->rmap_type
= 0;
4848 if (ret
== RMAP_DENYMATCH
) {
4849 /* Free uninterned attribute. */
4850 bgp_attr_flush(&attr_tmp
);
4852 /* Unintern original. */
4853 aspath_unintern(&attr
.aspath
);
4854 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4859 attr_new
= bgp_attr_intern(&attr_tmp
);
4861 attr_new
= bgp_attr_intern(&attr
);
4864 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4865 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4866 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4870 memset(&add
, 0, sizeof(union gw_addr
));
4871 if (attrhash_cmp(pi
->attr
, attr_new
)
4872 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4873 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4874 bgp_unlock_node(rn
);
4875 bgp_attr_unintern(&attr_new
);
4876 aspath_unintern(&attr
.aspath
);
4879 /* The attribute is changed. */
4880 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4882 /* Rewrite BGP route information. */
4883 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4884 bgp_path_info_restore(rn
, pi
);
4886 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4887 bgp_attr_unintern(&pi
->attr
);
4888 pi
->attr
= attr_new
;
4889 pi
->uptime
= bgp_clock();
4892 label
= decode_label(&pi
->extra
->label
[0]);
4895 /* Process change. */
4896 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4897 bgp_process(bgp
, rn
, afi
, safi
);
4899 if (SAFI_MPLS_VPN
== safi
4900 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4901 vpn_leak_to_vrf_update(bgp
, pi
);
4904 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4905 pi
->attr
, afi
, safi
, pi
->type
,
4906 pi
->sub_type
, &label
);
4908 bgp_unlock_node(rn
);
4909 aspath_unintern(&attr
.aspath
);
4915 /* Make new BGP info. */
4916 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4918 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4919 new->extra
= bgp_path_info_extra_new();
4921 new->extra
->label
[0] = bgp_static
->label
;
4922 new->extra
->num_labels
= num_labels
;
4925 label
= decode_label(&bgp_static
->label
);
4928 /* Aggregate address increment. */
4929 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4931 /* Register new BGP information. */
4932 bgp_path_info_add(rn
, new);
4933 /* route_node_get lock */
4934 bgp_unlock_node(rn
);
4936 /* Process change. */
4937 bgp_process(bgp
, rn
, afi
, safi
);
4939 if (SAFI_MPLS_VPN
== safi
4940 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4941 vpn_leak_to_vrf_update(bgp
, new);
4944 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4945 safi
, new->type
, new->sub_type
, &label
);
4948 /* Unintern original. */
4949 aspath_unintern(&attr
.aspath
);
4952 /* Configure static BGP network. When user don't run zebra, static
4953 route should be installed as valid. */
4954 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4955 const char *ip_str
, afi_t afi
, safi_t safi
,
4956 const char *rmap
, int backdoor
, uint32_t label_index
)
4958 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4961 struct bgp_static
*bgp_static
;
4962 struct bgp_node
*rn
;
4963 uint8_t need_update
= 0;
4965 /* Convert IP prefix string to struct prefix. */
4966 ret
= str2prefix(ip_str
, &p
);
4968 vty_out(vty
, "%% Malformed prefix\n");
4969 return CMD_WARNING_CONFIG_FAILED
;
4971 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4972 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4973 return CMD_WARNING_CONFIG_FAILED
;
4980 /* Set BGP static route configuration. */
4981 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4984 vty_out(vty
, "%% Can't find static route specified\n");
4985 return CMD_WARNING_CONFIG_FAILED
;
4988 bgp_static
= bgp_node_get_bgp_static_info(rn
);
4990 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4991 && (label_index
!= bgp_static
->label_index
)) {
4993 "%% label-index doesn't match static route\n");
4994 return CMD_WARNING_CONFIG_FAILED
;
4997 if ((rmap
&& bgp_static
->rmap
.name
)
4998 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5000 "%% route-map name doesn't match static route\n");
5001 return CMD_WARNING_CONFIG_FAILED
;
5004 /* Update BGP RIB. */
5005 if (!bgp_static
->backdoor
)
5006 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5008 /* Clear configuration. */
5009 bgp_static_free(bgp_static
);
5010 bgp_node_set_bgp_static_info(rn
, NULL
);
5011 bgp_unlock_node(rn
);
5012 bgp_unlock_node(rn
);
5015 /* Set BGP static route configuration. */
5016 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5018 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5020 /* Configuration change. */
5021 /* Label index cannot be changed. */
5022 if (bgp_static
->label_index
!= label_index
) {
5023 vty_out(vty
, "%% cannot change label-index\n");
5024 return CMD_WARNING_CONFIG_FAILED
;
5027 /* Check previous routes are installed into BGP. */
5028 if (bgp_static
->valid
5029 && bgp_static
->backdoor
!= backdoor
)
5032 bgp_static
->backdoor
= backdoor
;
5035 if (bgp_static
->rmap
.name
)
5036 XFREE(MTYPE_ROUTE_MAP_NAME
,
5037 bgp_static
->rmap
.name
);
5038 route_map_counter_decrement(
5039 bgp_static
->rmap
.map
);
5040 bgp_static
->rmap
.name
=
5041 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5042 bgp_static
->rmap
.map
=
5043 route_map_lookup_by_name(rmap
);
5044 route_map_counter_increment(
5045 bgp_static
->rmap
.map
);
5047 if (bgp_static
->rmap
.name
)
5048 XFREE(MTYPE_ROUTE_MAP_NAME
,
5049 bgp_static
->rmap
.name
);
5050 route_map_counter_decrement(
5051 bgp_static
->rmap
.map
);
5052 bgp_static
->rmap
.name
= NULL
;
5053 bgp_static
->rmap
.map
= NULL
;
5054 bgp_static
->valid
= 0;
5056 bgp_unlock_node(rn
);
5058 /* New configuration. */
5059 bgp_static
= bgp_static_new();
5060 bgp_static
->backdoor
= backdoor
;
5061 bgp_static
->valid
= 0;
5062 bgp_static
->igpmetric
= 0;
5063 bgp_static
->igpnexthop
.s_addr
= 0;
5064 bgp_static
->label_index
= label_index
;
5067 if (bgp_static
->rmap
.name
)
5068 XFREE(MTYPE_ROUTE_MAP_NAME
,
5069 bgp_static
->rmap
.name
);
5070 route_map_counter_decrement(
5071 bgp_static
->rmap
.map
);
5072 bgp_static
->rmap
.name
=
5073 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5074 bgp_static
->rmap
.map
=
5075 route_map_lookup_by_name(rmap
);
5076 route_map_counter_increment(
5077 bgp_static
->rmap
.map
);
5079 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5082 bgp_static
->valid
= 1;
5084 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5086 if (!bgp_static
->backdoor
)
5087 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5093 void bgp_static_add(struct bgp
*bgp
)
5097 struct bgp_node
*rn
;
5098 struct bgp_node
*rm
;
5099 struct bgp_table
*table
;
5100 struct bgp_static
*bgp_static
;
5102 FOREACH_AFI_SAFI (afi
, safi
)
5103 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5104 rn
= bgp_route_next(rn
)) {
5105 if (!bgp_node_has_bgp_path_info_data(rn
))
5108 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5109 || (safi
== SAFI_EVPN
)) {
5110 table
= bgp_node_get_bgp_table_info(rn
);
5112 for (rm
= bgp_table_top(table
); rm
;
5113 rm
= bgp_route_next(rm
)) {
5115 bgp_node_get_bgp_static_info(
5117 bgp_static_update_safi(bgp
, &rm
->p
,
5124 bgp_node_get_bgp_static_info(rn
), afi
,
5130 /* Called from bgp_delete(). Delete all static routes from the BGP
5132 void bgp_static_delete(struct bgp
*bgp
)
5136 struct bgp_node
*rn
;
5137 struct bgp_node
*rm
;
5138 struct bgp_table
*table
;
5139 struct bgp_static
*bgp_static
;
5141 FOREACH_AFI_SAFI (afi
, safi
)
5142 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5143 rn
= bgp_route_next(rn
)) {
5144 if (!bgp_node_has_bgp_path_info_data(rn
))
5147 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5148 || (safi
== SAFI_EVPN
)) {
5149 table
= bgp_node_get_bgp_table_info(rn
);
5151 for (rm
= bgp_table_top(table
); rm
;
5152 rm
= bgp_route_next(rm
)) {
5154 bgp_node_get_bgp_static_info(
5159 bgp_static_withdraw_safi(
5160 bgp
, &rm
->p
, AFI_IP
, safi
,
5161 (struct prefix_rd
*)&rn
->p
);
5162 bgp_static_free(bgp_static
);
5163 bgp_node_set_bgp_static_info(rn
, NULL
);
5164 bgp_unlock_node(rn
);
5167 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5168 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5169 bgp_static_free(bgp_static
);
5170 bgp_node_set_bgp_static_info(rn
, NULL
);
5171 bgp_unlock_node(rn
);
5176 void bgp_static_redo_import_check(struct bgp
*bgp
)
5180 struct bgp_node
*rn
;
5181 struct bgp_node
*rm
;
5182 struct bgp_table
*table
;
5183 struct bgp_static
*bgp_static
;
5185 /* Use this flag to force reprocessing of the route */
5186 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5187 FOREACH_AFI_SAFI (afi
, safi
) {
5188 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5189 rn
= bgp_route_next(rn
)) {
5190 if (!bgp_node_has_bgp_path_info_data(rn
))
5193 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5194 || (safi
== SAFI_EVPN
)) {
5195 table
= bgp_node_get_bgp_table_info(rn
);
5197 for (rm
= bgp_table_top(table
); rm
;
5198 rm
= bgp_route_next(rm
)) {
5200 bgp_node_get_bgp_static_info(
5202 bgp_static_update_safi(bgp
, &rm
->p
,
5207 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5208 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5213 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5216 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5219 struct bgp_table
*table
;
5220 struct bgp_node
*rn
;
5221 struct bgp_path_info
*pi
;
5223 table
= bgp
->rib
[afi
][safi
];
5224 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5225 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5226 if (pi
->peer
== bgp
->peer_self
5227 && ((pi
->type
== ZEBRA_ROUTE_BGP
5228 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5229 || (pi
->type
!= ZEBRA_ROUTE_BGP
5231 == BGP_ROUTE_REDISTRIBUTE
))) {
5232 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5234 bgp_unlink_nexthop(pi
);
5235 bgp_path_info_delete(rn
, pi
);
5236 bgp_process(bgp
, rn
, afi
, safi
);
5243 * Purge all networks and redistributed routes from routing table.
5244 * Invoked upon the instance going down.
5246 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5251 FOREACH_AFI_SAFI (afi
, safi
)
5252 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5257 * Currently this is used to set static routes for VPN and ENCAP.
5258 * I think it can probably be factored with bgp_static_set.
5260 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5261 const char *ip_str
, const char *rd_str
,
5262 const char *label_str
, const char *rmap_str
,
5263 int evpn_type
, const char *esi
, const char *gwip
,
5264 const char *ethtag
, const char *routermac
)
5266 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5269 struct prefix_rd prd
;
5270 struct bgp_node
*prn
;
5271 struct bgp_node
*rn
;
5272 struct bgp_table
*table
;
5273 struct bgp_static
*bgp_static
;
5274 mpls_label_t label
= MPLS_INVALID_LABEL
;
5275 struct prefix gw_ip
;
5277 /* validate ip prefix */
5278 ret
= str2prefix(ip_str
, &p
);
5280 vty_out(vty
, "%% Malformed prefix\n");
5281 return CMD_WARNING_CONFIG_FAILED
;
5284 if ((afi
== AFI_L2VPN
)
5285 && (bgp_build_evpn_prefix(evpn_type
,
5286 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5287 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5288 return CMD_WARNING_CONFIG_FAILED
;
5291 ret
= str2prefix_rd(rd_str
, &prd
);
5293 vty_out(vty
, "%% Malformed rd\n");
5294 return CMD_WARNING_CONFIG_FAILED
;
5298 unsigned long label_val
;
5299 label_val
= strtoul(label_str
, NULL
, 10);
5300 encode_label(label_val
, &label
);
5303 if (safi
== SAFI_EVPN
) {
5304 if (esi
&& str2esi(esi
, NULL
) == 0) {
5305 vty_out(vty
, "%% Malformed ESI\n");
5306 return CMD_WARNING_CONFIG_FAILED
;
5308 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5309 vty_out(vty
, "%% Malformed Router MAC\n");
5310 return CMD_WARNING_CONFIG_FAILED
;
5313 memset(&gw_ip
, 0, sizeof(struct prefix
));
5314 ret
= str2prefix(gwip
, &gw_ip
);
5316 vty_out(vty
, "%% Malformed GatewayIp\n");
5317 return CMD_WARNING_CONFIG_FAILED
;
5319 if ((gw_ip
.family
== AF_INET
5320 && is_evpn_prefix_ipaddr_v6(
5321 (struct prefix_evpn
*)&p
))
5322 || (gw_ip
.family
== AF_INET6
5323 && is_evpn_prefix_ipaddr_v4(
5324 (struct prefix_evpn
*)&p
))) {
5326 "%% GatewayIp family differs with IP prefix\n");
5327 return CMD_WARNING_CONFIG_FAILED
;
5331 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5332 if (!bgp_node_has_bgp_path_info_data(prn
))
5333 bgp_node_set_bgp_table_info(prn
,
5334 bgp_table_init(bgp
, afi
, safi
));
5335 table
= bgp_node_get_bgp_table_info(prn
);
5337 rn
= bgp_node_get(table
, &p
);
5339 if (bgp_node_has_bgp_path_info_data(rn
)) {
5340 vty_out(vty
, "%% Same network configuration exists\n");
5341 bgp_unlock_node(rn
);
5343 /* New configuration. */
5344 bgp_static
= bgp_static_new();
5345 bgp_static
->backdoor
= 0;
5346 bgp_static
->valid
= 0;
5347 bgp_static
->igpmetric
= 0;
5348 bgp_static
->igpnexthop
.s_addr
= 0;
5349 bgp_static
->label
= label
;
5350 bgp_static
->prd
= prd
;
5353 if (bgp_static
->rmap
.name
)
5354 XFREE(MTYPE_ROUTE_MAP_NAME
,
5355 bgp_static
->rmap
.name
);
5356 route_map_counter_decrement(bgp_static
->rmap
.map
);
5357 bgp_static
->rmap
.name
=
5358 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5359 bgp_static
->rmap
.map
=
5360 route_map_lookup_by_name(rmap_str
);
5361 route_map_counter_increment(bgp_static
->rmap
.map
);
5364 if (safi
== SAFI_EVPN
) {
5366 bgp_static
->eth_s_id
=
5368 sizeof(struct eth_segment_id
));
5369 str2esi(esi
, bgp_static
->eth_s_id
);
5372 bgp_static
->router_mac
=
5373 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5374 (void)prefix_str2mac(routermac
,
5375 bgp_static
->router_mac
);
5378 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5380 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5382 bgp_static
->valid
= 1;
5383 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5389 /* Configure static BGP network. */
5390 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5391 const char *ip_str
, const char *rd_str
,
5392 const char *label_str
, int evpn_type
, const char *esi
,
5393 const char *gwip
, const char *ethtag
)
5395 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5398 struct prefix_rd prd
;
5399 struct bgp_node
*prn
;
5400 struct bgp_node
*rn
;
5401 struct bgp_table
*table
;
5402 struct bgp_static
*bgp_static
;
5403 mpls_label_t label
= MPLS_INVALID_LABEL
;
5405 /* Convert IP prefix string to struct prefix. */
5406 ret
= str2prefix(ip_str
, &p
);
5408 vty_out(vty
, "%% Malformed prefix\n");
5409 return CMD_WARNING_CONFIG_FAILED
;
5412 if ((afi
== AFI_L2VPN
)
5413 && (bgp_build_evpn_prefix(evpn_type
,
5414 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5415 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5416 return CMD_WARNING_CONFIG_FAILED
;
5418 ret
= str2prefix_rd(rd_str
, &prd
);
5420 vty_out(vty
, "%% Malformed rd\n");
5421 return CMD_WARNING_CONFIG_FAILED
;
5425 unsigned long label_val
;
5426 label_val
= strtoul(label_str
, NULL
, 10);
5427 encode_label(label_val
, &label
);
5430 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5431 if (!bgp_node_has_bgp_path_info_data(prn
))
5432 bgp_node_set_bgp_table_info(prn
,
5433 bgp_table_init(bgp
, afi
, safi
));
5435 bgp_unlock_node(prn
);
5436 table
= bgp_node_get_bgp_table_info(prn
);
5438 rn
= bgp_node_lookup(table
, &p
);
5441 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5443 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5444 bgp_static_free(bgp_static
);
5445 bgp_node_set_bgp_static_info(rn
, NULL
);
5446 bgp_unlock_node(rn
);
5447 bgp_unlock_node(rn
);
5449 vty_out(vty
, "%% Can't find the route\n");
5454 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5455 const char *rmap_name
)
5457 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5458 struct bgp_rmap
*rmap
;
5460 rmap
= &bgp
->table_map
[afi
][safi
];
5463 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5464 route_map_counter_decrement(rmap
->map
);
5465 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5466 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5467 route_map_counter_increment(rmap
->map
);
5470 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5471 route_map_counter_decrement(rmap
->map
);
5476 if (bgp_fibupd_safi(safi
))
5477 bgp_zebra_announce_table(bgp
, afi
, safi
);
5482 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5483 const char *rmap_name
)
5485 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5486 struct bgp_rmap
*rmap
;
5488 rmap
= &bgp
->table_map
[afi
][safi
];
5490 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5491 route_map_counter_decrement(rmap
->map
);
5495 if (bgp_fibupd_safi(safi
))
5496 bgp_zebra_announce_table(bgp
, afi
, safi
);
5501 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5504 if (bgp
->table_map
[afi
][safi
].name
) {
5505 vty_out(vty
, " table-map %s\n",
5506 bgp
->table_map
[afi
][safi
].name
);
5510 DEFUN (bgp_table_map
,
5513 "BGP table to RIB route download filter\n"
5514 "Name of the route map\n")
5517 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5518 argv
[idx_word
]->arg
);
5520 DEFUN (no_bgp_table_map
,
5521 no_bgp_table_map_cmd
,
5522 "no table-map WORD",
5524 "BGP table to RIB route download filter\n"
5525 "Name of the route map\n")
5528 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5529 argv
[idx_word
]->arg
);
5535 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5536 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5537 backdoor$backdoor}]",
5539 "Specify a network to announce via BGP\n"
5544 "Route-map to modify the attributes\n"
5545 "Name of the route map\n"
5546 "Label index to associate with the prefix\n"
5547 "Label index value\n"
5548 "Specify a BGP backdoor route\n")
5550 char addr_prefix_str
[BUFSIZ
];
5555 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5558 vty_out(vty
, "%% Inconsistent address and mask\n");
5559 return CMD_WARNING_CONFIG_FAILED
;
5563 return bgp_static_set(
5564 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5565 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5566 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5569 DEFPY(ipv6_bgp_network
,
5570 ipv6_bgp_network_cmd
,
5571 "[no] network X:X::X:X/M$prefix \
5572 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5574 "Specify a network to announce via BGP\n"
5576 "Route-map to modify the attributes\n"
5577 "Name of the route map\n"
5578 "Label index to associate with the prefix\n"
5579 "Label index value\n")
5581 return bgp_static_set(
5582 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5583 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5586 /* Aggreagete address:
5588 advertise-map Set condition to advertise attribute
5589 as-set Generate AS set path information
5590 attribute-map Set attributes of aggregate
5591 route-map Set parameters of aggregate
5592 summary-only Filter more specific routes from updates
5593 suppress-map Conditionally filter more specific routes from updates
5596 struct bgp_aggregate
{
5597 /* Summary-only flag. */
5598 uint8_t summary_only
;
5600 /* AS set generation. */
5603 /* Route-map for aggregated route. */
5604 struct route_map
*map
;
5606 /* Suppress-count. */
5607 unsigned long count
;
5609 /* SAFI configuration. */
5613 static struct bgp_aggregate
*bgp_aggregate_new(void)
5615 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5618 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5620 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5623 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5624 struct aspath
*aspath
,
5625 struct community
*comm
,
5626 struct ecommunity
*ecomm
,
5627 struct lcommunity
*lcomm
)
5629 static struct aspath
*ae
= NULL
;
5632 ae
= aspath_empty();
5637 if (origin
!= pi
->attr
->origin
)
5640 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5643 if (!community_cmp(pi
->attr
->community
, comm
))
5646 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5649 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5652 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5658 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5659 struct prefix
*p
, uint8_t origin
,
5660 struct aspath
*aspath
,
5661 struct community
*community
,
5662 struct ecommunity
*ecommunity
,
5663 struct lcommunity
*lcommunity
,
5664 uint8_t atomic_aggregate
,
5665 struct bgp_aggregate
*aggregate
)
5667 struct bgp_node
*rn
;
5668 struct bgp_table
*table
;
5669 struct bgp_path_info
*pi
, *orig
, *new;
5671 table
= bgp
->rib
[afi
][safi
];
5673 rn
= bgp_node_get(table
, p
);
5675 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5676 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5677 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5680 if (aggregate
->count
> 0) {
5682 * If the aggregate information has not changed
5683 * no need to re-install it again.
5685 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5686 ecommunity
, lcommunity
)) {
5687 bgp_unlock_node(rn
);
5690 aspath_free(aspath
);
5692 community_free(&community
);
5694 ecommunity_free(&ecommunity
);
5696 lcommunity_free(&lcommunity
);
5702 * Mark the old as unusable
5705 bgp_path_info_delete(rn
, pi
);
5707 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5709 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5710 community
, ecommunity
,
5715 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5717 bgp_path_info_add(rn
, new);
5718 bgp_process(bgp
, rn
, afi
, safi
);
5720 for (pi
= orig
; pi
; pi
= pi
->next
)
5721 if (pi
->peer
== bgp
->peer_self
5722 && pi
->type
== ZEBRA_ROUTE_BGP
5723 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5726 /* Withdraw static BGP route from routing table. */
5728 bgp_path_info_delete(rn
, pi
);
5729 bgp_process(bgp
, rn
, afi
, safi
);
5733 bgp_unlock_node(rn
);
5736 /* Update an aggregate as routes are added/removed from the BGP table */
5737 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5738 struct bgp_path_info
*pinew
, afi_t afi
,
5739 safi_t safi
, struct bgp_path_info
*del
,
5740 struct bgp_aggregate
*aggregate
)
5742 struct bgp_table
*table
;
5743 struct bgp_node
*top
;
5744 struct bgp_node
*rn
;
5746 struct aspath
*aspath
= NULL
;
5747 struct aspath
*asmerge
= NULL
;
5748 struct community
*community
= NULL
;
5749 struct community
*commerge
= NULL
;
5750 struct ecommunity
*ecommunity
= NULL
;
5751 struct ecommunity
*ecommerge
= NULL
;
5752 struct lcommunity
*lcommunity
= NULL
;
5753 struct lcommunity
*lcommerge
= NULL
;
5754 struct bgp_path_info
*pi
;
5755 unsigned long match
= 0;
5756 uint8_t atomic_aggregate
= 0;
5758 /* ORIGIN attribute: If at least one route among routes that are
5759 aggregated has ORIGIN with the value INCOMPLETE, then the
5760 aggregated route must have the ORIGIN attribute with the value
5761 INCOMPLETE. Otherwise, if at least one route among routes that
5762 are aggregated has ORIGIN with the value EGP, then the aggregated
5763 route must have the origin attribute with the value EGP. In all
5764 other case the value of the ORIGIN attribute of the aggregated
5765 route is INTERNAL. */
5766 origin
= BGP_ORIGIN_IGP
;
5768 table
= bgp
->rib
[afi
][safi
];
5770 top
= bgp_node_get(table
, p
);
5771 for (rn
= bgp_node_get(table
, p
); rn
;
5772 rn
= bgp_route_next_until(rn
, top
)) {
5773 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5778 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5779 if (BGP_PATH_HOLDDOWN(pi
))
5782 if (del
&& pi
== del
)
5786 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5787 atomic_aggregate
= 1;
5789 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5793 * summary-only aggregate route suppress
5794 * aggregated route announcements.
5796 if (aggregate
->summary_only
) {
5797 (bgp_path_info_extra_get(pi
))->suppress
++;
5798 bgp_path_info_set_flag(rn
, pi
,
5799 BGP_PATH_ATTR_CHANGED
);
5806 * If at least one route among routes that are
5807 * aggregated has ORIGIN with the value INCOMPLETE,
5808 * then the aggregated route MUST have the ORIGIN
5809 * attribute with the value INCOMPLETE. Otherwise, if
5810 * at least one route among routes that are aggregated
5811 * has ORIGIN with the value EGP, then the aggregated
5812 * route MUST have the ORIGIN attribute with the value
5815 if (origin
< pi
->attr
->origin
)
5816 origin
= pi
->attr
->origin
;
5818 if (!aggregate
->as_set
)
5822 * as-set aggregate route generate origin, as path,
5823 * and community aggregation.
5826 asmerge
= aspath_aggregate(aspath
,
5828 aspath_free(aspath
);
5831 aspath
= aspath_dup(pi
->attr
->aspath
);
5833 if (pi
->attr
->community
) {
5835 commerge
= community_merge(
5836 community
, pi
->attr
->community
);
5838 community_uniq_sort(commerge
);
5839 community_free(&commerge
);
5841 community
= community_dup(
5842 pi
->attr
->community
);
5845 if (pi
->attr
->ecommunity
) {
5847 ecommerge
= ecommunity_merge(
5849 pi
->attr
->ecommunity
);
5851 ecommunity_uniq_sort(ecommerge
);
5852 ecommunity_free(&ecommerge
);
5854 ecommunity
= ecommunity_dup(
5855 pi
->attr
->ecommunity
);
5858 if (pi
->attr
->lcommunity
) {
5860 lcommerge
= lcommunity_merge(
5862 pi
->attr
->lcommunity
);
5864 lcommunity_uniq_sort(lcommerge
);
5865 lcommunity_free(&lcommerge
);
5867 lcommunity
= lcommunity_dup(
5868 pi
->attr
->lcommunity
);
5872 bgp_process(bgp
, rn
, afi
, safi
);
5874 bgp_unlock_node(top
);
5879 if (aggregate
->summary_only
)
5880 (bgp_path_info_extra_get(pinew
))->suppress
++;
5882 if (origin
< pinew
->attr
->origin
)
5883 origin
= pinew
->attr
->origin
;
5885 if (aggregate
->as_set
) {
5887 asmerge
= aspath_aggregate(aspath
,
5888 pinew
->attr
->aspath
);
5889 aspath_free(aspath
);
5892 aspath
= aspath_dup(pinew
->attr
->aspath
);
5894 if (pinew
->attr
->community
) {
5896 commerge
= community_merge(
5898 pinew
->attr
->community
);
5900 community_uniq_sort(commerge
);
5901 community_free(&commerge
);
5903 community
= community_dup(
5904 pinew
->attr
->community
);
5907 if (pinew
->attr
->ecommunity
) {
5909 ecommerge
= ecommunity_merge(
5911 pinew
->attr
->ecommunity
);
5913 ecommunity_uniq_sort(ecommerge
);
5914 ecommunity_free(&ecommerge
);
5916 ecommunity
= ecommunity_dup(
5917 pinew
->attr
->ecommunity
);
5920 if (pinew
->attr
->lcommunity
) {
5922 lcommerge
= lcommunity_merge(
5924 pinew
->attr
->lcommunity
);
5926 lcommunity_uniq_sort(lcommerge
);
5927 lcommunity_free(&lcommerge
);
5929 lcommunity
= lcommunity_dup(
5930 pinew
->attr
->lcommunity
);
5935 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5936 ecommunity
, lcommunity
, atomic_aggregate
,
5939 if (aggregate
->count
== 0) {
5941 aspath_free(aspath
);
5943 community_free(&community
);
5945 ecommunity_free(&ecommunity
);
5947 lcommunity_free(&lcommunity
);
5951 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5952 safi_t safi
, struct bgp_aggregate
*aggregate
)
5954 struct bgp_table
*table
;
5955 struct bgp_node
*top
;
5956 struct bgp_node
*rn
;
5957 struct bgp_path_info
*pi
;
5958 unsigned long match
;
5960 table
= bgp
->rib
[afi
][safi
];
5962 /* If routes exists below this node, generate aggregate routes. */
5963 top
= bgp_node_get(table
, p
);
5964 for (rn
= bgp_node_get(table
, p
); rn
;
5965 rn
= bgp_route_next_until(rn
, top
)) {
5966 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5970 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5971 if (BGP_PATH_HOLDDOWN(pi
))
5974 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5977 if (aggregate
->summary_only
&& pi
->extra
) {
5978 pi
->extra
->suppress
--;
5980 if (pi
->extra
->suppress
== 0) {
5981 bgp_path_info_set_flag(
5982 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5989 /* If this node was suppressed, process the change. */
5991 bgp_process(bgp
, rn
, afi
, safi
);
5993 bgp_unlock_node(top
);
5996 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5997 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
5999 struct bgp_node
*child
;
6000 struct bgp_node
*rn
;
6001 struct bgp_aggregate
*aggregate
;
6002 struct bgp_table
*table
;
6004 table
= bgp
->aggregate
[afi
][safi
];
6006 /* No aggregates configured. */
6007 if (bgp_table_top_nolock(table
) == NULL
)
6010 if (p
->prefixlen
== 0)
6013 if (BGP_PATH_HOLDDOWN(pi
))
6016 child
= bgp_node_get(table
, p
);
6018 /* Aggregate address configuration check. */
6019 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6020 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6021 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6022 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
6023 bgp_aggregate_route(bgp
, &rn
->p
, pi
, afi
, safi
, NULL
,
6027 bgp_unlock_node(child
);
6030 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6031 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6033 struct bgp_node
*child
;
6034 struct bgp_node
*rn
;
6035 struct bgp_aggregate
*aggregate
;
6036 struct bgp_table
*table
;
6038 table
= bgp
->aggregate
[afi
][safi
];
6040 /* No aggregates configured. */
6041 if (bgp_table_top_nolock(table
) == NULL
)
6044 if (p
->prefixlen
== 0)
6047 child
= bgp_node_get(table
, p
);
6049 /* Aggregate address configuration check. */
6050 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6051 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6052 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6053 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
6054 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
6058 bgp_unlock_node(child
);
6061 /* Aggregate route attribute. */
6062 #define AGGREGATE_SUMMARY_ONLY 1
6063 #define AGGREGATE_AS_SET 1
6065 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6066 afi_t afi
, safi_t safi
)
6068 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6071 struct bgp_node
*rn
;
6072 struct bgp_aggregate
*aggregate
;
6074 /* Convert string to prefix structure. */
6075 ret
= str2prefix(prefix_str
, &p
);
6077 vty_out(vty
, "Malformed prefix\n");
6078 return CMD_WARNING_CONFIG_FAILED
;
6082 /* Old configuration check. */
6083 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6086 "%% There is no aggregate-address configuration.\n");
6087 return CMD_WARNING_CONFIG_FAILED
;
6090 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6091 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6092 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6093 NULL
, NULL
, 0, aggregate
);
6095 /* Unlock aggregate address configuration. */
6096 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6097 bgp_aggregate_free(aggregate
);
6098 bgp_unlock_node(rn
);
6099 bgp_unlock_node(rn
);
6104 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6105 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6107 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6110 struct bgp_node
*rn
;
6111 struct bgp_aggregate
*aggregate
;
6113 /* Convert string to prefix structure. */
6114 ret
= str2prefix(prefix_str
, &p
);
6116 vty_out(vty
, "Malformed prefix\n");
6117 return CMD_WARNING_CONFIG_FAILED
;
6121 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6122 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6123 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6125 return CMD_WARNING_CONFIG_FAILED
;
6128 /* Old configuration check. */
6129 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6131 if (bgp_node_has_bgp_path_info_data(rn
)) {
6132 vty_out(vty
, "There is already same aggregate network.\n");
6133 /* try to remove the old entry */
6134 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6136 vty_out(vty
, "Error deleting aggregate.\n");
6137 bgp_unlock_node(rn
);
6138 return CMD_WARNING_CONFIG_FAILED
;
6142 /* Make aggregate address structure. */
6143 aggregate
= bgp_aggregate_new();
6144 aggregate
->summary_only
= summary_only
;
6145 aggregate
->as_set
= as_set
;
6146 aggregate
->safi
= safi
;
6147 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6149 /* Aggregate address insert into BGP routing table. */
6150 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
6155 DEFUN (aggregate_address
,
6156 aggregate_address_cmd
,
6157 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6158 "Configure BGP aggregate entries\n"
6159 "Aggregate prefix\n"
6160 "Generate AS set path information\n"
6161 "Filter more specific routes from updates\n"
6162 "Filter more specific routes from updates\n"
6163 "Generate AS set path information\n")
6166 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6167 char *prefix
= argv
[idx
]->arg
;
6169 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6171 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6172 ? AGGREGATE_SUMMARY_ONLY
6175 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6176 summary_only
, as_set
);
6179 DEFUN (aggregate_address_mask
,
6180 aggregate_address_mask_cmd
,
6181 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6182 "Configure BGP aggregate entries\n"
6183 "Aggregate address\n"
6185 "Generate AS set path information\n"
6186 "Filter more specific routes from updates\n"
6187 "Filter more specific routes from updates\n"
6188 "Generate AS set path information\n")
6191 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6192 char *prefix
= argv
[idx
]->arg
;
6193 char *mask
= argv
[idx
+ 1]->arg
;
6195 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6197 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6198 ? AGGREGATE_SUMMARY_ONLY
6201 char prefix_str
[BUFSIZ
];
6202 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6205 vty_out(vty
, "%% Inconsistent address and mask\n");
6206 return CMD_WARNING_CONFIG_FAILED
;
6209 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6210 summary_only
, as_set
);
6213 DEFUN (no_aggregate_address
,
6214 no_aggregate_address_cmd
,
6215 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6217 "Configure BGP aggregate entries\n"
6218 "Aggregate prefix\n"
6219 "Generate AS set path information\n"
6220 "Filter more specific routes from updates\n"
6221 "Filter more specific routes from updates\n"
6222 "Generate AS set path information\n")
6225 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6226 char *prefix
= argv
[idx
]->arg
;
6227 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6230 DEFUN (no_aggregate_address_mask
,
6231 no_aggregate_address_mask_cmd
,
6232 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6234 "Configure BGP aggregate entries\n"
6235 "Aggregate address\n"
6237 "Generate AS set path information\n"
6238 "Filter more specific routes from updates\n"
6239 "Filter more specific routes from updates\n"
6240 "Generate AS set path information\n")
6243 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6244 char *prefix
= argv
[idx
]->arg
;
6245 char *mask
= argv
[idx
+ 1]->arg
;
6247 char prefix_str
[BUFSIZ
];
6248 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6251 vty_out(vty
, "%% Inconsistent address and mask\n");
6252 return CMD_WARNING_CONFIG_FAILED
;
6255 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6258 DEFUN (ipv6_aggregate_address
,
6259 ipv6_aggregate_address_cmd
,
6260 "aggregate-address X:X::X:X/M [summary-only]",
6261 "Configure BGP aggregate entries\n"
6262 "Aggregate prefix\n"
6263 "Filter more specific routes from updates\n")
6266 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6267 char *prefix
= argv
[idx
]->arg
;
6268 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6269 ? AGGREGATE_SUMMARY_ONLY
6271 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6275 DEFUN (no_ipv6_aggregate_address
,
6276 no_ipv6_aggregate_address_cmd
,
6277 "no aggregate-address X:X::X:X/M [summary-only]",
6279 "Configure BGP aggregate entries\n"
6280 "Aggregate prefix\n"
6281 "Filter more specific routes from updates\n")
6284 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6285 char *prefix
= argv
[idx
]->arg
;
6286 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6289 /* Redistribute route treatment. */
6290 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6291 const union g_addr
*nexthop
, ifindex_t ifindex
,
6292 enum nexthop_types_t nhtype
, uint32_t metric
,
6293 uint8_t type
, unsigned short instance
,
6296 struct bgp_path_info
*new;
6297 struct bgp_path_info
*bpi
;
6298 struct bgp_path_info rmap_path
;
6299 struct bgp_node
*bn
;
6301 struct attr
*new_attr
;
6304 struct bgp_redist
*red
;
6306 /* Make default attribute. */
6307 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6310 case NEXTHOP_TYPE_IFINDEX
:
6312 case NEXTHOP_TYPE_IPV4
:
6313 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6314 attr
.nexthop
= nexthop
->ipv4
;
6316 case NEXTHOP_TYPE_IPV6
:
6317 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6318 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6319 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6321 case NEXTHOP_TYPE_BLACKHOLE
:
6322 switch (p
->family
) {
6324 attr
.nexthop
.s_addr
= INADDR_ANY
;
6327 memset(&attr
.mp_nexthop_global
, 0,
6328 sizeof(attr
.mp_nexthop_global
));
6329 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6334 attr
.nh_ifindex
= ifindex
;
6337 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6340 afi
= family2afi(p
->family
);
6342 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6344 struct attr attr_new
;
6346 /* Copy attribute for modification. */
6347 bgp_attr_dup(&attr_new
, &attr
);
6349 if (red
->redist_metric_flag
)
6350 attr_new
.med
= red
->redist_metric
;
6352 /* Apply route-map. */
6353 if (red
->rmap
.name
) {
6354 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6355 rmap_path
.peer
= bgp
->peer_self
;
6356 rmap_path
.attr
= &attr_new
;
6358 SET_FLAG(bgp
->peer_self
->rmap_type
,
6359 PEER_RMAP_TYPE_REDISTRIBUTE
);
6361 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6364 bgp
->peer_self
->rmap_type
= 0;
6366 if (ret
== RMAP_DENYMATCH
) {
6367 /* Free uninterned attribute. */
6368 bgp_attr_flush(&attr_new
);
6370 /* Unintern original. */
6371 aspath_unintern(&attr
.aspath
);
6372 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6377 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6378 bgp_attr_add_gshut_community(&attr_new
);
6380 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6381 SAFI_UNICAST
, p
, NULL
);
6383 new_attr
= bgp_attr_intern(&attr_new
);
6385 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6387 if (bpi
->peer
== bgp
->peer_self
6388 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6392 /* Ensure the (source route) type is updated. */
6394 if (attrhash_cmp(bpi
->attr
, new_attr
)
6395 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6396 bgp_attr_unintern(&new_attr
);
6397 aspath_unintern(&attr
.aspath
);
6398 bgp_unlock_node(bn
);
6401 /* The attribute is changed. */
6402 bgp_path_info_set_flag(bn
, bpi
,
6403 BGP_PATH_ATTR_CHANGED
);
6405 /* Rewrite BGP route information. */
6406 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6407 bgp_path_info_restore(bn
, bpi
);
6409 bgp_aggregate_decrement(
6410 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6411 bgp_attr_unintern(&bpi
->attr
);
6412 bpi
->attr
= new_attr
;
6413 bpi
->uptime
= bgp_clock();
6415 /* Process change. */
6416 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6418 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6419 bgp_unlock_node(bn
);
6420 aspath_unintern(&attr
.aspath
);
6422 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6424 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6426 vpn_leak_from_vrf_update(
6427 bgp_get_default(), bgp
, bpi
);
6433 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6434 bgp
->peer_self
, new_attr
, bn
);
6435 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6437 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6438 bgp_path_info_add(bn
, new);
6439 bgp_unlock_node(bn
);
6440 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6442 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6443 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6445 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6449 /* Unintern original. */
6450 aspath_unintern(&attr
.aspath
);
6453 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6454 unsigned short instance
)
6457 struct bgp_node
*rn
;
6458 struct bgp_path_info
*pi
;
6459 struct bgp_redist
*red
;
6461 afi
= family2afi(p
->family
);
6463 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6465 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6466 SAFI_UNICAST
, p
, NULL
);
6468 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6469 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6473 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6474 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6476 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6479 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6480 bgp_path_info_delete(rn
, pi
);
6481 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6483 bgp_unlock_node(rn
);
6487 /* Withdraw specified route type's route. */
6488 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6489 unsigned short instance
)
6491 struct bgp_node
*rn
;
6492 struct bgp_path_info
*pi
;
6493 struct bgp_table
*table
;
6495 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6497 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6498 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6499 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6500 && pi
->instance
== instance
)
6504 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6505 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6507 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6510 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6512 bgp_path_info_delete(rn
, pi
);
6513 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6518 /* Static function to display route. */
6519 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6526 if (p
->family
== AF_INET
) {
6530 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6533 json_object_string_add(json
, "prefix",
6534 inet_ntop(p
->family
,
6537 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6538 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6539 json_object_string_add(json
, "network", buf2
);
6541 } else if (p
->family
== AF_ETHERNET
) {
6542 prefix2str(p
, buf
, PREFIX_STRLEN
);
6543 len
= vty_out(vty
, "%s", buf
);
6544 } else if (p
->family
== AF_EVPN
) {
6548 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6551 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6552 } else if (p
->family
== AF_FLOWSPEC
) {
6553 route_vty_out_flowspec(vty
, p
, NULL
,
6555 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6556 NLRI_STRING_FORMAT_MIN
, json
);
6561 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6564 json_object_string_add(json
, "prefix",
6565 inet_ntop(p
->family
,
6568 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6569 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6570 json_object_string_add(json
, "network", buf2
);
6577 vty_out(vty
, "\n%*s", 20, " ");
6579 vty_out(vty
, "%*s", len
, " ");
6583 enum bgp_display_type
{
6587 /* Print the short form route status for a bgp_path_info */
6588 static void route_vty_short_status_out(struct vty
*vty
,
6589 struct bgp_path_info
*path
,
6590 json_object
*json_path
)
6594 /* Route status display. */
6595 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6596 json_object_boolean_true_add(json_path
, "removed");
6598 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6599 json_object_boolean_true_add(json_path
, "stale");
6601 if (path
->extra
&& path
->extra
->suppress
)
6602 json_object_boolean_true_add(json_path
, "suppressed");
6604 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6605 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6606 json_object_boolean_true_add(json_path
, "valid");
6609 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6610 json_object_boolean_true_add(json_path
, "history");
6612 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6613 json_object_boolean_true_add(json_path
, "damped");
6615 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6616 json_object_boolean_true_add(json_path
, "bestpath");
6618 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6619 json_object_boolean_true_add(json_path
, "multipath");
6621 /* Internal route. */
6622 if ((path
->peer
->as
)
6623 && (path
->peer
->as
== path
->peer
->local_as
))
6624 json_object_string_add(json_path
, "pathFrom",
6627 json_object_string_add(json_path
, "pathFrom",
6633 /* Route status display. */
6634 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6636 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6638 else if (path
->extra
&& path
->extra
->suppress
)
6640 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6641 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6647 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6649 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6651 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6653 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6658 /* Internal route. */
6659 if (path
->peer
&& (path
->peer
->as
)
6660 && (path
->peer
->as
== path
->peer
->local_as
))
6666 /* called from terminal list command */
6667 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6668 struct bgp_path_info
*path
, int display
, safi_t safi
,
6669 json_object
*json_paths
)
6672 json_object
*json_path
= NULL
;
6673 json_object
*json_nexthops
= NULL
;
6674 json_object
*json_nexthop_global
= NULL
;
6675 json_object
*json_nexthop_ll
= NULL
;
6676 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6678 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6679 bool nexthop_othervrf
= false;
6680 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6681 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6684 json_path
= json_object_new_object();
6686 /* short status lead text */
6687 route_vty_short_status_out(vty
, path
, json_path
);
6690 /* print prefix and mask */
6692 route_vty_out_route(p
, vty
, json_path
);
6694 vty_out(vty
, "%*s", 17, " ");
6696 route_vty_out_route(p
, vty
, json_path
);
6699 /* Print attribute */
6703 json_object_array_add(json_paths
, json_path
);
6711 * If vrf id of nexthop is different from that of prefix,
6712 * set up printable string to append
6714 if (path
->extra
&& path
->extra
->bgp_orig
) {
6715 const char *self
= "";
6720 nexthop_othervrf
= true;
6721 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6723 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6724 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6725 "@%s%s", VRFID_NONE_STR
, self
);
6727 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6728 path
->extra
->bgp_orig
->vrf_id
, self
);
6730 if (path
->extra
->bgp_orig
->inst_type
6731 != BGP_INSTANCE_TYPE_DEFAULT
)
6733 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6735 const char *self
= "";
6740 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6744 * For ENCAP and EVPN routes, nexthop address family is not
6745 * neccessarily the same as the prefix address family.
6746 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6747 * EVPN routes are also exchanged with a MP nexthop. Currently,
6749 * is only IPv4, the value will be present in either
6751 * attr->mp_nexthop_global_in
6753 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6756 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6760 sprintf(nexthop
, "%s",
6761 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6765 sprintf(nexthop
, "%s",
6766 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6770 sprintf(nexthop
, "?");
6775 json_nexthop_global
= json_object_new_object();
6777 json_object_string_add(json_nexthop_global
, "afi",
6778 (af
== AF_INET
) ? "ip" : "ipv6");
6779 json_object_string_add(json_nexthop_global
,
6780 (af
== AF_INET
) ? "ip" : "ipv6",
6782 json_object_boolean_true_add(json_nexthop_global
,
6785 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6786 } else if (safi
== SAFI_EVPN
) {
6788 json_nexthop_global
= json_object_new_object();
6790 json_object_string_add(json_nexthop_global
, "ip",
6791 inet_ntoa(attr
->nexthop
));
6792 json_object_string_add(json_nexthop_global
, "afi",
6794 json_object_boolean_true_add(json_nexthop_global
,
6797 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6799 } else if (safi
== SAFI_FLOWSPEC
) {
6800 if (attr
->nexthop
.s_addr
!= 0) {
6802 json_nexthop_global
= json_object_new_object();
6803 json_object_string_add(
6804 json_nexthop_global
, "ip",
6805 inet_ntoa(attr
->nexthop
));
6806 json_object_string_add(json_nexthop_global
,
6808 json_object_boolean_true_add(
6809 json_nexthop_global
,
6812 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6815 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6817 json_nexthop_global
= json_object_new_object();
6819 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6820 json_object_string_add(
6821 json_nexthop_global
, "ip",
6822 inet_ntoa(attr
->mp_nexthop_global_in
));
6824 json_object_string_add(
6825 json_nexthop_global
, "ip",
6826 inet_ntoa(attr
->nexthop
));
6828 json_object_string_add(json_nexthop_global
, "afi",
6830 json_object_boolean_true_add(json_nexthop_global
,
6835 snprintf(buf
, sizeof(buf
), "%s%s",
6836 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6837 vty_out(vty
, "%-16s", buf
);
6842 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6847 json_nexthop_global
= json_object_new_object();
6848 json_object_string_add(
6849 json_nexthop_global
, "ip",
6850 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6852 json_object_string_add(json_nexthop_global
, "afi",
6854 json_object_string_add(json_nexthop_global
, "scope",
6857 /* We display both LL & GL if both have been
6859 if ((attr
->mp_nexthop_len
== 32)
6860 || (path
->peer
->conf_if
)) {
6861 json_nexthop_ll
= json_object_new_object();
6862 json_object_string_add(
6863 json_nexthop_ll
, "ip",
6865 &attr
->mp_nexthop_local
, buf
,
6867 json_object_string_add(json_nexthop_ll
, "afi",
6869 json_object_string_add(json_nexthop_ll
, "scope",
6872 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6873 &attr
->mp_nexthop_local
)
6875 && !attr
->mp_nexthop_prefer_global
)
6876 json_object_boolean_true_add(
6877 json_nexthop_ll
, "used");
6879 json_object_boolean_true_add(
6880 json_nexthop_global
, "used");
6882 json_object_boolean_true_add(
6883 json_nexthop_global
, "used");
6885 /* Display LL if LL/Global both in table unless
6886 * prefer-global is set */
6887 if (((attr
->mp_nexthop_len
== 32)
6888 && !attr
->mp_nexthop_prefer_global
)
6889 || (path
->peer
->conf_if
)) {
6890 if (path
->peer
->conf_if
) {
6891 len
= vty_out(vty
, "%s",
6892 path
->peer
->conf_if
);
6893 len
= 16 - len
; /* len of IPv6
6899 vty_out(vty
, "\n%*s", 36, " ");
6901 vty_out(vty
, "%*s", len
, " ");
6907 &attr
->mp_nexthop_local
,
6913 vty_out(vty
, "\n%*s", 36, " ");
6915 vty_out(vty
, "%*s", len
, " ");
6921 &attr
->mp_nexthop_global
, buf
,
6927 vty_out(vty
, "\n%*s", 36, " ");
6929 vty_out(vty
, "%*s", len
, " ");
6935 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6939 * Adding "metric" field to match with corresponding
6940 * CLI. "med" will be deprecated in future.
6942 json_object_int_add(json_path
, "med", attr
->med
);
6943 json_object_int_add(json_path
, "metric", attr
->med
);
6945 vty_out(vty
, "%10u", attr
->med
);
6946 else if (!json_paths
)
6950 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6954 * Adding "locPrf" field to match with corresponding
6955 * CLI. "localPref" will be deprecated in future.
6957 json_object_int_add(json_path
, "localpref",
6959 json_object_int_add(json_path
, "locPrf",
6962 vty_out(vty
, "%7u", attr
->local_pref
);
6963 else if (!json_paths
)
6967 json_object_int_add(json_path
, "weight", attr
->weight
);
6969 vty_out(vty
, "%7u ", attr
->weight
);
6973 json_object_string_add(
6974 json_path
, "peerId",
6975 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6983 * Adding "path" field to match with corresponding
6984 * CLI. "aspath" will be deprecated in future.
6986 json_object_string_add(json_path
, "aspath",
6988 json_object_string_add(json_path
, "path",
6991 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6996 json_object_string_add(json_path
, "origin",
6997 bgp_origin_long_str
[attr
->origin
]);
6999 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7003 json_object_boolean_true_add(json_path
,
7004 "announceNexthopSelf");
7005 if (nexthop_othervrf
) {
7006 json_object_string_add(json_path
, "nhVrfName",
7009 json_object_int_add(json_path
, "nhVrfId",
7010 ((nexthop_vrfid
== VRF_UNKNOWN
)
7012 : (int)nexthop_vrfid
));
7017 if (json_nexthop_global
|| json_nexthop_ll
) {
7018 json_nexthops
= json_object_new_array();
7020 if (json_nexthop_global
)
7021 json_object_array_add(json_nexthops
,
7022 json_nexthop_global
);
7024 if (json_nexthop_ll
)
7025 json_object_array_add(json_nexthops
,
7028 json_object_object_add(json_path
, "nexthops",
7032 json_object_array_add(json_paths
, json_path
);
7036 /* prints an additional line, indented, with VNC info, if
7038 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7039 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7044 /* called from terminal list command */
7045 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7046 safi_t safi
, bool use_json
, json_object
*json_ar
)
7048 json_object
*json_status
= NULL
;
7049 json_object
*json_net
= NULL
;
7052 /* Route status display. */
7054 json_status
= json_object_new_object();
7055 json_net
= json_object_new_object();
7062 /* print prefix and mask */
7064 json_object_string_add(
7065 json_net
, "addrPrefix",
7066 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
7067 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
7068 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7069 json_object_string_add(json_net
, "network", buf2
);
7071 route_vty_out_route(p
, vty
, NULL
);
7073 /* Print attribute */
7076 if (p
->family
== AF_INET
7077 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7078 || safi
== SAFI_EVPN
7079 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7080 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7081 || safi
== SAFI_EVPN
)
7082 json_object_string_add(
7083 json_net
, "nextHop",
7085 attr
->mp_nexthop_global_in
));
7087 json_object_string_add(
7088 json_net
, "nextHop",
7089 inet_ntoa(attr
->nexthop
));
7090 } else if (p
->family
== AF_INET6
7091 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7094 json_object_string_add(
7095 json_net
, "nextHopGlobal",
7097 &attr
->mp_nexthop_global
, buf
,
7102 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7103 json_object_int_add(json_net
, "metric",
7106 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7109 * Adding "locPrf" field to match with
7110 * corresponding CLI. "localPref" will be
7111 * deprecated in future.
7113 json_object_int_add(json_net
, "localPref",
7115 json_object_int_add(json_net
, "locPrf",
7119 json_object_int_add(json_net
, "weight", attr
->weight
);
7125 * Adding "path" field to match with
7126 * corresponding CLI. "localPref" will be
7127 * deprecated in future.
7129 json_object_string_add(json_net
, "asPath",
7131 json_object_string_add(json_net
, "path",
7136 json_object_string_add(json_net
, "bgpOriginCode",
7137 bgp_origin_str
[attr
->origin
]);
7139 if (p
->family
== AF_INET
7140 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7141 || safi
== SAFI_EVPN
7142 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7143 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7144 || safi
== SAFI_EVPN
)
7145 vty_out(vty
, "%-16s",
7147 attr
->mp_nexthop_global_in
));
7149 vty_out(vty
, "%-16s",
7150 inet_ntoa(attr
->nexthop
));
7151 } else if (p
->family
== AF_INET6
7152 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7159 &attr
->mp_nexthop_global
, buf
,
7163 vty_out(vty
, "\n%*s", 36, " ");
7165 vty_out(vty
, "%*s", len
, " ");
7168 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7169 vty_out(vty
, "%10u", attr
->med
);
7173 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7174 vty_out(vty
, "%7u", attr
->local_pref
);
7178 vty_out(vty
, "%7u ", attr
->weight
);
7182 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7185 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7189 json_object_boolean_true_add(json_status
, "*");
7190 json_object_boolean_true_add(json_status
, ">");
7191 json_object_object_add(json_net
, "appliedStatusSymbols",
7193 char buf_cut
[BUFSIZ
];
7194 json_object_object_add(
7196 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7202 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7203 struct bgp_path_info
*path
, int display
, safi_t safi
,
7206 json_object
*json_out
= NULL
;
7208 mpls_label_t label
= MPLS_INVALID_LABEL
;
7214 json_out
= json_object_new_object();
7216 /* short status lead text */
7217 route_vty_short_status_out(vty
, path
, json_out
);
7219 /* print prefix and mask */
7222 route_vty_out_route(p
, vty
, NULL
);
7224 vty_out(vty
, "%*s", 17, " ");
7227 /* Print attribute */
7230 if (((p
->family
== AF_INET
)
7231 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7232 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7233 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7234 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7235 || safi
== SAFI_EVPN
) {
7237 json_object_string_add(
7238 json_out
, "mpNexthopGlobalIn",
7240 attr
->mp_nexthop_global_in
));
7242 vty_out(vty
, "%-16s",
7244 attr
->mp_nexthop_global_in
));
7247 json_object_string_add(
7248 json_out
, "nexthop",
7249 inet_ntoa(attr
->nexthop
));
7251 vty_out(vty
, "%-16s",
7252 inet_ntoa(attr
->nexthop
));
7254 } else if (((p
->family
== AF_INET6
)
7255 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7256 || (safi
== SAFI_EVPN
7257 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7258 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7262 if (attr
->mp_nexthop_len
7263 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7265 json_object_string_add(
7266 json_out
, "mpNexthopGlobalIn",
7269 &attr
->mp_nexthop_global
,
7270 buf_a
, sizeof(buf_a
)));
7275 &attr
->mp_nexthop_global
,
7276 buf_a
, sizeof(buf_a
)));
7277 } else if (attr
->mp_nexthop_len
7278 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7281 &attr
->mp_nexthop_global
,
7282 buf_a
, sizeof(buf_a
));
7284 &attr
->mp_nexthop_local
,
7285 buf_b
, sizeof(buf_b
));
7286 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7287 json_object_string_add(
7289 "mpNexthopGlobalLocal", buf_c
);
7291 vty_out(vty
, "%s(%s)",
7294 &attr
->mp_nexthop_global
,
7295 buf_a
, sizeof(buf_a
)),
7298 &attr
->mp_nexthop_local
,
7299 buf_b
, sizeof(buf_b
)));
7304 label
= decode_label(&path
->extra
->label
[0]);
7306 if (bgp_is_valid_label(&label
)) {
7308 json_object_int_add(json_out
, "notag", label
);
7309 json_object_array_add(json
, json_out
);
7311 vty_out(vty
, "notag/%d", label
);
7317 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7318 struct bgp_path_info
*path
, int display
,
7319 json_object
*json_paths
)
7323 json_object
*json_path
= NULL
;
7326 json_path
= json_object_new_object();
7331 /* short status lead text */
7332 route_vty_short_status_out(vty
, path
, json_path
);
7334 /* print prefix and mask */
7336 route_vty_out_route(p
, vty
, NULL
);
7338 vty_out(vty
, "%*s", 17, " ");
7340 /* Print attribute */
7344 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7348 vty_out(vty
, "%-16s",
7349 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7353 vty_out(vty
, "%s(%s)",
7354 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7356 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7363 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7365 vty_out(vty
, "%s", str
);
7366 XFREE(MTYPE_TMP
, str
);
7368 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7370 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7371 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7374 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7377 if (attr
->ecommunity
) {
7379 struct ecommunity_val
*routermac
= ecommunity_lookup(
7380 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7381 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7383 mac
= ecom_mac2str((char *)routermac
->val
);
7385 vty_out(vty
, "/%s", (char *)mac
);
7386 XFREE(MTYPE_TMP
, mac
);
7394 /* dampening route */
7395 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7396 struct bgp_path_info
*path
, int display
,
7397 safi_t safi
, bool use_json
, json_object
*json
)
7401 char timebuf
[BGP_UPTIME_LEN
];
7403 /* short status lead text */
7404 route_vty_short_status_out(vty
, path
, json
);
7406 /* print prefix and mask */
7409 route_vty_out_route(p
, vty
, NULL
);
7411 vty_out(vty
, "%*s", 17, " ");
7414 len
= vty_out(vty
, "%s", path
->peer
->host
);
7418 vty_out(vty
, "\n%*s", 34, " ");
7421 json_object_int_add(json
, "peerHost", len
);
7423 vty_out(vty
, "%*s", len
, " ");
7427 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7431 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7432 BGP_UPTIME_LEN
, use_json
,
7435 /* Print attribute */
7441 json_object_string_add(json
, "asPath",
7444 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7449 json_object_string_add(json
, "origin",
7450 bgp_origin_str
[attr
->origin
]);
7452 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7459 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7460 struct bgp_path_info
*path
, int display
,
7461 safi_t safi
, bool use_json
, json_object
*json
)
7464 struct bgp_damp_info
*bdi
;
7465 char timebuf
[BGP_UPTIME_LEN
];
7471 bdi
= path
->extra
->damp_info
;
7473 /* short status lead text */
7474 route_vty_short_status_out(vty
, path
, json
);
7476 /* print prefix and mask */
7479 route_vty_out_route(p
, vty
, NULL
);
7481 vty_out(vty
, "%*s", 17, " ");
7484 len
= vty_out(vty
, "%s", path
->peer
->host
);
7488 vty_out(vty
, "\n%*s", 33, " ");
7491 json_object_int_add(json
, "peerHost", len
);
7493 vty_out(vty
, "%*s", len
, " ");
7496 len
= vty_out(vty
, "%d", bdi
->flap
);
7503 json_object_int_add(json
, "bdiFlap", len
);
7505 vty_out(vty
, "%*s", len
, " ");
7509 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7512 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7513 BGP_UPTIME_LEN
, 0, NULL
));
7515 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7516 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7518 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7519 BGP_UPTIME_LEN
, use_json
, json
);
7522 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7527 vty_out(vty
, "%*s ", 8, " ");
7530 /* Print attribute */
7536 json_object_string_add(json
, "asPath",
7539 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7544 json_object_string_add(json
, "origin",
7545 bgp_origin_str
[attr
->origin
]);
7547 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7553 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7554 int *first
, const char *header
,
7555 json_object
*json_adv_to
)
7557 char buf1
[INET6_ADDRSTRLEN
];
7558 json_object
*json_peer
= NULL
;
7561 /* 'advertised-to' is a dictionary of peers we have advertised
7563 * prefix too. The key is the peer's IP or swpX, the value is
7565 * hostname if we know it and "" if not.
7567 json_peer
= json_object_new_object();
7570 json_object_string_add(json_peer
, "hostname",
7574 json_object_object_add(json_adv_to
, peer
->conf_if
,
7577 json_object_object_add(
7579 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7583 vty_out(vty
, "%s", header
);
7588 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7590 vty_out(vty
, " %s(%s)", peer
->hostname
,
7593 vty_out(vty
, " %s(%s)", peer
->hostname
,
7594 sockunion2str(&peer
->su
, buf1
,
7598 vty_out(vty
, " %s", peer
->conf_if
);
7601 sockunion2str(&peer
->su
, buf1
,
7607 static void route_vty_out_tx_ids(struct vty
*vty
,
7608 struct bgp_addpath_info_data
*d
)
7612 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7613 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7614 d
->addpath_tx_id
[i
],
7615 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7619 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7620 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7621 json_object
*json_paths
)
7623 char buf
[INET6_ADDRSTRLEN
];
7625 char buf2
[EVPN_ROUTE_STRLEN
];
7627 int sockunion_vty_out(struct vty
*, union sockunion
*);
7629 json_object
*json_bestpath
= NULL
;
7630 json_object
*json_cluster_list
= NULL
;
7631 json_object
*json_cluster_list_list
= NULL
;
7632 json_object
*json_ext_community
= NULL
;
7633 json_object
*json_last_update
= NULL
;
7634 json_object
*json_pmsi
= NULL
;
7635 json_object
*json_nexthop_global
= NULL
;
7636 json_object
*json_nexthop_ll
= NULL
;
7637 json_object
*json_nexthops
= NULL
;
7638 json_object
*json_path
= NULL
;
7639 json_object
*json_peer
= NULL
;
7640 json_object
*json_string
= NULL
;
7641 json_object
*json_adv_to
= NULL
;
7643 struct listnode
*node
, *nnode
;
7645 int addpath_capable
;
7647 unsigned int first_as
;
7649 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7653 json_path
= json_object_new_object();
7654 json_peer
= json_object_new_object();
7655 json_nexthop_global
= json_object_new_object();
7658 if (!json_paths
&& safi
== SAFI_EVPN
) {
7661 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7662 vty_out(vty
, " Route %s", buf2
);
7664 if (path
->extra
&& path
->extra
->num_labels
) {
7665 bgp_evpn_label2str(path
->extra
->label
,
7666 path
->extra
->num_labels
, tag_buf
,
7668 vty_out(vty
, " VNI %s", tag_buf
);
7671 if (path
->extra
&& path
->extra
->parent
) {
7672 struct bgp_path_info
*parent_ri
;
7673 struct bgp_node
*rn
, *prn
;
7675 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7676 rn
= parent_ri
->net
;
7677 if (rn
&& rn
->prn
) {
7679 vty_out(vty
, " Imported from %s:%s\n",
7681 (struct prefix_rd
*)&prn
->p
,
7682 buf1
, sizeof(buf1
)),
7691 /* Line1 display AS-path, Aggregator */
7694 if (!attr
->aspath
->json
)
7695 aspath_str_update(attr
->aspath
, true);
7696 json_object_lock(attr
->aspath
->json
);
7697 json_object_object_add(json_path
, "aspath",
7698 attr
->aspath
->json
);
7700 if (attr
->aspath
->segments
)
7701 aspath_print_vty(vty
, " %s",
7704 vty_out(vty
, " Local");
7708 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7710 json_object_boolean_true_add(json_path
,
7713 vty_out(vty
, ", (removed)");
7716 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7718 json_object_boolean_true_add(json_path
,
7721 vty_out(vty
, ", (stale)");
7724 if (CHECK_FLAG(attr
->flag
,
7725 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7727 json_object_int_add(json_path
, "aggregatorAs",
7728 attr
->aggregator_as
);
7729 json_object_string_add(
7730 json_path
, "aggregatorId",
7731 inet_ntoa(attr
->aggregator_addr
));
7733 vty_out(vty
, ", (aggregated by %u %s)",
7734 attr
->aggregator_as
,
7735 inet_ntoa(attr
->aggregator_addr
));
7739 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7740 PEER_FLAG_REFLECTOR_CLIENT
)) {
7742 json_object_boolean_true_add(
7743 json_path
, "rxedFromRrClient");
7745 vty_out(vty
, ", (Received from a RR-client)");
7748 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7749 PEER_FLAG_RSERVER_CLIENT
)) {
7751 json_object_boolean_true_add(
7752 json_path
, "rxedFromRsClient");
7754 vty_out(vty
, ", (Received from a RS-client)");
7757 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7759 json_object_boolean_true_add(
7760 json_path
, "dampeningHistoryEntry");
7762 vty_out(vty
, ", (history entry)");
7763 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
7765 json_object_boolean_true_add(
7766 json_path
, "dampeningSuppressed");
7768 vty_out(vty
, ", (suppressed due to dampening)");
7774 /* Line2 display Next-hop, Neighbor, Router-id */
7775 /* Display the nexthop */
7776 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7777 || p
->family
== AF_EVPN
)
7778 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7779 || safi
== SAFI_EVPN
7780 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7781 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7782 || safi
== SAFI_EVPN
) {
7784 json_object_string_add(
7785 json_nexthop_global
, "ip",
7787 attr
->mp_nexthop_global_in
));
7791 attr
->mp_nexthop_global_in
));
7794 json_object_string_add(
7795 json_nexthop_global
, "ip",
7796 inet_ntoa(attr
->nexthop
));
7799 inet_ntoa(attr
->nexthop
));
7803 json_object_string_add(json_nexthop_global
,
7807 json_object_string_add(
7808 json_nexthop_global
, "ip",
7810 &attr
->mp_nexthop_global
, buf
,
7812 json_object_string_add(json_nexthop_global
,
7814 json_object_string_add(json_nexthop_global
,
7819 &attr
->mp_nexthop_global
, buf
,
7824 /* Display the IGP cost or 'inaccessible' */
7825 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
7827 json_object_boolean_false_add(
7828 json_nexthop_global
, "accessible");
7830 vty_out(vty
, " (inaccessible)");
7832 if (path
->extra
&& path
->extra
->igpmetric
) {
7834 json_object_int_add(
7835 json_nexthop_global
, "metric",
7836 path
->extra
->igpmetric
);
7838 vty_out(vty
, " (metric %u)",
7839 path
->extra
->igpmetric
);
7842 /* IGP cost is 0, display this only for json */
7845 json_object_int_add(json_nexthop_global
,
7850 json_object_boolean_true_add(
7851 json_nexthop_global
, "accessible");
7854 /* Display peer "from" output */
7855 /* This path was originated locally */
7856 if (path
->peer
== bgp
->peer_self
) {
7858 if (safi
== SAFI_EVPN
7859 || (p
->family
== AF_INET
7860 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7862 json_object_string_add(
7863 json_peer
, "peerId", "0.0.0.0");
7865 vty_out(vty
, " from 0.0.0.0 ");
7868 json_object_string_add(json_peer
,
7871 vty_out(vty
, " from :: ");
7875 json_object_string_add(
7876 json_peer
, "routerId",
7877 inet_ntoa(bgp
->router_id
));
7879 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7882 /* We RXed this path from one of our peers */
7886 json_object_string_add(
7887 json_peer
, "peerId",
7888 sockunion2str(&path
->peer
->su
, buf
,
7890 json_object_string_add(
7891 json_peer
, "routerId",
7893 &path
->peer
->remote_id
, buf1
,
7896 if (path
->peer
->hostname
)
7897 json_object_string_add(
7898 json_peer
, "hostname",
7899 path
->peer
->hostname
);
7901 if (path
->peer
->domainname
)
7902 json_object_string_add(
7903 json_peer
, "domainname",
7904 path
->peer
->domainname
);
7906 if (path
->peer
->conf_if
)
7907 json_object_string_add(
7908 json_peer
, "interface",
7909 path
->peer
->conf_if
);
7911 if (path
->peer
->conf_if
) {
7912 if (path
->peer
->hostname
7915 BGP_FLAG_SHOW_HOSTNAME
))
7916 vty_out(vty
, " from %s(%s)",
7917 path
->peer
->hostname
,
7918 path
->peer
->conf_if
);
7920 vty_out(vty
, " from %s",
7921 path
->peer
->conf_if
);
7923 if (path
->peer
->hostname
7926 BGP_FLAG_SHOW_HOSTNAME
))
7927 vty_out(vty
, " from %s(%s)",
7928 path
->peer
->hostname
,
7931 vty_out(vty
, " from %s",
7939 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7940 vty_out(vty
, " (%s)",
7941 inet_ntoa(attr
->originator_id
));
7943 vty_out(vty
, " (%s)",
7946 &path
->peer
->remote_id
,
7947 buf1
, sizeof(buf1
)));
7952 * Note when vrfid of nexthop is different from that of prefix
7954 if (path
->extra
&& path
->extra
->bgp_orig
) {
7955 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7960 if (path
->extra
->bgp_orig
->inst_type
7961 == BGP_INSTANCE_TYPE_DEFAULT
)
7963 vn
= VRF_DEFAULT_NAME
;
7965 vn
= path
->extra
->bgp_orig
->name
;
7967 json_object_string_add(json_path
, "nhVrfName",
7970 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7971 json_object_int_add(json_path
,
7974 json_object_int_add(json_path
,
7975 "nhVrfId", (int)nexthop_vrfid
);
7978 if (nexthop_vrfid
== VRF_UNKNOWN
)
7979 vty_out(vty
, " vrf ?");
7981 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7987 json_object_boolean_true_add(json_path
,
7988 "announceNexthopSelf");
7990 vty_out(vty
, " announce-nh-self");
7997 /* display the link-local nexthop */
7998 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8000 json_nexthop_ll
= json_object_new_object();
8001 json_object_string_add(
8002 json_nexthop_ll
, "ip",
8004 &attr
->mp_nexthop_local
, buf
,
8006 json_object_string_add(json_nexthop_ll
, "afi",
8008 json_object_string_add(json_nexthop_ll
, "scope",
8011 json_object_boolean_true_add(json_nexthop_ll
,
8014 if (!attr
->mp_nexthop_prefer_global
)
8015 json_object_boolean_true_add(
8016 json_nexthop_ll
, "used");
8018 json_object_boolean_true_add(
8019 json_nexthop_global
, "used");
8021 vty_out(vty
, " (%s) %s\n",
8023 &attr
->mp_nexthop_local
, buf
,
8025 attr
->mp_nexthop_prefer_global
8030 /* If we do not have a link-local nexthop then we must flag the
8034 json_object_boolean_true_add(
8035 json_nexthop_global
, "used");
8038 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8039 * Int/Ext/Local, Atomic, best */
8041 json_object_string_add(
8042 json_path
, "origin",
8043 bgp_origin_long_str
[attr
->origin
]);
8045 vty_out(vty
, " Origin %s",
8046 bgp_origin_long_str
[attr
->origin
]);
8048 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8052 * Adding "metric" field to match with
8053 * corresponding CLI. "med" will be
8054 * deprecated in future.
8056 json_object_int_add(json_path
, "med",
8058 json_object_int_add(json_path
, "metric",
8061 vty_out(vty
, ", metric %u", attr
->med
);
8064 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8066 json_object_int_add(json_path
, "localpref",
8069 vty_out(vty
, ", localpref %u",
8073 if (attr
->weight
!= 0) {
8075 json_object_int_add(json_path
, "weight",
8078 vty_out(vty
, ", weight %u", attr
->weight
);
8081 if (attr
->tag
!= 0) {
8083 json_object_int_add(json_path
, "tag",
8086 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8090 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8092 json_object_boolean_false_add(json_path
,
8095 vty_out(vty
, ", invalid");
8096 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8098 json_object_boolean_true_add(json_path
,
8101 vty_out(vty
, ", valid");
8104 if (path
->peer
!= bgp
->peer_self
) {
8105 if (path
->peer
->as
== path
->peer
->local_as
) {
8106 if (CHECK_FLAG(bgp
->config
,
8107 BGP_CONFIG_CONFEDERATION
)) {
8109 json_object_string_add(
8114 ", confed-internal");
8117 json_object_string_add(
8121 vty_out(vty
, ", internal");
8124 if (bgp_confederation_peers_check(
8125 bgp
, path
->peer
->as
)) {
8127 json_object_string_add(
8132 ", confed-external");
8135 json_object_string_add(
8139 vty_out(vty
, ", external");
8142 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8144 json_object_boolean_true_add(json_path
,
8146 json_object_boolean_true_add(json_path
,
8149 vty_out(vty
, ", aggregated, local");
8151 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8153 json_object_boolean_true_add(json_path
,
8156 vty_out(vty
, ", sourced");
8159 json_object_boolean_true_add(json_path
,
8161 json_object_boolean_true_add(json_path
,
8164 vty_out(vty
, ", sourced, local");
8168 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8170 json_object_boolean_true_add(json_path
,
8173 vty_out(vty
, ", atomic-aggregate");
8176 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8177 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8178 && bgp_path_info_mpath_count(path
))) {
8180 json_object_boolean_true_add(json_path
,
8183 vty_out(vty
, ", multipath");
8186 // Mark the bestpath(s)
8187 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8188 first_as
= aspath_get_first_as(attr
->aspath
);
8193 json_object_new_object();
8194 json_object_int_add(json_bestpath
,
8195 "bestpathFromAs", first_as
);
8198 vty_out(vty
, ", bestpath-from-AS %u",
8202 ", bestpath-from-AS Local");
8206 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8210 json_object_new_object();
8211 json_object_boolean_true_add(json_bestpath
,
8214 vty_out(vty
, ", best");
8218 json_object_object_add(json_path
, "bestpath",
8224 /* Line 4 display Community */
8225 if (attr
->community
) {
8227 if (!attr
->community
->json
)
8228 community_str(attr
->community
, true);
8229 json_object_lock(attr
->community
->json
);
8230 json_object_object_add(json_path
, "community",
8231 attr
->community
->json
);
8233 vty_out(vty
, " Community: %s\n",
8234 attr
->community
->str
);
8238 /* Line 5 display Extended-community */
8239 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8241 json_ext_community
= json_object_new_object();
8242 json_object_string_add(json_ext_community
,
8244 attr
->ecommunity
->str
);
8245 json_object_object_add(json_path
,
8246 "extendedCommunity",
8247 json_ext_community
);
8249 vty_out(vty
, " Extended Community: %s\n",
8250 attr
->ecommunity
->str
);
8254 /* Line 6 display Large community */
8255 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8257 if (!attr
->lcommunity
->json
)
8258 lcommunity_str(attr
->lcommunity
, true);
8259 json_object_lock(attr
->lcommunity
->json
);
8260 json_object_object_add(json_path
,
8262 attr
->lcommunity
->json
);
8264 vty_out(vty
, " Large Community: %s\n",
8265 attr
->lcommunity
->str
);
8269 /* Line 7 display Originator, Cluster-id */
8270 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8271 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8273 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8275 json_object_string_add(
8276 json_path
, "originatorId",
8277 inet_ntoa(attr
->originator_id
));
8279 vty_out(vty
, " Originator: %s",
8280 inet_ntoa(attr
->originator_id
));
8283 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8288 json_object_new_object();
8289 json_cluster_list_list
=
8290 json_object_new_array();
8293 i
< attr
->cluster
->length
/ 4;
8295 json_string
= json_object_new_string(
8299 json_object_array_add(
8300 json_cluster_list_list
,
8304 /* struct cluster_list does not have
8306 * aspath and community do. Add this
8309 json_object_string_add(json_cluster_list,
8310 "string", attr->cluster->str);
8312 json_object_object_add(
8313 json_cluster_list
, "list",
8314 json_cluster_list_list
);
8315 json_object_object_add(
8316 json_path
, "clusterList",
8319 vty_out(vty
, ", Cluster list: ");
8322 i
< attr
->cluster
->length
/ 4;
8336 if (path
->extra
&& path
->extra
->damp_info
)
8337 bgp_damp_info_vty(vty
, path
, json_path
);
8340 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8341 && safi
!= SAFI_EVPN
) {
8342 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8345 json_object_int_add(json_path
, "remoteLabel",
8348 vty_out(vty
, " Remote label: %d\n", label
);
8352 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8354 json_object_int_add(json_path
, "labelIndex",
8357 vty_out(vty
, " Label Index: %d\n",
8361 /* Line 8 display Addpath IDs */
8362 if (path
->addpath_rx_id
8363 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8365 json_object_int_add(json_path
, "addpathRxId",
8366 path
->addpath_rx_id
);
8368 /* Keep backwards compatibility with the old API
8369 * by putting TX All's ID in the old field
8371 json_object_int_add(
8372 json_path
, "addpathTxId",
8373 path
->tx_addpath
.addpath_tx_id
8376 /* ... but create a specific field for each
8379 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8380 json_object_int_add(
8382 bgp_addpath_names(i
)
8388 vty_out(vty
, " AddPath ID: RX %u, ",
8389 path
->addpath_rx_id
);
8391 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8395 /* If we used addpath to TX a non-bestpath we need to display
8396 * "Advertised to" on a path-by-path basis
8398 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8401 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8403 bgp_addpath_encode_tx(peer
, afi
, safi
);
8404 has_adj
= bgp_adj_out_lookup(
8406 bgp_addpath_id_for_peer(
8408 &path
->tx_addpath
));
8410 if ((addpath_capable
&& has_adj
)
8411 || (!addpath_capable
&& has_adj
8412 && CHECK_FLAG(path
->flags
,
8413 BGP_PATH_SELECTED
))) {
8414 if (json_path
&& !json_adv_to
)
8416 json_object_new_object();
8418 route_vty_out_advertised_to(
8427 json_object_object_add(json_path
,
8438 /* Line 9 display Uptime */
8439 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8441 json_last_update
= json_object_new_object();
8442 json_object_int_add(json_last_update
, "epoch", tbuf
);
8443 json_object_string_add(json_last_update
, "string",
8445 json_object_object_add(json_path
, "lastUpdate",
8448 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8450 /* Line 10 display PMSI tunnel attribute, if present */
8451 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8452 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8453 attr
->pmsi_tnl_type
,
8454 PMSI_TNLTYPE_STR_DEFAULT
);
8457 json_pmsi
= json_object_new_object();
8458 json_object_string_add(json_pmsi
,
8460 json_object_int_add(json_pmsi
,
8462 label2vni(&attr
->label
));
8463 json_object_object_add(json_path
, "pmsi",
8467 " PMSI Tunnel Type: %s, label: %d\n",
8468 str
, label2vni(&attr
->label
));
8473 /* We've constructed the json object for this path, add it to the json
8477 if (json_nexthop_global
|| json_nexthop_ll
) {
8478 json_nexthops
= json_object_new_array();
8480 if (json_nexthop_global
)
8481 json_object_array_add(json_nexthops
,
8482 json_nexthop_global
);
8484 if (json_nexthop_ll
)
8485 json_object_array_add(json_nexthops
,
8488 json_object_object_add(json_path
, "nexthops",
8492 json_object_object_add(json_path
, "peer", json_peer
);
8493 json_object_array_add(json_paths
, json_path
);
8498 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8499 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8500 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8502 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8503 const char *prefix_list_str
, afi_t afi
,
8504 safi_t safi
, enum bgp_show_type type
);
8505 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8506 const char *filter
, afi_t afi
, safi_t safi
,
8507 enum bgp_show_type type
);
8508 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8509 const char *rmap_str
, afi_t afi
, safi_t safi
,
8510 enum bgp_show_type type
);
8511 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8512 const char *com
, int exact
, afi_t afi
,
8514 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8515 const char *prefix
, afi_t afi
, safi_t safi
,
8516 enum bgp_show_type type
);
8517 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8518 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8519 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8520 const char *comstr
, int exact
, afi_t afi
,
8521 safi_t safi
, bool use_json
);
8524 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8525 struct bgp_table
*table
, enum bgp_show_type type
,
8526 void *output_arg
, bool use_json
, char *rd
,
8527 int is_last
, unsigned long *output_cum
,
8528 unsigned long *total_cum
,
8529 unsigned long *json_header_depth
)
8531 struct bgp_path_info
*pi
;
8532 struct bgp_node
*rn
;
8535 unsigned long output_count
= 0;
8536 unsigned long total_count
= 0;
8539 json_object
*json_paths
= NULL
;
8542 if (output_cum
&& *output_cum
!= 0)
8545 if (use_json
&& !*json_header_depth
) {
8547 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8548 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8549 " \"localAS\": %u,\n \"routes\": { ",
8550 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8551 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8554 table
->version
, inet_ntoa(bgp
->router_id
),
8555 bgp
->default_local_pref
, bgp
->as
);
8556 *json_header_depth
= 2;
8558 vty_out(vty
, " \"routeDistinguishers\" : {");
8559 ++*json_header_depth
;
8563 if (use_json
&& rd
) {
8564 vty_out(vty
, " \"%s\" : { ", rd
);
8567 /* Start processing of routes. */
8568 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8569 pi
= bgp_node_get_bgp_path_info(rn
);
8575 json_paths
= json_object_new_array();
8579 for (; pi
; pi
= pi
->next
) {
8581 if (type
== bgp_show_type_flap_statistics
8582 || type
== bgp_show_type_flap_neighbor
8583 || type
== bgp_show_type_dampend_paths
8584 || type
== bgp_show_type_damp_neighbor
) {
8585 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8588 if (type
== bgp_show_type_regexp
) {
8589 regex_t
*regex
= output_arg
;
8591 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8595 if (type
== bgp_show_type_prefix_list
) {
8596 struct prefix_list
*plist
= output_arg
;
8598 if (prefix_list_apply(plist
, &rn
->p
)
8602 if (type
== bgp_show_type_filter_list
) {
8603 struct as_list
*as_list
= output_arg
;
8605 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8606 != AS_FILTER_PERMIT
)
8609 if (type
== bgp_show_type_route_map
) {
8610 struct route_map
*rmap
= output_arg
;
8611 struct bgp_path_info path
;
8612 struct attr dummy_attr
;
8615 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8617 path
.peer
= pi
->peer
;
8618 path
.attr
= &dummy_attr
;
8620 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8622 if (ret
== RMAP_DENYMATCH
)
8625 if (type
== bgp_show_type_neighbor
8626 || type
== bgp_show_type_flap_neighbor
8627 || type
== bgp_show_type_damp_neighbor
) {
8628 union sockunion
*su
= output_arg
;
8630 if (pi
->peer
== NULL
8631 || pi
->peer
->su_remote
== NULL
8632 || !sockunion_same(pi
->peer
->su_remote
, su
))
8635 if (type
== bgp_show_type_cidr_only
) {
8636 uint32_t destination
;
8638 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8639 if (IN_CLASSC(destination
)
8640 && rn
->p
.prefixlen
== 24)
8642 if (IN_CLASSB(destination
)
8643 && rn
->p
.prefixlen
== 16)
8645 if (IN_CLASSA(destination
)
8646 && rn
->p
.prefixlen
== 8)
8649 if (type
== bgp_show_type_prefix_longer
) {
8651 if (!prefix_match(p
, &rn
->p
))
8654 if (type
== bgp_show_type_community_all
) {
8655 if (!pi
->attr
->community
)
8658 if (type
== bgp_show_type_community
) {
8659 struct community
*com
= output_arg
;
8661 if (!pi
->attr
->community
8662 || !community_match(pi
->attr
->community
,
8666 if (type
== bgp_show_type_community_exact
) {
8667 struct community
*com
= output_arg
;
8669 if (!pi
->attr
->community
8670 || !community_cmp(pi
->attr
->community
, com
))
8673 if (type
== bgp_show_type_community_list
) {
8674 struct community_list
*list
= output_arg
;
8676 if (!community_list_match(pi
->attr
->community
,
8680 if (type
== bgp_show_type_community_list_exact
) {
8681 struct community_list
*list
= output_arg
;
8683 if (!community_list_exact_match(
8684 pi
->attr
->community
, list
))
8687 if (type
== bgp_show_type_lcommunity
) {
8688 struct lcommunity
*lcom
= output_arg
;
8690 if (!pi
->attr
->lcommunity
8691 || !lcommunity_match(pi
->attr
->lcommunity
,
8695 if (type
== bgp_show_type_lcommunity_list
) {
8696 struct community_list
*list
= output_arg
;
8698 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8702 if (type
== bgp_show_type_lcommunity_all
) {
8703 if (!pi
->attr
->lcommunity
)
8706 if (type
== bgp_show_type_dampend_paths
8707 || type
== bgp_show_type_damp_neighbor
) {
8708 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8709 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8713 if (!use_json
&& header
) {
8714 vty_out(vty
, "BGP table version is %" PRIu64
8715 ", local router ID is %s, vrf id ",
8717 inet_ntoa(bgp
->router_id
));
8718 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8719 vty_out(vty
, "%s", VRFID_NONE_STR
);
8721 vty_out(vty
, "%u", bgp
->vrf_id
);
8723 vty_out(vty
, "Default local pref %u, ",
8724 bgp
->default_local_pref
);
8725 vty_out(vty
, "local AS %u\n", bgp
->as
);
8726 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8727 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8728 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8729 if (type
== bgp_show_type_dampend_paths
8730 || type
== bgp_show_type_damp_neighbor
)
8731 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8732 else if (type
== bgp_show_type_flap_statistics
8733 || type
== bgp_show_type_flap_neighbor
)
8734 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8736 vty_out(vty
, BGP_SHOW_HEADER
);
8739 if (rd
!= NULL
&& !display
&& !output_count
) {
8742 "Route Distinguisher: %s\n",
8745 if (type
== bgp_show_type_dampend_paths
8746 || type
== bgp_show_type_damp_neighbor
)
8747 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
8748 safi
, use_json
, json_paths
);
8749 else if (type
== bgp_show_type_flap_statistics
8750 || type
== bgp_show_type_flap_neighbor
)
8751 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
8752 safi
, use_json
, json_paths
);
8754 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
8766 if (p
->family
== AF_FLOWSPEC
) {
8767 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
8769 bgp_fs_nlri_get_string((unsigned char *)
8770 p
->u
.prefix_flowspec
.ptr
,
8771 p
->u
.prefix_flowspec
8774 NLRI_STRING_FORMAT_MIN
,
8777 vty_out(vty
, "\"%s/%d\": ",
8779 p
->u
.prefix_flowspec
.prefixlen
);
8781 vty_out(vty
, ",\"%s/%d\": ",
8783 p
->u
.prefix_flowspec
.prefixlen
);
8785 prefix2str(p
, buf2
, sizeof(buf2
));
8787 vty_out(vty
, "\"%s\": ", buf2
);
8789 vty_out(vty
, ",\"%s\": ", buf2
);
8792 json_object_to_json_string(json_paths
));
8793 json_object_free(json_paths
);
8800 output_count
+= *output_cum
;
8801 *output_cum
= output_count
;
8804 total_count
+= *total_cum
;
8805 *total_cum
= total_count
;
8809 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8813 for (i
= 0; i
< *json_header_depth
; ++i
)
8814 vty_out(vty
, " } ");
8818 /* No route is displayed */
8819 if (output_count
== 0) {
8820 if (type
== bgp_show_type_normal
)
8822 "No BGP prefixes displayed, %ld exist\n",
8826 "\nDisplayed %ld routes and %ld total paths\n",
8827 output_count
, total_count
);
8834 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8835 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8836 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8838 struct bgp_node
*rn
, *next
;
8839 unsigned long output_cum
= 0;
8840 unsigned long total_cum
= 0;
8841 unsigned long json_header_depth
= 0;
8842 struct bgp_table
*itable
;
8845 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8847 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8848 next
= bgp_route_next(rn
);
8849 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8852 itable
= bgp_node_get_bgp_table_info(rn
);
8853 if (itable
!= NULL
) {
8854 struct prefix_rd prd
;
8855 char rd
[RD_ADDRSTRLEN
];
8857 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8858 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8859 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
8860 use_json
, rd
, next
== NULL
, &output_cum
,
8861 &total_cum
, &json_header_depth
);
8867 if (output_cum
== 0)
8868 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8872 "\nDisplayed %ld routes and %ld total paths\n",
8873 output_cum
, total_cum
);
8877 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8878 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8880 struct bgp_table
*table
;
8881 unsigned long json_header_depth
= 0;
8884 bgp
= bgp_get_default();
8889 vty_out(vty
, "No BGP process is configured\n");
8891 vty_out(vty
, "{}\n");
8895 table
= bgp
->rib
[afi
][safi
];
8896 /* use MPLS and ENCAP specific shows until they are merged */
8897 if (safi
== SAFI_MPLS_VPN
) {
8898 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8899 output_arg
, use_json
);
8902 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8903 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8904 output_arg
, use_json
,
8907 /* labeled-unicast routes live in the unicast table */
8908 else if (safi
== SAFI_LABELED_UNICAST
)
8909 safi
= SAFI_UNICAST
;
8911 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8912 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8915 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8916 safi_t safi
, bool use_json
)
8918 struct listnode
*node
, *nnode
;
8921 bool route_output
= false;
8924 vty_out(vty
, "{\n");
8926 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8927 route_output
= true;
8930 vty_out(vty
, ",\n");
8934 vty_out(vty
, "\"%s\":",
8935 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8939 vty_out(vty
, "\nInstance %s:\n",
8940 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8944 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8949 vty_out(vty
, "}\n");
8950 else if (!route_output
)
8951 vty_out(vty
, "%% BGP instance not found\n");
8954 /* Header of detailed BGP route information */
8955 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8956 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8957 afi_t afi
, safi_t safi
, json_object
*json
)
8959 struct bgp_path_info
*pi
;
8962 struct listnode
*node
, *nnode
;
8963 char buf1
[RD_ADDRSTRLEN
];
8964 char buf2
[INET6_ADDRSTRLEN
];
8965 char buf3
[EVPN_ROUTE_STRLEN
];
8966 char prefix_str
[BUFSIZ
];
8971 int route_filter_translated_v4
= 0;
8972 int route_filter_v4
= 0;
8973 int route_filter_translated_v6
= 0;
8974 int route_filter_v6
= 0;
8977 int accept_own_nexthop
= 0;
8980 int no_advertise
= 0;
8984 int has_valid_label
= 0;
8985 mpls_label_t label
= 0;
8986 json_object
*json_adv_to
= NULL
;
8989 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8991 if (has_valid_label
)
8992 label
= label_pton(&rn
->local_label
);
8995 if (has_valid_label
)
8996 json_object_int_add(json
, "localLabel", label
);
8998 json_object_string_add(
9000 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9002 if (safi
== SAFI_EVPN
)
9003 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9004 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9007 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9008 buf3
, sizeof(buf3
)));
9010 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9011 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9012 ? prefix_rd2str(prd
, buf1
,
9015 safi
== SAFI_MPLS_VPN
? ":" : "",
9016 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9020 if (has_valid_label
)
9021 vty_out(vty
, "Local label: %d\n", label
);
9022 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9023 vty_out(vty
, "not allocated\n");
9026 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9028 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9030 if (pi
->extra
&& pi
->extra
->suppress
)
9033 if (pi
->attr
->community
== NULL
)
9036 no_advertise
+= community_include(
9037 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9038 no_export
+= community_include(pi
->attr
->community
,
9039 COMMUNITY_NO_EXPORT
);
9040 local_as
+= community_include(pi
->attr
->community
,
9041 COMMUNITY_LOCAL_AS
);
9042 accept_own
+= community_include(pi
->attr
->community
,
9043 COMMUNITY_ACCEPT_OWN
);
9044 route_filter_translated_v4
+= community_include(
9045 pi
->attr
->community
,
9046 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9047 route_filter_translated_v6
+= community_include(
9048 pi
->attr
->community
,
9049 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9050 route_filter_v4
+= community_include(
9051 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9052 route_filter_v6
+= community_include(
9053 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9054 llgr_stale
+= community_include(pi
->attr
->community
,
9055 COMMUNITY_LLGR_STALE
);
9056 no_llgr
+= community_include(pi
->attr
->community
,
9058 accept_own_nexthop
+=
9059 community_include(pi
->attr
->community
,
9060 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9061 blackhole
+= community_include(pi
->attr
->community
,
9062 COMMUNITY_BLACKHOLE
);
9063 no_peer
+= community_include(pi
->attr
->community
,
9069 vty_out(vty
, "Paths: (%d available", count
);
9071 vty_out(vty
, ", best #%d", best
);
9072 if (safi
== SAFI_UNICAST
)
9073 vty_out(vty
, ", table %s",
9075 == BGP_INSTANCE_TYPE_DEFAULT
)
9079 vty_out(vty
, ", no best path");
9083 ", accept own local route exported and imported in different VRF");
9084 else if (route_filter_translated_v4
)
9086 ", mark translated RTs for VPNv4 route filtering");
9087 else if (route_filter_v4
)
9089 ", attach RT as-is for VPNv4 route filtering");
9090 else if (route_filter_translated_v6
)
9092 ", mark translated RTs for VPNv6 route filtering");
9093 else if (route_filter_v6
)
9095 ", attach RT as-is for VPNv6 route filtering");
9096 else if (llgr_stale
)
9098 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9101 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9102 else if (accept_own_nexthop
)
9104 ", accept local nexthop");
9106 vty_out(vty
, ", inform peer to blackhole prefix");
9108 vty_out(vty
, ", not advertised to EBGP peer");
9109 else if (no_advertise
)
9110 vty_out(vty
, ", not advertised to any peer");
9112 vty_out(vty
, ", not advertised outside local AS");
9115 ", inform EBGP peer not to advertise to their EBGP peers");
9119 ", Advertisements suppressed by an aggregate.");
9120 vty_out(vty
, ")\n");
9123 /* If we are not using addpath then we can display Advertised to and
9125 * show what peers we advertised the bestpath to. If we are using
9127 * though then we must display Advertised to on a path-by-path basis. */
9128 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9129 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9130 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9131 if (json
&& !json_adv_to
)
9132 json_adv_to
= json_object_new_object();
9134 route_vty_out_advertised_to(
9136 " Advertised to non peer-group peers:\n ",
9143 json_object_object_add(json
, "advertisedTo",
9148 vty_out(vty
, " Not advertised to any peer");
9154 /* Display specified route of BGP table. */
9155 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9156 struct bgp_table
*rib
, const char *ip_str
,
9157 afi_t afi
, safi_t safi
,
9158 struct prefix_rd
*prd
, int prefix_check
,
9159 enum bgp_path_type pathtype
, bool use_json
)
9164 struct prefix match
;
9165 struct bgp_node
*rn
;
9166 struct bgp_node
*rm
;
9167 struct bgp_path_info
*pi
;
9168 struct bgp_table
*table
;
9169 json_object
*json
= NULL
;
9170 json_object
*json_paths
= NULL
;
9172 /* Check IP address argument. */
9173 ret
= str2prefix(ip_str
, &match
);
9175 vty_out(vty
, "address is malformed\n");
9179 match
.family
= afi2family(afi
);
9182 json
= json_object_new_object();
9183 json_paths
= json_object_new_array();
9186 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9187 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9188 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9190 table
= bgp_node_get_bgp_table_info(rn
);
9196 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9200 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9201 bgp_unlock_node(rm
);
9205 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9208 route_vty_out_detail_header(
9210 (struct prefix_rd
*)&rn
->p
,
9211 AFI_IP
, safi
, json
);
9216 if (pathtype
== BGP_PATH_SHOW_ALL
9217 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9218 && CHECK_FLAG(pi
->flags
,
9220 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9221 && (CHECK_FLAG(pi
->flags
,
9223 || CHECK_FLAG(pi
->flags
,
9224 BGP_PATH_SELECTED
))))
9225 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9230 bgp_unlock_node(rm
);
9232 } else if (safi
== SAFI_FLOWSPEC
) {
9233 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9234 &match
, prefix_check
,
9241 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9243 || rn
->p
.prefixlen
== match
.prefixlen
) {
9244 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9247 route_vty_out_detail_header(
9248 vty
, bgp
, rn
, NULL
, afi
,
9254 if (pathtype
== BGP_PATH_SHOW_ALL
9256 == BGP_PATH_SHOW_BESTPATH
9261 == BGP_PATH_SHOW_MULTIPATH
9267 BGP_PATH_SELECTED
))))
9268 route_vty_out_detail(
9269 vty
, bgp
, &rn
->p
, pi
,
9270 afi
, safi
, json_paths
);
9274 bgp_unlock_node(rn
);
9280 json_object_object_add(json
, "paths", json_paths
);
9282 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9283 json
, JSON_C_TO_STRING_PRETTY
));
9284 json_object_free(json
);
9287 vty_out(vty
, "%% Network not in table\n");
9295 /* Display specified route of Main RIB */
9296 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9297 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9298 int prefix_check
, enum bgp_path_type pathtype
,
9302 bgp
= bgp_get_default();
9305 vty_out(vty
, "No BGP process is configured\n");
9307 vty_out(vty
, "{}\n");
9312 /* labeled-unicast routes live in the unicast table */
9313 if (safi
== SAFI_LABELED_UNICAST
)
9314 safi
= SAFI_UNICAST
;
9316 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9317 afi
, safi
, prd
, prefix_check
, pathtype
,
9321 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9322 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9325 struct lcommunity
*lcom
;
9331 b
= buffer_new(1024);
9332 for (i
= 0; i
< argc
; i
++) {
9334 buffer_putc(b
, ' ');
9336 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9338 buffer_putstr(b
, argv
[i
]->arg
);
9342 buffer_putc(b
, '\0');
9344 str
= buffer_getstr(b
);
9347 lcom
= lcommunity_str2com(str
);
9348 XFREE(MTYPE_TMP
, str
);
9350 vty_out(vty
, "%% Large-community malformed\n");
9354 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9358 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9359 const char *lcom
, afi_t afi
, safi_t safi
,
9362 struct community_list
*list
;
9364 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9365 LARGE_COMMUNITY_LIST_MASTER
);
9367 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9372 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9376 DEFUN (show_ip_bgp_large_community_list
,
9377 show_ip_bgp_large_community_list_cmd
,
9378 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9382 BGP_INSTANCE_HELP_STR
9384 BGP_SAFI_WITH_LABEL_HELP_STR
9385 "Display routes matching the large-community-list\n"
9386 "large-community-list number\n"
9387 "large-community-list name\n"
9391 afi_t afi
= AFI_IP6
;
9392 safi_t safi
= SAFI_UNICAST
;
9395 if (argv_find(argv
, argc
, "ip", &idx
))
9397 if (argv_find(argv
, argc
, "view", &idx
)
9398 || argv_find(argv
, argc
, "vrf", &idx
))
9399 vrf
= argv
[++idx
]->arg
;
9400 if (argv_find(argv
, argc
, "ipv4", &idx
)
9401 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9402 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9403 if (argv_find(argv
, argc
, "unicast", &idx
)
9404 || argv_find(argv
, argc
, "multicast", &idx
))
9405 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9408 bool uj
= use_json(argc
, argv
);
9410 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9412 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9416 argv_find(argv
, argc
, "large-community-list", &idx
);
9417 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9420 DEFUN (show_ip_bgp_large_community
,
9421 show_ip_bgp_large_community_cmd
,
9422 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9426 BGP_INSTANCE_HELP_STR
9428 BGP_SAFI_WITH_LABEL_HELP_STR
9429 "Display routes matching the large-communities\n"
9430 "List of large-community numbers\n"
9434 afi_t afi
= AFI_IP6
;
9435 safi_t safi
= SAFI_UNICAST
;
9438 if (argv_find(argv
, argc
, "ip", &idx
))
9440 if (argv_find(argv
, argc
, "view", &idx
)
9441 || argv_find(argv
, argc
, "vrf", &idx
))
9442 vrf
= argv
[++idx
]->arg
;
9443 if (argv_find(argv
, argc
, "ipv4", &idx
)
9444 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9445 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9446 if (argv_find(argv
, argc
, "unicast", &idx
)
9447 || argv_find(argv
, argc
, "multicast", &idx
))
9448 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9451 bool uj
= use_json(argc
, argv
);
9453 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9455 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9459 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9460 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9462 return bgp_show(vty
, bgp
, afi
, safi
,
9463 bgp_show_type_lcommunity_all
, NULL
, uj
);
9466 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9470 /* BGP route print out function without JSON */
9473 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9474 <dampening <parameters>\
9479 |community-list <(1-500)|WORD> [exact-match]\
9480 |A.B.C.D/M longer-prefixes\
9481 |X:X::X:X/M longer-prefixes\
9486 BGP_INSTANCE_HELP_STR
9488 BGP_SAFI_WITH_LABEL_HELP_STR
9489 "Display detailed information about dampening\n"
9490 "Display detail of configured dampening parameters\n"
9491 "Display routes matching the route-map\n"
9492 "A route-map to match on\n"
9493 "Display routes conforming to the prefix-list\n"
9494 "Prefix-list name\n"
9495 "Display routes conforming to the filter-list\n"
9496 "Regular expression access list name\n"
9497 "BGP RIB advertisement statistics\n"
9498 "Display routes matching the community-list\n"
9499 "community-list number\n"
9500 "community-list name\n"
9501 "Exact match of the communities\n"
9503 "Display route and more specific routes\n"
9505 "Display route and more specific routes\n")
9507 afi_t afi
= AFI_IP6
;
9508 safi_t safi
= SAFI_UNICAST
;
9509 int exact_match
= 0;
9510 struct bgp
*bgp
= NULL
;
9513 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9518 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9519 if (argv_find(argv
, argc
, "parameters", &idx
))
9520 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9523 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9524 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9525 safi
, bgp_show_type_prefix_list
);
9527 if (argv_find(argv
, argc
, "filter-list", &idx
))
9528 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9529 safi
, bgp_show_type_filter_list
);
9531 if (argv_find(argv
, argc
, "statistics", &idx
))
9532 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9534 if (argv_find(argv
, argc
, "route-map", &idx
))
9535 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9536 safi
, bgp_show_type_route_map
);
9538 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9539 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9540 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9542 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9543 exact_match
, afi
, safi
);
9546 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9547 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9548 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9550 bgp_show_type_prefix_longer
);
9555 /* BGP route print out function with JSON */
9556 DEFUN (show_ip_bgp_json
,
9557 show_ip_bgp_json_cmd
,
9558 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9560 |dampening <flap-statistics|dampened-paths>\
9561 |community [AA:NN|local-AS|no-advertise|no-export\
9562 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9563 |accept-own|accept-own-nexthop|route-filter-v6\
9564 |route-filter-v4|route-filter-translated-v6\
9565 |route-filter-translated-v4] [exact-match]\
9570 BGP_INSTANCE_HELP_STR
9572 BGP_SAFI_WITH_LABEL_HELP_STR
9573 "Display only routes with non-natural netmasks\n"
9574 "Display detailed information about dampening\n"
9575 "Display flap statistics of routes\n"
9576 "Display paths suppressed due to dampening\n"
9577 "Display routes matching the communities\n"
9579 "Do not send outside local AS (well-known community)\n"
9580 "Do not advertise to any peer (well-known community)\n"
9581 "Do not export to next AS (well-known community)\n"
9582 "Graceful shutdown (well-known community)\n"
9583 "Do not export to any peer (well-known community)\n"
9584 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9585 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9586 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9587 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9588 "Should accept VPN route with local nexthop (well-known community)\n"
9589 "RT VPNv6 route filtering (well-known community)\n"
9590 "RT VPNv4 route filtering (well-known community)\n"
9591 "RT translated VPNv6 route filtering (well-known community)\n"
9592 "RT translated VPNv4 route filtering (well-known community)\n"
9593 "Exact match of the communities\n"
9596 afi_t afi
= AFI_IP6
;
9597 safi_t safi
= SAFI_UNICAST
;
9598 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9599 struct bgp
*bgp
= NULL
;
9601 int exact_match
= 0;
9602 bool uj
= use_json(argc
, argv
);
9607 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9612 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9613 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9616 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9617 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9618 return bgp_show(vty
, bgp
, afi
, safi
,
9619 bgp_show_type_dampend_paths
, NULL
, uj
);
9620 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9621 return bgp_show(vty
, bgp
, afi
, safi
,
9622 bgp_show_type_flap_statistics
, NULL
,
9626 if (argv_find(argv
, argc
, "community", &idx
)) {
9627 char *maybecomm
= NULL
;
9628 char *community
= NULL
;
9630 if (idx
+ 1 < argc
) {
9631 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
9632 maybecomm
= argv
[idx
+ 1]->arg
;
9634 maybecomm
= argv
[idx
+ 1]->text
;
9637 if (maybecomm
&& !strmatch(maybecomm
, "json")
9638 && !strmatch(maybecomm
, "exact-match"))
9639 community
= maybecomm
;
9641 if (argv_find(argv
, argc
, "exact-match", &idx
))
9645 return bgp_show_community(vty
, bgp
, community
,
9646 exact_match
, afi
, safi
, uj
);
9648 return (bgp_show(vty
, bgp
, afi
, safi
,
9649 bgp_show_type_community_all
, NULL
,
9653 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9656 DEFUN (show_ip_bgp_route
,
9657 show_ip_bgp_route_cmd
,
9658 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9659 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9663 BGP_INSTANCE_HELP_STR
9665 BGP_SAFI_WITH_LABEL_HELP_STR
9666 "Network in the BGP routing table to display\n"
9668 "Network in the BGP routing table to display\n"
9670 "Display only the bestpath\n"
9671 "Display only multipaths\n"
9674 int prefix_check
= 0;
9676 afi_t afi
= AFI_IP6
;
9677 safi_t safi
= SAFI_UNICAST
;
9678 char *prefix
= NULL
;
9679 struct bgp
*bgp
= NULL
;
9680 enum bgp_path_type path_type
;
9681 bool uj
= use_json(argc
, argv
);
9685 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9692 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9696 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9697 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9698 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9700 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9701 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9704 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9705 && afi
!= AFI_IP6
) {
9707 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9710 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9713 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9717 prefix
= argv
[idx
]->arg
;
9719 /* [<bestpath|multipath>] */
9720 if (argv_find(argv
, argc
, "bestpath", &idx
))
9721 path_type
= BGP_PATH_SHOW_BESTPATH
;
9722 else if (argv_find(argv
, argc
, "multipath", &idx
))
9723 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9725 path_type
= BGP_PATH_SHOW_ALL
;
9727 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9731 DEFUN (show_ip_bgp_regexp
,
9732 show_ip_bgp_regexp_cmd
,
9733 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9737 BGP_INSTANCE_HELP_STR
9739 BGP_SAFI_WITH_LABEL_HELP_STR
9740 "Display routes matching the AS path regular expression\n"
9741 "A regular-expression to match the BGP AS paths\n")
9743 afi_t afi
= AFI_IP6
;
9744 safi_t safi
= SAFI_UNICAST
;
9745 struct bgp
*bgp
= NULL
;
9748 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9753 // get index of regex
9754 argv_find(argv
, argc
, "regexp", &idx
);
9757 char *regstr
= argv_concat(argv
, argc
, idx
);
9758 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9759 bgp_show_type_regexp
);
9760 XFREE(MTYPE_TMP
, regstr
);
9764 DEFUN (show_ip_bgp_instance_all
,
9765 show_ip_bgp_instance_all_cmd
,
9766 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9770 BGP_INSTANCE_ALL_HELP_STR
9772 BGP_SAFI_WITH_LABEL_HELP_STR
9776 safi_t safi
= SAFI_UNICAST
;
9777 struct bgp
*bgp
= NULL
;
9779 bool uj
= use_json(argc
, argv
);
9784 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9789 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9793 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9794 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9799 regex
= bgp_regcomp(regstr
);
9801 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9805 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9806 bgp_regex_free(regex
);
9810 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9811 const char *prefix_list_str
, afi_t afi
,
9812 safi_t safi
, enum bgp_show_type type
)
9814 struct prefix_list
*plist
;
9816 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9817 if (plist
== NULL
) {
9818 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9823 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9826 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9827 const char *filter
, afi_t afi
, safi_t safi
,
9828 enum bgp_show_type type
)
9830 struct as_list
*as_list
;
9832 as_list
= as_list_lookup(filter
);
9833 if (as_list
== NULL
) {
9834 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9839 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9842 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9843 const char *rmap_str
, afi_t afi
, safi_t safi
,
9844 enum bgp_show_type type
)
9846 struct route_map
*rmap
;
9848 rmap
= route_map_lookup_by_name(rmap_str
);
9850 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9854 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9857 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9858 const char *comstr
, int exact
, afi_t afi
,
9859 safi_t safi
, bool use_json
)
9861 struct community
*com
;
9864 com
= community_str2com(comstr
);
9866 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9870 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9871 (exact
? bgp_show_type_community_exact
9872 : bgp_show_type_community
),
9874 community_free(&com
);
9879 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9880 const char *com
, int exact
, afi_t afi
,
9883 struct community_list
*list
;
9885 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
9887 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9891 return bgp_show(vty
, bgp
, afi
, safi
,
9892 (exact
? bgp_show_type_community_list_exact
9893 : bgp_show_type_community_list
),
9897 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9898 const char *prefix
, afi_t afi
, safi_t safi
,
9899 enum bgp_show_type type
)
9906 ret
= str2prefix(prefix
, p
);
9908 vty_out(vty
, "%% Malformed Prefix\n");
9912 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9917 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9918 const char *ip_str
, bool use_json
)
9924 /* Get peer sockunion. */
9925 ret
= str2sockunion(ip_str
, &su
);
9927 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9929 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9933 json_object
*json_no
= NULL
;
9934 json_no
= json_object_new_object();
9935 json_object_string_add(
9937 "malformedAddressOrName",
9939 vty_out(vty
, "%s\n",
9940 json_object_to_json_string_ext(
9942 JSON_C_TO_STRING_PRETTY
));
9943 json_object_free(json_no
);
9946 "%% Malformed address or name: %s\n",
9954 /* Peer structure lookup. */
9955 peer
= peer_lookup(bgp
, &su
);
9958 json_object
*json_no
= NULL
;
9959 json_no
= json_object_new_object();
9960 json_object_string_add(json_no
, "warning",
9961 "No such neighbor in this view/vrf");
9962 vty_out(vty
, "%s\n",
9963 json_object_to_json_string_ext(
9964 json_no
, JSON_C_TO_STRING_PRETTY
));
9965 json_object_free(json_no
);
9967 vty_out(vty
, "No such neighbor in this view/vrf\n");
9975 BGP_STATS_MAXBITLEN
= 0,
9979 BGP_STATS_UNAGGREGATEABLE
,
9980 BGP_STATS_MAX_AGGREGATEABLE
,
9981 BGP_STATS_AGGREGATES
,
9983 BGP_STATS_ASPATH_COUNT
,
9984 BGP_STATS_ASPATH_MAXHOPS
,
9985 BGP_STATS_ASPATH_TOTHOPS
,
9986 BGP_STATS_ASPATH_MAXSIZE
,
9987 BGP_STATS_ASPATH_TOTSIZE
,
9988 BGP_STATS_ASN_HIGHEST
,
9992 static const char *table_stats_strs
[] = {
9993 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9994 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9995 [BGP_STATS_RIB
] = "Total Advertisements",
9996 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9997 [BGP_STATS_MAX_AGGREGATEABLE
] =
9998 "Maximum aggregateable prefixes",
9999 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10000 [BGP_STATS_SPACE
] = "Address space advertised",
10001 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10002 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10003 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10004 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10005 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10006 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10007 [BGP_STATS_MAX
] = NULL
,
10010 struct bgp_table_stats
{
10011 struct bgp_table
*table
;
10012 unsigned long long counts
[BGP_STATS_MAX
];
10013 double total_space
;
10017 #define TALLY_SIGFIG 100000
10018 static unsigned long
10019 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10021 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10022 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10023 unsigned long ret
= newtot
/ count
;
10025 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10032 static int bgp_table_stats_walker(struct thread
*t
)
10034 struct bgp_node
*rn
;
10035 struct bgp_node
*top
;
10036 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10037 unsigned int space
= 0;
10039 if (!(top
= bgp_table_top(ts
->table
)))
10042 switch (top
->p
.family
) {
10044 space
= IPV4_MAX_BITLEN
;
10047 space
= IPV6_MAX_BITLEN
;
10051 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10053 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10054 struct bgp_path_info
*pi
;
10055 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10056 unsigned int pinum
= 0;
10061 if (!bgp_node_has_bgp_path_info_data(rn
))
10064 ts
->counts
[BGP_STATS_PREFIXES
]++;
10065 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10068 ts
->counts
[BGP_STATS_AVGPLEN
]
10069 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10070 ts
->counts
[BGP_STATS_AVGPLEN
],
10074 /* check if the prefix is included by any other announcements */
10075 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10076 prn
= bgp_node_parent_nolock(prn
);
10078 if (prn
== NULL
|| prn
== top
) {
10079 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10080 /* announced address space */
10083 pow(2.0, space
- rn
->p
.prefixlen
);
10084 } else if (bgp_node_has_bgp_path_info_data(prn
))
10085 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10087 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10089 ts
->counts
[BGP_STATS_RIB
]++;
10092 && (CHECK_FLAG(pi
->attr
->flag
,
10094 BGP_ATTR_ATOMIC_AGGREGATE
))))
10095 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10097 /* as-path stats */
10098 if (pi
->attr
&& pi
->attr
->aspath
) {
10099 unsigned int hops
=
10100 aspath_count_hops(pi
->attr
->aspath
);
10101 unsigned int size
=
10102 aspath_size(pi
->attr
->aspath
);
10103 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10105 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10107 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10108 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
10111 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10112 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
10115 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10116 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10118 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10119 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10120 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10122 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10123 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10124 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10127 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10128 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
10136 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10139 struct bgp_table_stats ts
;
10142 if (!bgp
->rib
[afi
][safi
]) {
10143 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10145 return CMD_WARNING
;
10148 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10150 /* labeled-unicast routes live in the unicast table */
10151 if (safi
== SAFI_LABELED_UNICAST
)
10152 safi
= SAFI_UNICAST
;
10154 memset(&ts
, 0, sizeof(ts
));
10155 ts
.table
= bgp
->rib
[afi
][safi
];
10156 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10158 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10159 if (!table_stats_strs
[i
])
10164 case BGP_STATS_ASPATH_AVGHOPS
:
10165 case BGP_STATS_ASPATH_AVGSIZE
:
10166 case BGP_STATS_AVGPLEN
:
10167 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10168 vty_out (vty
, "%12.2f",
10169 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10172 case BGP_STATS_ASPATH_TOTHOPS
:
10173 case BGP_STATS_ASPATH_TOTSIZE
:
10174 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10175 vty_out(vty
, "%12.2f",
10177 ? (float)ts
.counts
[i
]
10179 [BGP_STATS_ASPATH_COUNT
]
10182 case BGP_STATS_TOTPLEN
:
10183 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10184 vty_out(vty
, "%12.2f",
10186 ? (float)ts
.counts
[i
]
10188 [BGP_STATS_PREFIXES
]
10191 case BGP_STATS_SPACE
:
10192 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10193 vty_out(vty
, "%12g\n", ts
.total_space
);
10195 if (afi
== AFI_IP6
) {
10196 vty_out(vty
, "%30s: ", "/32 equivalent ");
10197 vty_out(vty
, "%12g\n",
10198 ts
.total_space
* pow(2.0, -128 + 32));
10199 vty_out(vty
, "%30s: ", "/48 equivalent ");
10200 vty_out(vty
, "%12g\n",
10201 ts
.total_space
* pow(2.0, -128 + 48));
10203 vty_out(vty
, "%30s: ", "% announced ");
10204 vty_out(vty
, "%12.2f\n",
10205 ts
.total_space
* 100. * pow(2.0, -32));
10206 vty_out(vty
, "%30s: ", "/8 equivalent ");
10207 vty_out(vty
, "%12.2f\n",
10208 ts
.total_space
* pow(2.0, -32 + 8));
10209 vty_out(vty
, "%30s: ", "/24 equivalent ");
10210 vty_out(vty
, "%12.2f\n",
10211 ts
.total_space
* pow(2.0, -32 + 24));
10215 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10216 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10219 vty_out(vty
, "\n");
10221 return CMD_SUCCESS
;
10233 PCOUNT_PFCNT
, /* the figure we display to users */
10237 static const char *pcount_strs
[] = {
10238 [PCOUNT_ADJ_IN
] = "Adj-in",
10239 [PCOUNT_DAMPED
] = "Damped",
10240 [PCOUNT_REMOVED
] = "Removed",
10241 [PCOUNT_HISTORY
] = "History",
10242 [PCOUNT_STALE
] = "Stale",
10243 [PCOUNT_VALID
] = "Valid",
10244 [PCOUNT_ALL
] = "All RIB",
10245 [PCOUNT_COUNTED
] = "PfxCt counted",
10246 [PCOUNT_PFCNT
] = "Useable",
10247 [PCOUNT_MAX
] = NULL
,
10250 struct peer_pcounts
{
10251 unsigned int count
[PCOUNT_MAX
];
10252 const struct peer
*peer
;
10253 const struct bgp_table
*table
;
10256 static int bgp_peer_count_walker(struct thread
*t
)
10258 struct bgp_node
*rn
;
10259 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10260 const struct peer
*peer
= pc
->peer
;
10262 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10263 struct bgp_adj_in
*ain
;
10264 struct bgp_path_info
*pi
;
10266 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10267 if (ain
->peer
== peer
)
10268 pc
->count
[PCOUNT_ADJ_IN
]++;
10270 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10272 if (pi
->peer
!= peer
)
10275 pc
->count
[PCOUNT_ALL
]++;
10277 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10278 pc
->count
[PCOUNT_DAMPED
]++;
10279 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10280 pc
->count
[PCOUNT_HISTORY
]++;
10281 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10282 pc
->count
[PCOUNT_REMOVED
]++;
10283 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10284 pc
->count
[PCOUNT_STALE
]++;
10285 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10286 pc
->count
[PCOUNT_VALID
]++;
10287 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10288 pc
->count
[PCOUNT_PFCNT
]++;
10290 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10291 pc
->count
[PCOUNT_COUNTED
]++;
10292 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10294 EC_LIB_DEVELOPMENT
,
10295 "Attempting to count but flags say it is unusable");
10297 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10299 EC_LIB_DEVELOPMENT
,
10300 "Not counted but flags say we should");
10307 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10308 safi_t safi
, bool use_json
)
10310 struct peer_pcounts pcounts
= {.peer
= peer
};
10312 json_object
*json
= NULL
;
10313 json_object
*json_loop
= NULL
;
10316 json
= json_object_new_object();
10317 json_loop
= json_object_new_object();
10320 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10321 || !peer
->bgp
->rib
[afi
][safi
]) {
10323 json_object_string_add(
10325 "No such neighbor or address family");
10326 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10327 json_object_free(json
);
10329 vty_out(vty
, "%% No such neighbor or address family\n");
10331 return CMD_WARNING
;
10334 memset(&pcounts
, 0, sizeof(pcounts
));
10335 pcounts
.peer
= peer
;
10336 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10338 /* in-place call via thread subsystem so as to record execution time
10339 * stats for the thread-walk (i.e. ensure this can't be blamed on
10340 * on just vty_read()).
10342 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10345 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10346 json_object_string_add(json
, "multiProtocol",
10347 afi_safi_print(afi
, safi
));
10348 json_object_int_add(json
, "pfxCounter",
10349 peer
->pcount
[afi
][safi
]);
10351 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10352 json_object_int_add(json_loop
, pcount_strs
[i
],
10355 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10357 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10358 json_object_string_add(json
, "pfxctDriftFor",
10360 json_object_string_add(
10361 json
, "recommended",
10362 "Please report this bug, with the above command output");
10364 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10365 json
, JSON_C_TO_STRING_PRETTY
));
10366 json_object_free(json
);
10370 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10371 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10372 peer
->hostname
, peer
->host
,
10373 afi_safi_print(afi
, safi
));
10375 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10376 afi_safi_print(afi
, safi
));
10379 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10380 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10382 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10383 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10386 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10387 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10389 "Please report this bug, with the above command output\n");
10393 return CMD_SUCCESS
;
10396 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10397 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10398 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10399 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10403 BGP_INSTANCE_HELP_STR
10406 "Detailed information on TCP and BGP neighbor connections\n"
10407 "Neighbor to display information about\n"
10408 "Neighbor to display information about\n"
10409 "Neighbor on BGP configured interface\n"
10410 "Display detailed prefix count information\n"
10413 afi_t afi
= AFI_IP6
;
10414 safi_t safi
= SAFI_UNICAST
;
10417 struct bgp
*bgp
= NULL
;
10418 bool uj
= use_json(argc
, argv
);
10423 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10426 return CMD_WARNING
;
10428 argv_find(argv
, argc
, "neighbors", &idx
);
10429 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10431 return CMD_WARNING
;
10433 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10436 #ifdef KEEP_OLD_VPN_COMMANDS
10437 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10438 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10439 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10444 "Display information about all VPNv4 NLRIs\n"
10445 "Detailed information on TCP and BGP neighbor connections\n"
10446 "Neighbor to display information about\n"
10447 "Neighbor to display information about\n"
10448 "Neighbor on BGP configured interface\n"
10449 "Display detailed prefix count information\n"
10454 bool uj
= use_json(argc
, argv
);
10456 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10458 return CMD_WARNING
;
10460 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10463 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10464 show_ip_bgp_vpn_all_route_prefix_cmd
,
10465 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10470 "Display information about all VPNv4 NLRIs\n"
10471 "Network in the BGP routing table to display\n"
10472 "Network in the BGP routing table to display\n"
10476 char *network
= NULL
;
10477 struct bgp
*bgp
= bgp_get_default();
10479 vty_out(vty
, "Can't find default instance\n");
10480 return CMD_WARNING
;
10483 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10484 network
= argv
[idx
]->arg
;
10485 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10486 network
= argv
[idx
]->arg
;
10488 vty_out(vty
, "Unable to figure out Network\n");
10489 return CMD_WARNING
;
10492 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10493 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10495 #endif /* KEEP_OLD_VPN_COMMANDS */
10497 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10498 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10499 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10505 "Display information about all EVPN NLRIs\n"
10506 "Network in the BGP routing table to display\n"
10507 "Network in the BGP routing table to display\n"
10511 char *network
= NULL
;
10513 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10514 network
= argv
[idx
]->arg
;
10515 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10516 network
= argv
[idx
]->arg
;
10518 vty_out(vty
, "Unable to figure out Network\n");
10519 return CMD_WARNING
;
10521 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10522 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10525 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10526 safi_t safi
, enum bgp_show_adj_route_type type
,
10527 const char *rmap_name
, bool use_json
,
10530 struct bgp_table
*table
;
10531 struct bgp_adj_in
*ain
;
10532 struct bgp_adj_out
*adj
;
10533 unsigned long output_count
;
10534 unsigned long filtered_count
;
10535 struct bgp_node
*rn
;
10541 struct update_subgroup
*subgrp
;
10542 json_object
*json_scode
= NULL
;
10543 json_object
*json_ocode
= NULL
;
10544 json_object
*json_ar
= NULL
;
10545 struct peer_af
*paf
;
10546 bool route_filtered
;
10549 json_scode
= json_object_new_object();
10550 json_ocode
= json_object_new_object();
10551 json_ar
= json_object_new_object();
10553 json_object_string_add(json_scode
, "suppressed", "s");
10554 json_object_string_add(json_scode
, "damped", "d");
10555 json_object_string_add(json_scode
, "history", "h");
10556 json_object_string_add(json_scode
, "valid", "*");
10557 json_object_string_add(json_scode
, "best", ">");
10558 json_object_string_add(json_scode
, "multipath", "=");
10559 json_object_string_add(json_scode
, "internal", "i");
10560 json_object_string_add(json_scode
, "ribFailure", "r");
10561 json_object_string_add(json_scode
, "stale", "S");
10562 json_object_string_add(json_scode
, "removed", "R");
10564 json_object_string_add(json_ocode
, "igp", "i");
10565 json_object_string_add(json_ocode
, "egp", "e");
10566 json_object_string_add(json_ocode
, "incomplete", "?");
10573 json_object_string_add(json
, "alert", "no BGP");
10574 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10575 json_object_free(json
);
10577 vty_out(vty
, "%% No bgp\n");
10581 table
= bgp
->rib
[afi
][safi
];
10583 output_count
= filtered_count
= 0;
10584 subgrp
= peer_subgroup(peer
, afi
, safi
);
10586 if (type
== bgp_show_adj_route_advertised
&& subgrp
10587 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10589 json_object_int_add(json
, "bgpTableVersion",
10591 json_object_string_add(json
, "bgpLocalRouterId",
10592 inet_ntoa(bgp
->router_id
));
10593 json_object_int_add(json
, "defaultLocPrf",
10594 bgp
->default_local_pref
);
10595 json_object_int_add(json
, "localAS", bgp
->as
);
10596 json_object_object_add(json
, "bgpStatusCodes",
10598 json_object_object_add(json
, "bgpOriginCodes",
10600 json_object_string_add(
10601 json
, "bgpOriginatingDefaultNetwork",
10602 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10604 vty_out(vty
, "BGP table version is %" PRIu64
10605 ", local router ID is %s, vrf id ",
10606 table
->version
, inet_ntoa(bgp
->router_id
));
10607 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10608 vty_out(vty
, "%s", VRFID_NONE_STR
);
10610 vty_out(vty
, "%u", bgp
->vrf_id
);
10611 vty_out(vty
, "\n");
10612 vty_out(vty
, "Default local pref %u, ",
10613 bgp
->default_local_pref
);
10614 vty_out(vty
, "local AS %u\n", bgp
->as
);
10615 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10616 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10617 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10619 vty_out(vty
, "Originating default network %s\n\n",
10620 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10625 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10626 if (type
== bgp_show_adj_route_received
10627 || type
== bgp_show_adj_route_filtered
) {
10628 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10629 if (ain
->peer
!= peer
|| !ain
->attr
)
10634 json_object_int_add(
10635 json
, "bgpTableVersion",
10637 json_object_string_add(
10639 "bgpLocalRouterId",
10642 json_object_int_add(json
,
10644 bgp
->default_local_pref
);
10645 json_object_int_add(json
,
10646 "localAS", bgp
->as
);
10647 json_object_object_add(
10648 json
, "bgpStatusCodes",
10650 json_object_object_add(
10651 json
, "bgpOriginCodes",
10655 "BGP table version is 0, local router ID is %s, vrf id ",
10658 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10664 vty_out(vty
, "\n");
10666 "Default local pref %u, ",
10667 bgp
->default_local_pref
);
10668 vty_out(vty
, "local AS %u\n",
10671 BGP_SHOW_SCODE_HEADER
);
10673 BGP_SHOW_NCODE_HEADER
);
10675 BGP_SHOW_OCODE_HEADER
);
10681 vty_out(vty
, BGP_SHOW_HEADER
);
10685 bgp_attr_dup(&attr
, ain
->attr
);
10686 route_filtered
= false;
10688 /* Filter prefix using distribute list,
10689 * filter list or prefix list
10691 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10692 safi
)) == FILTER_DENY
)
10693 route_filtered
= true;
10695 /* Filter prefix using route-map */
10696 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10697 afi
, safi
, rmap_name
);
10699 if (type
== bgp_show_adj_route_filtered
&&
10700 !route_filtered
&& ret
!= RMAP_DENY
) {
10701 bgp_attr_undup(&attr
, ain
->attr
);
10705 if (type
== bgp_show_adj_route_received
&&
10706 (route_filtered
|| ret
== RMAP_DENY
))
10709 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10710 use_json
, json_ar
);
10711 bgp_attr_undup(&attr
, ain
->attr
);
10714 } else if (type
== bgp_show_adj_route_advertised
) {
10715 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
10716 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10717 if (paf
->peer
!= peer
|| !adj
->attr
)
10722 json_object_int_add(
10726 json_object_string_add(
10728 "bgpLocalRouterId",
10731 json_object_int_add(
10732 json
, "defaultLocPrf",
10733 bgp
->default_local_pref
10735 json_object_int_add(
10738 json_object_object_add(
10742 json_object_object_add(
10748 "BGP table version is %" PRIu64
10749 ", local router ID is %s, vrf id ",
10762 vty_out(vty
, "\n");
10764 "Default local pref %u, ",
10765 bgp
->default_local_pref
10771 BGP_SHOW_SCODE_HEADER
);
10773 BGP_SHOW_NCODE_HEADER
);
10775 BGP_SHOW_OCODE_HEADER
);
10786 bgp_attr_dup(&attr
, adj
->attr
);
10787 ret
= bgp_output_modifier(
10788 peer
, &rn
->p
, &attr
, afi
, safi
,
10791 if (ret
!= RMAP_DENY
) {
10792 route_vty_out_tmp(vty
, &rn
->p
,
10801 bgp_attr_undup(&attr
, adj
->attr
);
10807 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10808 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10809 json_object_int_add(json
, "filteredPrefixCounter",
10812 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10813 json
, JSON_C_TO_STRING_PRETTY
));
10814 json_object_free(json
);
10815 } else if (output_count
> 0) {
10816 if (filtered_count
> 0)
10818 "\nTotal number of prefixes %ld (%ld filtered)\n",
10819 output_count
, filtered_count
);
10821 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10826 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10827 safi_t safi
, enum bgp_show_adj_route_type type
,
10828 const char *rmap_name
, bool use_json
)
10830 json_object
*json
= NULL
;
10833 json
= json_object_new_object();
10835 /* labeled-unicast routes live in the unicast table */
10836 if (safi
== SAFI_LABELED_UNICAST
)
10837 safi
= SAFI_UNICAST
;
10839 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10841 json_object_string_add(
10843 "No such neighbor or address family");
10844 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10845 json_object_free(json
);
10847 vty_out(vty
, "%% No such neighbor or address family\n");
10849 return CMD_WARNING
;
10852 if ((type
== bgp_show_adj_route_received
10853 || type
== bgp_show_adj_route_filtered
)
10854 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10855 PEER_FLAG_SOFT_RECONFIG
)) {
10857 json_object_string_add(
10859 "Inbound soft reconfiguration not enabled");
10860 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10861 json_object_free(json
);
10864 "%% Inbound soft reconfiguration not enabled\n");
10866 return CMD_WARNING
;
10869 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10871 return CMD_SUCCESS
;
10874 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10875 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10876 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10877 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10881 BGP_INSTANCE_HELP_STR
10883 BGP_SAFI_WITH_LABEL_HELP_STR
10884 "Detailed information on TCP and BGP neighbor connections\n"
10885 "Neighbor to display information about\n"
10886 "Neighbor to display information about\n"
10887 "Neighbor on BGP configured interface\n"
10888 "Display the routes advertised to a BGP neighbor\n"
10889 "Display the received routes from neighbor\n"
10890 "Display the filtered routes received from neighbor\n"
10891 "Route-map to modify the attributes\n"
10892 "Name of the route map\n"
10895 afi_t afi
= AFI_IP6
;
10896 safi_t safi
= SAFI_UNICAST
;
10897 char *rmap_name
= NULL
;
10898 char *peerstr
= NULL
;
10899 struct bgp
*bgp
= NULL
;
10901 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10903 bool uj
= use_json(argc
, argv
);
10908 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10911 return CMD_WARNING
;
10913 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10914 argv_find(argv
, argc
, "neighbors", &idx
);
10915 peerstr
= argv
[++idx
]->arg
;
10917 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10919 return CMD_WARNING
;
10921 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10922 type
= bgp_show_adj_route_advertised
;
10923 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10924 type
= bgp_show_adj_route_received
;
10925 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10926 type
= bgp_show_adj_route_filtered
;
10928 if (argv_find(argv
, argc
, "route-map", &idx
))
10929 rmap_name
= argv
[++idx
]->arg
;
10931 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10934 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10935 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10936 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10942 "Address Family modifier\n"
10943 "Detailed information on TCP and BGP neighbor connections\n"
10944 "Neighbor to display information about\n"
10945 "Neighbor to display information about\n"
10946 "Neighbor on BGP configured interface\n"
10947 "Display information received from a BGP neighbor\n"
10948 "Display the prefixlist filter\n"
10951 afi_t afi
= AFI_IP6
;
10952 safi_t safi
= SAFI_UNICAST
;
10953 char *peerstr
= NULL
;
10956 union sockunion su
;
10962 /* show [ip] bgp */
10963 if (argv_find(argv
, argc
, "ip", &idx
))
10965 /* [<ipv4|ipv6> [unicast]] */
10966 if (argv_find(argv
, argc
, "ipv4", &idx
))
10968 if (argv_find(argv
, argc
, "ipv6", &idx
))
10970 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10971 argv_find(argv
, argc
, "neighbors", &idx
);
10972 peerstr
= argv
[++idx
]->arg
;
10974 bool uj
= use_json(argc
, argv
);
10976 ret
= str2sockunion(peerstr
, &su
);
10978 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10981 vty_out(vty
, "{}\n");
10984 "%% Malformed address or name: %s\n",
10986 return CMD_WARNING
;
10989 peer
= peer_lookup(NULL
, &su
);
10992 vty_out(vty
, "{}\n");
10994 vty_out(vty
, "No peer\n");
10995 return CMD_WARNING
;
10999 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11000 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11003 vty_out(vty
, "Address Family: %s\n",
11004 afi_safi_print(afi
, safi
));
11005 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11008 vty_out(vty
, "{}\n");
11010 vty_out(vty
, "No functional output\n");
11013 return CMD_SUCCESS
;
11016 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11017 afi_t afi
, safi_t safi
,
11018 enum bgp_show_type type
, bool use_json
)
11020 /* labeled-unicast routes live in the unicast table */
11021 if (safi
== SAFI_LABELED_UNICAST
)
11022 safi
= SAFI_UNICAST
;
11024 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11026 json_object
*json_no
= NULL
;
11027 json_no
= json_object_new_object();
11028 json_object_string_add(
11029 json_no
, "warning",
11030 "No such neighbor or address family");
11031 vty_out(vty
, "%s\n",
11032 json_object_to_json_string(json_no
));
11033 json_object_free(json_no
);
11035 vty_out(vty
, "%% No such neighbor or address family\n");
11036 return CMD_WARNING
;
11039 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11042 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11043 show_ip_bgp_flowspec_routes_detailed_cmd
,
11044 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11048 BGP_INSTANCE_HELP_STR
11051 "Detailed information on flowspec entries\n"
11054 afi_t afi
= AFI_IP
;
11055 safi_t safi
= SAFI_UNICAST
;
11056 struct bgp
*bgp
= NULL
;
11058 bool uj
= use_json(argc
, argv
);
11063 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11066 return CMD_WARNING
;
11068 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11071 DEFUN (show_ip_bgp_neighbor_routes
,
11072 show_ip_bgp_neighbor_routes_cmd
,
11073 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11074 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11078 BGP_INSTANCE_HELP_STR
11080 BGP_SAFI_WITH_LABEL_HELP_STR
11081 "Detailed information on TCP and BGP neighbor connections\n"
11082 "Neighbor to display information about\n"
11083 "Neighbor to display information about\n"
11084 "Neighbor on BGP configured interface\n"
11085 "Display flap statistics of the routes learned from neighbor\n"
11086 "Display the dampened routes received from neighbor\n"
11087 "Display routes learned from neighbor\n"
11090 char *peerstr
= NULL
;
11091 struct bgp
*bgp
= NULL
;
11092 afi_t afi
= AFI_IP6
;
11093 safi_t safi
= SAFI_UNICAST
;
11095 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11097 bool uj
= use_json(argc
, argv
);
11102 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11105 return CMD_WARNING
;
11107 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11108 argv_find(argv
, argc
, "neighbors", &idx
);
11109 peerstr
= argv
[++idx
]->arg
;
11111 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11113 return CMD_WARNING
;
11115 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11116 sh_type
= bgp_show_type_flap_neighbor
;
11117 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11118 sh_type
= bgp_show_type_damp_neighbor
;
11119 else if (argv_find(argv
, argc
, "routes", &idx
))
11120 sh_type
= bgp_show_type_neighbor
;
11122 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11125 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11127 struct bgp_distance
{
11128 /* Distance value for the IP source prefix. */
11131 /* Name of the access-list to be matched. */
11135 DEFUN (show_bgp_afi_vpn_rd_route
,
11136 show_bgp_afi_vpn_rd_route_cmd
,
11137 "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]",
11141 "Address Family modifier\n"
11142 "Display information for a route distinguisher\n"
11143 "Route Distinguisher\n"
11144 "Network in the BGP routing table to display\n"
11145 "Network in the BGP routing table to display\n"
11149 struct prefix_rd prd
;
11150 afi_t afi
= AFI_MAX
;
11153 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11154 vty_out(vty
, "%% Malformed Address Family\n");
11155 return CMD_WARNING
;
11158 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11160 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11161 return CMD_WARNING
;
11164 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11165 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11168 static struct bgp_distance
*bgp_distance_new(void)
11170 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11173 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11175 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11178 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11179 const char *ip_str
, const char *access_list_str
)
11186 struct bgp_node
*rn
;
11187 struct bgp_distance
*bdistance
;
11189 afi
= bgp_node_afi(vty
);
11190 safi
= bgp_node_safi(vty
);
11192 ret
= str2prefix(ip_str
, &p
);
11194 vty_out(vty
, "Malformed prefix\n");
11195 return CMD_WARNING_CONFIG_FAILED
;
11198 distance
= atoi(distance_str
);
11200 /* Get BGP distance node. */
11201 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11202 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11204 bgp_unlock_node(rn
);
11206 bdistance
= bgp_distance_new();
11207 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11210 /* Set distance value. */
11211 bdistance
->distance
= distance
;
11213 /* Reset access-list configuration. */
11214 if (bdistance
->access_list
) {
11215 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11216 bdistance
->access_list
= NULL
;
11218 if (access_list_str
)
11219 bdistance
->access_list
=
11220 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11222 return CMD_SUCCESS
;
11225 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11226 const char *ip_str
, const char *access_list_str
)
11233 struct bgp_node
*rn
;
11234 struct bgp_distance
*bdistance
;
11236 afi
= bgp_node_afi(vty
);
11237 safi
= bgp_node_safi(vty
);
11239 ret
= str2prefix(ip_str
, &p
);
11241 vty_out(vty
, "Malformed prefix\n");
11242 return CMD_WARNING_CONFIG_FAILED
;
11245 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11246 (struct prefix
*)&p
);
11248 vty_out(vty
, "Can't find specified prefix\n");
11249 return CMD_WARNING_CONFIG_FAILED
;
11252 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11253 distance
= atoi(distance_str
);
11255 if (bdistance
->distance
!= distance
) {
11256 vty_out(vty
, "Distance does not match configured\n");
11257 return CMD_WARNING_CONFIG_FAILED
;
11260 if (bdistance
->access_list
)
11261 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11262 bgp_distance_free(bdistance
);
11264 bgp_node_set_bgp_path_info(rn
, NULL
);
11265 bgp_unlock_node(rn
);
11266 bgp_unlock_node(rn
);
11268 return CMD_SUCCESS
;
11271 /* Apply BGP information to distance method. */
11272 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11273 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11275 struct bgp_node
*rn
;
11278 struct bgp_distance
*bdistance
;
11279 struct access_list
*alist
;
11280 struct bgp_static
*bgp_static
;
11285 peer
= pinfo
->peer
;
11287 /* Check source address. */
11288 sockunion2hostprefix(&peer
->su
, &q
);
11289 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11291 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11292 bgp_unlock_node(rn
);
11294 if (bdistance
->access_list
) {
11295 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11297 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11298 return bdistance
->distance
;
11300 return bdistance
->distance
;
11303 /* Backdoor check. */
11304 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11306 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11307 bgp_unlock_node(rn
);
11309 if (bgp_static
->backdoor
) {
11310 if (bgp
->distance_local
[afi
][safi
])
11311 return bgp
->distance_local
[afi
][safi
];
11313 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11317 if (peer
->sort
== BGP_PEER_EBGP
) {
11318 if (bgp
->distance_ebgp
[afi
][safi
])
11319 return bgp
->distance_ebgp
[afi
][safi
];
11320 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11322 if (bgp
->distance_ibgp
[afi
][safi
])
11323 return bgp
->distance_ibgp
[afi
][safi
];
11324 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11328 DEFUN (bgp_distance
,
11330 "distance bgp (1-255) (1-255) (1-255)",
11331 "Define an administrative distance\n"
11333 "Distance for routes external to the AS\n"
11334 "Distance for routes internal to the AS\n"
11335 "Distance for local routes\n")
11337 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11338 int idx_number
= 2;
11339 int idx_number_2
= 3;
11340 int idx_number_3
= 4;
11344 afi
= bgp_node_afi(vty
);
11345 safi
= bgp_node_safi(vty
);
11347 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11348 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11349 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11350 return CMD_SUCCESS
;
11353 DEFUN (no_bgp_distance
,
11354 no_bgp_distance_cmd
,
11355 "no distance bgp [(1-255) (1-255) (1-255)]",
11357 "Define an administrative distance\n"
11359 "Distance for routes external to the AS\n"
11360 "Distance for routes internal to the AS\n"
11361 "Distance for local routes\n")
11363 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11367 afi
= bgp_node_afi(vty
);
11368 safi
= bgp_node_safi(vty
);
11370 bgp
->distance_ebgp
[afi
][safi
] = 0;
11371 bgp
->distance_ibgp
[afi
][safi
] = 0;
11372 bgp
->distance_local
[afi
][safi
] = 0;
11373 return CMD_SUCCESS
;
11377 DEFUN (bgp_distance_source
,
11378 bgp_distance_source_cmd
,
11379 "distance (1-255) A.B.C.D/M",
11380 "Define an administrative distance\n"
11381 "Administrative distance\n"
11382 "IP source prefix\n")
11384 int idx_number
= 1;
11385 int idx_ipv4_prefixlen
= 2;
11386 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11387 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11388 return CMD_SUCCESS
;
11391 DEFUN (no_bgp_distance_source
,
11392 no_bgp_distance_source_cmd
,
11393 "no distance (1-255) A.B.C.D/M",
11395 "Define an administrative distance\n"
11396 "Administrative distance\n"
11397 "IP source prefix\n")
11399 int idx_number
= 2;
11400 int idx_ipv4_prefixlen
= 3;
11401 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11402 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11403 return CMD_SUCCESS
;
11406 DEFUN (bgp_distance_source_access_list
,
11407 bgp_distance_source_access_list_cmd
,
11408 "distance (1-255) A.B.C.D/M WORD",
11409 "Define an administrative distance\n"
11410 "Administrative distance\n"
11411 "IP source prefix\n"
11412 "Access list name\n")
11414 int idx_number
= 1;
11415 int idx_ipv4_prefixlen
= 2;
11417 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11418 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11419 return CMD_SUCCESS
;
11422 DEFUN (no_bgp_distance_source_access_list
,
11423 no_bgp_distance_source_access_list_cmd
,
11424 "no distance (1-255) A.B.C.D/M WORD",
11426 "Define an administrative distance\n"
11427 "Administrative distance\n"
11428 "IP source prefix\n"
11429 "Access list name\n")
11431 int idx_number
= 2;
11432 int idx_ipv4_prefixlen
= 3;
11434 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11435 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11436 return CMD_SUCCESS
;
11439 DEFUN (ipv6_bgp_distance_source
,
11440 ipv6_bgp_distance_source_cmd
,
11441 "distance (1-255) X:X::X:X/M",
11442 "Define an administrative distance\n"
11443 "Administrative distance\n"
11444 "IP source prefix\n")
11446 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11447 return CMD_SUCCESS
;
11450 DEFUN (no_ipv6_bgp_distance_source
,
11451 no_ipv6_bgp_distance_source_cmd
,
11452 "no distance (1-255) X:X::X:X/M",
11454 "Define an administrative distance\n"
11455 "Administrative distance\n"
11456 "IP source prefix\n")
11458 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11459 return CMD_SUCCESS
;
11462 DEFUN (ipv6_bgp_distance_source_access_list
,
11463 ipv6_bgp_distance_source_access_list_cmd
,
11464 "distance (1-255) X:X::X:X/M WORD",
11465 "Define an administrative distance\n"
11466 "Administrative distance\n"
11467 "IP source prefix\n"
11468 "Access list name\n")
11470 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11471 return CMD_SUCCESS
;
11474 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11475 no_ipv6_bgp_distance_source_access_list_cmd
,
11476 "no distance (1-255) X:X::X:X/M WORD",
11478 "Define an administrative distance\n"
11479 "Administrative distance\n"
11480 "IP source prefix\n"
11481 "Access list name\n")
11483 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11484 return CMD_SUCCESS
;
11487 DEFUN (bgp_damp_set
,
11489 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11490 "BGP Specific commands\n"
11491 "Enable route-flap dampening\n"
11492 "Half-life time for the penalty\n"
11493 "Value to start reusing a route\n"
11494 "Value to start suppressing a route\n"
11495 "Maximum duration to suppress a stable route\n")
11497 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11498 int idx_half_life
= 2;
11500 int idx_suppress
= 4;
11501 int idx_max_suppress
= 5;
11502 int half
= DEFAULT_HALF_LIFE
* 60;
11503 int reuse
= DEFAULT_REUSE
;
11504 int suppress
= DEFAULT_SUPPRESS
;
11505 int max
= 4 * half
;
11508 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11509 reuse
= atoi(argv
[idx_reuse
]->arg
);
11510 suppress
= atoi(argv
[idx_suppress
]->arg
);
11511 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11512 } else if (argc
== 3) {
11513 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11517 if (suppress
< reuse
) {
11519 "Suppress value cannot be less than reuse value \n");
11523 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11524 reuse
, suppress
, max
);
11527 DEFUN (bgp_damp_unset
,
11528 bgp_damp_unset_cmd
,
11529 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11531 "BGP Specific commands\n"
11532 "Enable route-flap dampening\n"
11533 "Half-life time for the penalty\n"
11534 "Value to start reusing a route\n"
11535 "Value to start suppressing a route\n"
11536 "Maximum duration to suppress a stable route\n")
11538 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11539 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11542 /* Display specified route of BGP table. */
11543 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11544 const char *ip_str
, afi_t afi
, safi_t safi
,
11545 struct prefix_rd
*prd
, int prefix_check
)
11548 struct prefix match
;
11549 struct bgp_node
*rn
;
11550 struct bgp_node
*rm
;
11551 struct bgp_path_info
*pi
;
11552 struct bgp_path_info
*pi_temp
;
11554 struct bgp_table
*table
;
11556 /* BGP structure lookup. */
11558 bgp
= bgp_lookup_by_name(view_name
);
11560 vty_out(vty
, "%% Can't find BGP instance %s\n",
11562 return CMD_WARNING
;
11565 bgp
= bgp_get_default();
11567 vty_out(vty
, "%% No BGP process is configured\n");
11568 return CMD_WARNING
;
11572 /* Check IP address argument. */
11573 ret
= str2prefix(ip_str
, &match
);
11575 vty_out(vty
, "%% address is malformed\n");
11576 return CMD_WARNING
;
11579 match
.family
= afi2family(afi
);
11581 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11582 || (safi
== SAFI_EVPN
)) {
11583 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11584 rn
= bgp_route_next(rn
)) {
11585 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11587 table
= bgp_node_get_bgp_table_info(rn
);
11590 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11594 || rm
->p
.prefixlen
== match
.prefixlen
) {
11595 pi
= bgp_node_get_bgp_path_info(rm
);
11597 if (pi
->extra
&& pi
->extra
->damp_info
) {
11598 pi_temp
= pi
->next
;
11599 bgp_damp_info_free(
11600 pi
->extra
->damp_info
,
11608 bgp_unlock_node(rm
);
11611 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11614 || rn
->p
.prefixlen
== match
.prefixlen
) {
11615 pi
= bgp_node_get_bgp_path_info(rn
);
11617 if (pi
->extra
&& pi
->extra
->damp_info
) {
11618 pi_temp
= pi
->next
;
11619 bgp_damp_info_free(
11620 pi
->extra
->damp_info
,
11628 bgp_unlock_node(rn
);
11632 return CMD_SUCCESS
;
11635 DEFUN (clear_ip_bgp_dampening
,
11636 clear_ip_bgp_dampening_cmd
,
11637 "clear ip bgp dampening",
11641 "Clear route flap dampening information\n")
11643 bgp_damp_info_clean();
11644 return CMD_SUCCESS
;
11647 DEFUN (clear_ip_bgp_dampening_prefix
,
11648 clear_ip_bgp_dampening_prefix_cmd
,
11649 "clear ip bgp dampening A.B.C.D/M",
11653 "Clear route flap dampening information\n"
11656 int idx_ipv4_prefixlen
= 4;
11657 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11658 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11661 DEFUN (clear_ip_bgp_dampening_address
,
11662 clear_ip_bgp_dampening_address_cmd
,
11663 "clear ip bgp dampening A.B.C.D",
11667 "Clear route flap dampening information\n"
11668 "Network to clear damping information\n")
11671 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11672 SAFI_UNICAST
, NULL
, 0);
11675 DEFUN (clear_ip_bgp_dampening_address_mask
,
11676 clear_ip_bgp_dampening_address_mask_cmd
,
11677 "clear ip bgp dampening A.B.C.D A.B.C.D",
11681 "Clear route flap dampening information\n"
11682 "Network to clear damping information\n"
11686 int idx_ipv4_2
= 5;
11688 char prefix_str
[BUFSIZ
];
11690 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11693 vty_out(vty
, "%% Inconsistent address and mask\n");
11694 return CMD_WARNING
;
11697 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11701 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
11703 struct vty
*vty
= arg
;
11704 struct peer
*peer
= bucket
->data
;
11705 char buf
[SU_ADDRSTRLEN
];
11707 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
11708 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
11711 DEFUN (show_bgp_peerhash
,
11712 show_bgp_peerhash_cmd
,
11713 "show bgp peerhash",
11716 "Display information about the BGP peerhash\n")
11718 struct list
*instances
= bm
->bgp
;
11719 struct listnode
*node
;
11722 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
11723 vty_out(vty
, "BGP: %s\n", bgp
->name
);
11724 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
11728 return CMD_SUCCESS
;
11731 /* also used for encap safi */
11732 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11733 afi_t afi
, safi_t safi
)
11735 struct bgp_node
*prn
;
11736 struct bgp_node
*rn
;
11737 struct bgp_table
*table
;
11739 struct prefix_rd
*prd
;
11740 struct bgp_static
*bgp_static
;
11741 mpls_label_t label
;
11742 char buf
[SU_ADDRSTRLEN
];
11743 char rdbuf
[RD_ADDRSTRLEN
];
11745 /* Network configuration. */
11746 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11747 prn
= bgp_route_next(prn
)) {
11748 table
= bgp_node_get_bgp_table_info(prn
);
11752 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11753 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11754 if (bgp_static
== NULL
)
11758 prd
= (struct prefix_rd
*)&prn
->p
;
11760 /* "network" configuration display. */
11761 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11762 label
= decode_label(&bgp_static
->label
);
11764 vty_out(vty
, " network %s/%d rd %s",
11765 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11767 p
->prefixlen
, rdbuf
);
11768 if (safi
== SAFI_MPLS_VPN
)
11769 vty_out(vty
, " label %u", label
);
11771 if (bgp_static
->rmap
.name
)
11772 vty_out(vty
, " route-map %s",
11773 bgp_static
->rmap
.name
);
11775 if (bgp_static
->backdoor
)
11776 vty_out(vty
, " backdoor");
11778 vty_out(vty
, "\n");
11783 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11784 afi_t afi
, safi_t safi
)
11786 struct bgp_node
*prn
;
11787 struct bgp_node
*rn
;
11788 struct bgp_table
*table
;
11790 struct prefix_rd
*prd
;
11791 struct bgp_static
*bgp_static
;
11792 char buf
[PREFIX_STRLEN
* 2];
11793 char buf2
[SU_ADDRSTRLEN
];
11794 char rdbuf
[RD_ADDRSTRLEN
];
11796 /* Network configuration. */
11797 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11798 prn
= bgp_route_next(prn
)) {
11799 table
= bgp_node_get_bgp_table_info(prn
);
11803 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11804 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11805 if (bgp_static
== NULL
)
11808 char *macrouter
= NULL
;
11811 if (bgp_static
->router_mac
)
11812 macrouter
= prefix_mac2str(
11813 bgp_static
->router_mac
, NULL
, 0);
11814 if (bgp_static
->eth_s_id
)
11815 esi
= esi2str(bgp_static
->eth_s_id
);
11817 prd
= (struct prefix_rd
*)&prn
->p
;
11819 /* "network" configuration display. */
11820 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11821 if (p
->u
.prefix_evpn
.route_type
== 5) {
11822 char local_buf
[PREFIX_STRLEN
];
11823 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11824 struct prefix_evpn
*)p
)
11828 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11829 local_buf
, PREFIX_STRLEN
);
11830 sprintf(buf
, "%s/%u", local_buf
,
11831 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11833 prefix2str(p
, buf
, sizeof(buf
));
11836 if (bgp_static
->gatewayIp
.family
== AF_INET
11837 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11838 inet_ntop(bgp_static
->gatewayIp
.family
,
11839 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11842 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11844 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11845 decode_label(&bgp_static
->label
), esi
, buf2
,
11849 XFREE(MTYPE_TMP
, macrouter
);
11851 XFREE(MTYPE_TMP
, esi
);
11856 /* Configuration of static route announcement and aggregate
11858 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11861 struct bgp_node
*rn
;
11863 struct bgp_static
*bgp_static
;
11864 struct bgp_aggregate
*bgp_aggregate
;
11865 char buf
[SU_ADDRSTRLEN
];
11867 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11868 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11872 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11873 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11877 /* Network configuration. */
11878 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11879 rn
= bgp_route_next(rn
)) {
11880 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11881 if (bgp_static
== NULL
)
11886 /* "network" configuration display. */
11887 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11888 uint32_t destination
;
11889 struct in_addr netmask
;
11891 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11892 masklen2ip(p
->prefixlen
, &netmask
);
11893 vty_out(vty
, " network %s",
11894 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11897 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11898 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11899 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11900 || p
->u
.prefix4
.s_addr
== 0) {
11901 /* Natural mask is not display. */
11903 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11905 vty_out(vty
, " network %s/%d",
11906 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11911 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11912 vty_out(vty
, " label-index %u",
11913 bgp_static
->label_index
);
11915 if (bgp_static
->rmap
.name
)
11916 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11918 if (bgp_static
->backdoor
)
11919 vty_out(vty
, " backdoor");
11921 vty_out(vty
, "\n");
11924 /* Aggregate-address configuration. */
11925 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11926 rn
= bgp_route_next(rn
)) {
11927 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
11928 if (bgp_aggregate
== NULL
)
11933 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11934 struct in_addr netmask
;
11936 masklen2ip(p
->prefixlen
, &netmask
);
11937 vty_out(vty
, " aggregate-address %s %s",
11938 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11940 inet_ntoa(netmask
));
11942 vty_out(vty
, " aggregate-address %s/%d",
11943 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11948 if (bgp_aggregate
->as_set
)
11949 vty_out(vty
, " as-set");
11951 if (bgp_aggregate
->summary_only
)
11952 vty_out(vty
, " summary-only");
11954 vty_out(vty
, "\n");
11958 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11961 struct bgp_node
*rn
;
11962 struct bgp_distance
*bdistance
;
11964 /* Distance configuration. */
11965 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11966 && bgp
->distance_local
[afi
][safi
]
11967 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11968 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11969 || bgp
->distance_local
[afi
][safi
]
11970 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11971 vty_out(vty
, " distance bgp %d %d %d\n",
11972 bgp
->distance_ebgp
[afi
][safi
],
11973 bgp
->distance_ibgp
[afi
][safi
],
11974 bgp
->distance_local
[afi
][safi
]);
11977 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11978 rn
= bgp_route_next(rn
)) {
11979 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11980 if (bdistance
!= NULL
) {
11981 char buf
[PREFIX_STRLEN
];
11983 vty_out(vty
, " distance %d %s %s\n",
11984 bdistance
->distance
,
11985 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11986 bdistance
->access_list
? bdistance
->access_list
11992 /* Allocate routing table structure and install commands. */
11993 void bgp_route_init(void)
11998 /* Init BGP distance table. */
11999 FOREACH_AFI_SAFI (afi
, safi
)
12000 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12002 /* IPv4 BGP commands. */
12003 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12004 install_element(BGP_NODE
, &bgp_network_cmd
);
12005 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12007 install_element(BGP_NODE
, &aggregate_address_cmd
);
12008 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12009 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12010 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12012 /* IPv4 unicast configuration. */
12013 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12014 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12015 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12017 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12018 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12019 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12020 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12022 /* IPv4 multicast configuration. */
12023 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12024 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12025 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12026 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12027 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12028 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12029 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12031 /* IPv4 labeled-unicast configuration. */
12032 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12033 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12034 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12035 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12036 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12038 install_element(VIEW_NODE
,
12039 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12040 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12041 install_element(VIEW_NODE
,
12042 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12043 #ifdef KEEP_OLD_VPN_COMMANDS
12044 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12045 #endif /* KEEP_OLD_VPN_COMMANDS */
12046 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12047 install_element(VIEW_NODE
,
12048 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
12050 /* BGP dampening clear commands */
12051 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12052 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12054 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12055 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12058 install_element(ENABLE_NODE
,
12059 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12060 #ifdef KEEP_OLD_VPN_COMMANDS
12061 install_element(ENABLE_NODE
,
12062 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12063 #endif /* KEEP_OLD_VPN_COMMANDS */
12065 /* New config IPv6 BGP commands. */
12066 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12067 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12068 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12070 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12071 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12073 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12075 install_element(BGP_NODE
, &bgp_distance_cmd
);
12076 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12077 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12078 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12079 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12080 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12081 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12082 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12083 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12084 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12085 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12086 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12087 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12088 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12089 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12090 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12091 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12092 install_element(BGP_IPV4M_NODE
,
12093 &no_bgp_distance_source_access_list_cmd
);
12094 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12095 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12096 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12097 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12098 install_element(BGP_IPV6_NODE
,
12099 &ipv6_bgp_distance_source_access_list_cmd
);
12100 install_element(BGP_IPV6_NODE
,
12101 &no_ipv6_bgp_distance_source_access_list_cmd
);
12102 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12103 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12104 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12105 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12106 install_element(BGP_IPV6M_NODE
,
12107 &ipv6_bgp_distance_source_access_list_cmd
);
12108 install_element(BGP_IPV6M_NODE
,
12109 &no_ipv6_bgp_distance_source_access_list_cmd
);
12111 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12112 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12113 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12114 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12116 /* IPv4 Multicast Mode */
12117 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12118 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12120 /* Large Communities */
12121 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12122 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12124 /* show bgp ipv4 flowspec detailed */
12125 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12127 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12130 void bgp_route_finish(void)
12135 FOREACH_AFI_SAFI (afi
, safi
) {
12136 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12137 bgp_distance_table
[afi
][safi
] = NULL
;