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_advertise_type5_route(bgp
,
2500 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2501 (!old_select
->extra
|| !old_select
->extra
->parent
))
2502 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2505 /* Clear any route change flags. */
2506 bgp_zebra_clear_route_change_flags(rn
);
2508 /* Reap old select bgp_path_info, if it has been removed */
2509 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2510 bgp_path_info_reap(rn
, old_select
);
2512 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2516 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2518 struct bgp_process_queue
*pqnode
= data
;
2519 struct bgp
*bgp
= pqnode
->bgp
;
2520 struct bgp_table
*table
;
2521 struct bgp_node
*rn
;
2524 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2525 bgp_process_main_one(bgp
, NULL
, 0, 0);
2526 /* should always have dedicated wq call */
2527 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2531 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2532 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2533 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2534 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2535 table
= bgp_node_table(rn
);
2536 /* note, new RNs may be added as part of processing */
2537 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2539 bgp_unlock_node(rn
);
2540 bgp_table_unlock(table
);
2546 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2548 struct bgp_process_queue
*pqnode
= data
;
2550 bgp_unlock(pqnode
->bgp
);
2552 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2555 void bgp_process_queue_init(void)
2557 if (!bm
->process_main_queue
)
2558 bm
->process_main_queue
=
2559 work_queue_new(bm
->master
, "process_main_queue");
2561 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2562 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2563 bm
->process_main_queue
->spec
.max_retries
= 0;
2564 bm
->process_main_queue
->spec
.hold
= 50;
2565 /* Use a higher yield value of 50ms for main queue processing */
2566 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2569 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2571 struct bgp_process_queue
*pqnode
;
2573 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2574 sizeof(struct bgp_process_queue
));
2576 /* unlocked in bgp_processq_del */
2577 pqnode
->bgp
= bgp_lock(bgp
);
2578 STAILQ_INIT(&pqnode
->pqueue
);
2583 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2585 #define ARBITRARY_PROCESS_QLEN 10000
2586 struct work_queue
*wq
= bm
->process_main_queue
;
2587 struct bgp_process_queue
*pqnode
;
2588 int pqnode_reuse
= 0;
2590 /* already scheduled for processing? */
2591 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2597 /* Add route nodes to an existing work queue item until reaching the
2598 limit only if is from the same BGP view and it's not an EOIU marker
2600 if (work_queue_item_count(wq
)) {
2601 struct work_queue_item
*item
= work_queue_last_item(wq
);
2602 pqnode
= item
->data
;
2604 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2605 || pqnode
->bgp
!= bgp
2606 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2607 pqnode
= bgp_processq_alloc(bgp
);
2611 pqnode
= bgp_processq_alloc(bgp
);
2612 /* all unlocked in bgp_process_wq */
2613 bgp_table_lock(bgp_node_table(rn
));
2615 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2618 /* can't be enqueued twice */
2619 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2620 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2624 work_queue_add(wq
, pqnode
);
2629 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2631 struct bgp_process_queue
*pqnode
;
2633 if (bm
->process_main_queue
== NULL
)
2636 pqnode
= bgp_processq_alloc(bgp
);
2638 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2639 work_queue_add(bm
->process_main_queue
, pqnode
);
2642 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2646 peer
= THREAD_ARG(thread
);
2647 peer
->t_pmax_restart
= NULL
;
2649 if (bgp_debug_neighbor_events(peer
))
2651 "%s Maximum-prefix restart timer expired, restore peering",
2654 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2655 zlog_debug("%s: %s peer_clear failed",
2656 __PRETTY_FUNCTION__
, peer
->host
);
2661 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2665 iana_safi_t pkt_safi
;
2667 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2670 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2671 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2672 PEER_STATUS_PREFIX_LIMIT
)
2677 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2679 afi_safi_print(afi
, safi
), peer
->host
,
2680 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2681 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2683 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2684 PEER_FLAG_MAX_PREFIX_WARNING
))
2687 /* Convert AFI, SAFI to values for packet. */
2688 pkt_afi
= afi_int2iana(afi
);
2689 pkt_safi
= safi_int2iana(safi
);
2693 ndata
[0] = (pkt_afi
>> 8);
2695 ndata
[2] = pkt_safi
;
2696 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2697 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2698 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2699 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2701 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2702 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2703 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2707 /* Dynamic peers will just close their connection. */
2708 if (peer_dynamic_neighbor(peer
))
2711 /* restart timer start */
2712 if (peer
->pmax_restart
[afi
][safi
]) {
2713 peer
->v_pmax_restart
=
2714 peer
->pmax_restart
[afi
][safi
] * 60;
2716 if (bgp_debug_neighbor_events(peer
))
2718 "%s Maximum-prefix restart timer started for %d secs",
2719 peer
->host
, peer
->v_pmax_restart
);
2721 BGP_TIMER_ON(peer
->t_pmax_restart
,
2722 bgp_maximum_prefix_restart_timer
,
2723 peer
->v_pmax_restart
);
2728 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2729 PEER_STATUS_PREFIX_LIMIT
);
2731 if (peer
->pcount
[afi
][safi
]
2732 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2733 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2734 PEER_STATUS_PREFIX_THRESHOLD
)
2739 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2740 afi_safi_print(afi
, safi
), peer
->host
,
2741 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2742 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2743 PEER_STATUS_PREFIX_THRESHOLD
);
2745 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2746 PEER_STATUS_PREFIX_THRESHOLD
);
2750 /* Unconditionally remove the route from the RIB, without taking
2751 * damping into consideration (eg, because the session went down)
2753 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2754 struct peer
*peer
, afi_t afi
, safi_t safi
)
2756 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2758 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2759 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2761 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2764 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2765 struct peer
*peer
, afi_t afi
, safi_t safi
,
2766 struct prefix_rd
*prd
)
2768 /* apply dampening, if result is suppressed, we'll be retaining
2769 * the bgp_path_info in the RIB for historical reference.
2771 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2772 && peer
->sort
== BGP_PEER_EBGP
)
2773 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2774 == BGP_DAMP_SUPPRESSED
) {
2775 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2781 if (safi
== SAFI_MPLS_VPN
) {
2782 struct bgp_node
*prn
= NULL
;
2783 struct bgp_table
*table
= NULL
;
2785 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2786 (struct prefix
*)prd
);
2787 if (bgp_node_has_bgp_path_info_data(prn
)) {
2788 table
= bgp_node_get_bgp_table_info(prn
);
2790 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2791 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2793 bgp_unlock_node(prn
);
2795 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2796 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2798 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2799 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2805 /* If this is an EVPN route, process for un-import. */
2806 if (safi
== SAFI_EVPN
)
2807 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2809 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2812 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2813 struct peer
*peer
, struct attr
*attr
,
2814 struct bgp_node
*rn
)
2816 struct bgp_path_info
*new;
2818 /* Make new BGP info. */
2819 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2821 new->instance
= instance
;
2822 new->sub_type
= sub_type
;
2825 new->uptime
= bgp_clock();
2830 static void overlay_index_update(struct attr
*attr
,
2831 struct eth_segment_id
*eth_s_id
,
2832 union gw_addr
*gw_ip
)
2837 if (eth_s_id
== NULL
) {
2838 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2839 sizeof(struct eth_segment_id
));
2841 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2842 sizeof(struct eth_segment_id
));
2844 if (gw_ip
== NULL
) {
2845 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2847 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2848 sizeof(union gw_addr
));
2852 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2853 struct eth_segment_id
*eth_s_id
,
2854 union gw_addr
*gw_ip
)
2856 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2857 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2859 struct eth_segment_id esi
;
2863 if (afi
!= AFI_L2VPN
)
2866 memset(&temp
, 0, sizeof(temp
));
2867 path_eth_s_id
= &temp
.esi
;
2868 path_gw_ip
= &temp
.ip
;
2870 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2873 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2874 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2877 if (gw_ip
== NULL
) {
2878 memset(&temp
, 0, sizeof(temp
));
2879 path_gw_ip_remote
= &temp
.ip
;
2881 path_gw_ip_remote
= gw_ip
;
2883 if (eth_s_id
== NULL
) {
2884 memset(&temp
, 0, sizeof(temp
));
2885 path_eth_s_id_remote
= &temp
.esi
;
2887 path_eth_s_id_remote
= eth_s_id
;
2889 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2892 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2893 sizeof(struct eth_segment_id
));
2896 /* Check if received nexthop is valid or not. */
2897 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2902 /* Only validated for unicast and multicast currently. */
2903 /* Also valid for EVPN where the nexthop is an IP address. */
2904 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2907 /* If NEXT_HOP is present, validate it. */
2908 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2909 if (attr
->nexthop
.s_addr
== 0
2910 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2911 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2915 /* If MP_NEXTHOP is present, validate it. */
2916 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2917 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2918 * it is not an IPv6 link-local address.
2920 if (attr
->mp_nexthop_len
) {
2921 switch (attr
->mp_nexthop_len
) {
2922 case BGP_ATTR_NHLEN_IPV4
:
2923 case BGP_ATTR_NHLEN_VPNV4
:
2924 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2925 || IPV4_CLASS_DE(ntohl(
2926 attr
->mp_nexthop_global_in
.s_addr
))
2927 || bgp_nexthop_self(bgp
,
2928 attr
->mp_nexthop_global_in
));
2931 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2932 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2933 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2934 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2935 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2936 || IN6_IS_ADDR_MULTICAST(
2937 &attr
->mp_nexthop_global
));
2949 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2950 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2951 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2952 uint32_t num_labels
, int soft_reconfig
,
2953 struct bgp_route_evpn
*evpn
)
2956 int aspath_loop_count
= 0;
2957 struct bgp_node
*rn
;
2959 struct attr new_attr
;
2960 struct attr
*attr_new
;
2961 struct bgp_path_info
*pi
;
2962 struct bgp_path_info
*new;
2963 struct bgp_path_info_extra
*extra
;
2965 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2967 int do_loop_check
= 1;
2968 int has_valid_label
= 0;
2970 int vnc_implicit_withdraw
= 0;
2974 memset(&new_attr
, 0, sizeof(struct attr
));
2975 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2976 new_attr
.label
= MPLS_INVALID_LABEL
;
2979 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2980 /* TODO: Check to see if we can get rid of "is_valid_label" */
2981 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2982 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2984 has_valid_label
= bgp_is_valid_label(label
);
2986 /* When peer's soft reconfiguration enabled. Record input packet in
2989 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2990 && peer
!= bgp
->peer_self
)
2991 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2993 /* Check previously received route. */
2994 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
2995 if (pi
->peer
== peer
&& pi
->type
== type
2996 && pi
->sub_type
== sub_type
2997 && pi
->addpath_rx_id
== addpath_id
)
3000 /* AS path local-as loop check. */
3001 if (peer
->change_local_as
) {
3002 if (peer
->allowas_in
[afi
][safi
])
3003 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3004 else if (!CHECK_FLAG(peer
->flags
,
3005 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3006 aspath_loop_count
= 1;
3008 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3009 > aspath_loop_count
) {
3010 reason
= "as-path contains our own AS;";
3015 /* If the peer is configured for "allowas-in origin" and the last ASN in
3017 * as-path is our ASN then we do not need to call aspath_loop_check
3019 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3020 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3023 /* AS path loop check. */
3024 if (do_loop_check
) {
3025 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3026 > peer
->allowas_in
[afi
][safi
]
3027 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3028 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3029 > peer
->allowas_in
[afi
][safi
])) {
3030 reason
= "as-path contains our own AS;";
3035 /* Route reflector originator ID check. */
3036 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3037 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3038 reason
= "originator is us;";
3042 /* Route reflector cluster ID check. */
3043 if (bgp_cluster_filter(peer
, attr
)) {
3044 reason
= "reflected from the same cluster;";
3048 /* Apply incoming filter. */
3049 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3054 bgp_attr_dup(&new_attr
, attr
);
3056 /* Apply incoming route-map.
3057 * NB: new_attr may now contain newly allocated values from route-map
3059 * commands, so we need bgp_attr_flush in the error paths, until we
3061 * the attr (which takes over the memory references) */
3062 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3064 reason
= "route-map;";
3065 bgp_attr_flush(&new_attr
);
3069 if (peer
->sort
== BGP_PEER_EBGP
) {
3071 /* If we receive the graceful-shutdown community from an eBGP
3072 * peer we must lower local-preference */
3073 if (new_attr
.community
3074 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3075 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3076 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3078 /* If graceful-shutdown is configured then add the GSHUT
3079 * community to all paths received from eBGP peers */
3080 } else if (bgp_flag_check(peer
->bgp
,
3081 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3082 bgp_attr_add_gshut_community(&new_attr
);
3086 /* next hop check. */
3087 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3088 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3089 reason
= "martian or self next-hop;";
3090 bgp_attr_flush(&new_attr
);
3094 if (bgp_mac_entry_exists(p
)) {
3095 reason
= "self mac;";
3099 attr_new
= bgp_attr_intern(&new_attr
);
3101 /* If the update is implicit withdraw. */
3103 pi
->uptime
= bgp_clock();
3104 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3106 /* Same attribute comes in. */
3107 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3108 && attrhash_cmp(pi
->attr
, attr_new
)
3109 && (!has_valid_label
3110 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3111 num_labels
* sizeof(mpls_label_t
))
3113 && (overlay_index_equal(
3114 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3115 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3116 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3117 BGP_CONFIG_DAMPENING
)
3118 && peer
->sort
== BGP_PEER_EBGP
3119 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3120 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3121 bgp_debug_rdpfxpath2str(
3122 afi
, safi
, prd
, p
, label
,
3123 num_labels
, addpath_id
? 1 : 0,
3124 addpath_id
, pfx_buf
,
3126 zlog_debug("%s rcvd %s", peer
->host
,
3130 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3131 != BGP_DAMP_SUPPRESSED
) {
3132 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3134 bgp_process(bgp
, rn
, afi
, safi
);
3136 } else /* Duplicate - odd */
3138 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3139 if (!peer
->rcvd_attr_printed
) {
3141 "%s rcvd UPDATE w/ attr: %s",
3143 peer
->rcvd_attr_str
);
3144 peer
->rcvd_attr_printed
= 1;
3147 bgp_debug_rdpfxpath2str(
3148 afi
, safi
, prd
, p
, label
,
3149 num_labels
, addpath_id
? 1 : 0,
3150 addpath_id
, pfx_buf
,
3153 "%s rcvd %s...duplicate ignored",
3154 peer
->host
, pfx_buf
);
3157 /* graceful restart STALE flag unset. */
3158 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3159 bgp_path_info_unset_flag(
3160 rn
, pi
, BGP_PATH_STALE
);
3161 bgp_process(bgp
, rn
, afi
, safi
);
3165 bgp_unlock_node(rn
);
3166 bgp_attr_unintern(&attr_new
);
3171 /* Withdraw/Announce before we fully processed the withdraw */
3172 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3173 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3174 bgp_debug_rdpfxpath2str(
3175 afi
, safi
, prd
, p
, label
, num_labels
,
3176 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3179 "%s rcvd %s, flapped quicker than processing",
3180 peer
->host
, pfx_buf
);
3183 bgp_path_info_restore(rn
, pi
);
3186 /* Received Logging. */
3187 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3188 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3189 num_labels
, addpath_id
? 1 : 0,
3190 addpath_id
, pfx_buf
,
3192 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3195 /* graceful restart STALE flag unset. */
3196 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3197 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3199 /* The attribute is changed. */
3200 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3202 /* implicit withdraw, decrement aggregate and pcount here.
3203 * only if update is accepted, they'll increment below.
3205 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3207 /* Update bgp route dampening information. */
3208 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3209 && peer
->sort
== BGP_PEER_EBGP
) {
3210 /* This is implicit withdraw so we should update
3213 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3214 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3217 if (safi
== SAFI_MPLS_VPN
) {
3218 struct bgp_node
*prn
= NULL
;
3219 struct bgp_table
*table
= NULL
;
3221 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3222 (struct prefix
*)prd
);
3223 if (bgp_node_has_bgp_path_info_data(prn
)) {
3224 table
= bgp_node_get_bgp_table_info(prn
);
3226 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3227 bgp
, prd
, table
, p
, pi
);
3229 bgp_unlock_node(prn
);
3231 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3232 && (safi
== SAFI_UNICAST
)) {
3233 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3235 * Implicit withdraw case.
3237 ++vnc_implicit_withdraw
;
3238 vnc_import_bgp_del_route(bgp
, p
, pi
);
3239 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3244 /* Special handling for EVPN update of an existing route. If the
3245 * extended community attribute has changed, we need to
3247 * the route using its existing extended community. It will be
3248 * subsequently processed for import with the new extended
3251 if (safi
== SAFI_EVPN
&& !same_attr
) {
3253 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3255 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3258 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3259 attr_new
->ecommunity
);
3261 if (bgp_debug_update(peer
, p
, NULL
, 1))
3263 "Change in EXT-COMM, existing %s new %s",
3265 pi
->attr
->ecommunity
),
3267 attr_new
->ecommunity
));
3268 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3274 /* Update to new attribute. */
3275 bgp_attr_unintern(&pi
->attr
);
3276 pi
->attr
= attr_new
;
3278 /* Update MPLS label */
3279 if (has_valid_label
) {
3280 extra
= bgp_path_info_extra_get(pi
);
3281 if (extra
->label
!= label
) {
3282 memcpy(&extra
->label
, label
,
3283 num_labels
* sizeof(mpls_label_t
));
3284 extra
->num_labels
= num_labels
;
3286 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3287 bgp_set_valid_label(&extra
->label
[0]);
3291 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3292 && (safi
== SAFI_UNICAST
)) {
3293 if (vnc_implicit_withdraw
) {
3295 * Add back the route with its new attributes
3297 * The route is still selected, until the route
3299 * queued by bgp_process actually runs. We have
3301 * update to the VNC side immediately to avoid
3303 * configuration changes (e.g., route-map
3305 * trigger re-importation of the entire RIB.
3307 vnc_import_bgp_add_route(bgp
, p
, pi
);
3308 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3312 /* Update Overlay Index */
3313 if (afi
== AFI_L2VPN
) {
3314 overlay_index_update(
3315 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3316 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3319 /* Update bgp route dampening information. */
3320 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3321 && peer
->sort
== BGP_PEER_EBGP
) {
3322 /* Now we do normal update dampening. */
3323 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3324 if (ret
== BGP_DAMP_SUPPRESSED
) {
3325 bgp_unlock_node(rn
);
3330 /* Nexthop reachability check - for unicast and
3331 * labeled-unicast.. */
3332 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3333 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3334 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3335 && !CHECK_FLAG(peer
->flags
,
3336 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3338 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3343 struct bgp
*bgp_nexthop
= bgp
;
3345 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3346 bgp_nexthop
= pi
->extra
->bgp_orig
;
3348 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3350 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3351 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3353 if (BGP_DEBUG(nht
, NHT
)) {
3354 char buf1
[INET6_ADDRSTRLEN
];
3356 (const void *)&attr_new
3358 buf1
, INET6_ADDRSTRLEN
);
3359 zlog_debug("%s(%s): NH unresolved",
3360 __FUNCTION__
, buf1
);
3362 bgp_path_info_unset_flag(rn
, pi
,
3366 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3369 if (safi
== SAFI_MPLS_VPN
) {
3370 struct bgp_node
*prn
= NULL
;
3371 struct bgp_table
*table
= NULL
;
3373 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3374 (struct prefix
*)prd
);
3375 if (bgp_node_has_bgp_path_info_data(prn
)) {
3376 table
= bgp_node_get_bgp_table_info(prn
);
3378 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3379 bgp
, prd
, table
, p
, pi
);
3381 bgp_unlock_node(prn
);
3385 /* If this is an EVPN route and some attribute has changed,
3387 * route for import. If the extended community has changed, we
3389 * have done the un-import earlier and the import would result
3391 * route getting injected into appropriate L2 VNIs. If it is
3393 * some other attribute change, the import will result in
3395 * the attributes for the route in the VNI(s).
3397 if (safi
== SAFI_EVPN
&& !same_attr
)
3398 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3400 /* Process change. */
3401 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3403 bgp_process(bgp
, rn
, afi
, safi
);
3404 bgp_unlock_node(rn
);
3406 if (SAFI_UNICAST
== safi
3407 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3408 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3410 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3412 if ((SAFI_MPLS_VPN
== safi
)
3413 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3415 vpn_leak_to_vrf_update(bgp
, pi
);
3419 if (SAFI_MPLS_VPN
== safi
) {
3420 mpls_label_t label_decoded
= decode_label(label
);
3422 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3423 type
, sub_type
, &label_decoded
);
3425 if (SAFI_ENCAP
== safi
) {
3426 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3427 type
, sub_type
, NULL
);
3432 } // End of implicit withdraw
3434 /* Received Logging. */
3435 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3436 if (!peer
->rcvd_attr_printed
) {
3437 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3438 peer
->rcvd_attr_str
);
3439 peer
->rcvd_attr_printed
= 1;
3442 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3443 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3445 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3448 /* Make new BGP info. */
3449 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3451 /* Update MPLS label */
3452 if (has_valid_label
) {
3453 extra
= bgp_path_info_extra_get(new);
3454 if (extra
->label
!= label
) {
3455 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3456 extra
->num_labels
= num_labels
;
3458 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3459 bgp_set_valid_label(&extra
->label
[0]);
3462 /* Update Overlay Index */
3463 if (afi
== AFI_L2VPN
) {
3464 overlay_index_update(new->attr
,
3465 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3466 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3468 /* Nexthop reachability check. */
3469 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3470 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3471 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3472 && !CHECK_FLAG(peer
->flags
,
3473 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3474 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3479 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3480 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3481 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3483 if (BGP_DEBUG(nht
, NHT
)) {
3484 char buf1
[INET6_ADDRSTRLEN
];
3486 (const void *)&attr_new
->nexthop
,
3487 buf1
, INET6_ADDRSTRLEN
);
3488 zlog_debug("%s(%s): NH unresolved",
3489 __FUNCTION__
, buf1
);
3491 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3494 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3497 new->addpath_rx_id
= addpath_id
;
3499 /* Increment prefix */
3500 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3502 /* Register new BGP information. */
3503 bgp_path_info_add(rn
, new);
3505 /* route_node_get lock */
3506 bgp_unlock_node(rn
);
3509 if (safi
== SAFI_MPLS_VPN
) {
3510 struct bgp_node
*prn
= NULL
;
3511 struct bgp_table
*table
= NULL
;
3513 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3514 if (bgp_node_has_bgp_path_info_data(prn
)) {
3515 table
= bgp_node_get_bgp_table_info(prn
);
3517 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3518 bgp
, prd
, table
, p
, new);
3520 bgp_unlock_node(prn
);
3524 /* If maximum prefix count is configured and current prefix
3526 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3529 /* If this is an EVPN route, process for import. */
3530 if (safi
== SAFI_EVPN
)
3531 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3533 /* Process change. */
3534 bgp_process(bgp
, rn
, afi
, safi
);
3536 if (SAFI_UNICAST
== safi
3537 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3538 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3539 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3541 if ((SAFI_MPLS_VPN
== safi
)
3542 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3544 vpn_leak_to_vrf_update(bgp
, new);
3547 if (SAFI_MPLS_VPN
== safi
) {
3548 mpls_label_t label_decoded
= decode_label(label
);
3550 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3551 sub_type
, &label_decoded
);
3553 if (SAFI_ENCAP
== safi
) {
3554 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3561 /* This BGP update is filtered. Log the reason then update BGP
3564 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3565 if (!peer
->rcvd_attr_printed
) {
3566 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3567 peer
->rcvd_attr_str
);
3568 peer
->rcvd_attr_printed
= 1;
3571 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3572 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3574 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3575 peer
->host
, pfx_buf
, reason
);
3579 /* If this is an EVPN route, un-import it as it is now filtered.
3581 if (safi
== SAFI_EVPN
)
3582 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3584 if (SAFI_UNICAST
== safi
3585 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3586 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3588 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3590 if ((SAFI_MPLS_VPN
== safi
)
3591 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3593 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3596 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3599 bgp_unlock_node(rn
);
3603 * Filtered update is treated as an implicit withdrawal (see
3605 * a few lines above)
3607 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3608 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3616 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3617 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3618 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3619 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3622 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3623 struct bgp_node
*rn
;
3624 struct bgp_path_info
*pi
;
3627 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3628 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3636 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3638 /* If peer is soft reconfiguration enabled. Record input packet for
3639 * further calculation.
3641 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3642 * routes that are filtered. This tanks out Quagga RS pretty badly due
3644 * the iteration over all RS clients.
3645 * Since we need to remove the entry from adj_in anyway, do that first
3647 * if there was no entry, we don't need to do anything more.
3649 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3650 && peer
!= bgp
->peer_self
)
3651 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3652 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3653 bgp_debug_rdpfxpath2str(
3654 afi
, safi
, prd
, p
, label
, num_labels
,
3655 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3658 "%s withdrawing route %s not in adj-in",
3659 peer
->host
, pfx_buf
);
3661 bgp_unlock_node(rn
);
3665 /* Lookup withdrawn route. */
3666 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3667 if (pi
->peer
== peer
&& pi
->type
== type
3668 && pi
->sub_type
== sub_type
3669 && pi
->addpath_rx_id
== addpath_id
)
3673 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3674 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3675 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3677 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3681 /* Withdraw specified route from routing table. */
3682 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3683 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3684 if (SAFI_UNICAST
== safi
3685 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3686 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3687 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3689 if ((SAFI_MPLS_VPN
== safi
)
3690 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3692 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3694 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3695 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3696 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3698 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3701 /* Unlock bgp_node_get() lock. */
3702 bgp_unlock_node(rn
);
3707 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3710 struct update_subgroup
*subgrp
;
3711 subgrp
= peer_subgroup(peer
, afi
, safi
);
3712 subgroup_default_originate(subgrp
, withdraw
);
3717 * bgp_stop_announce_route_timer
3719 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3721 if (!paf
->t_announce_route
)
3724 THREAD_TIMER_OFF(paf
->t_announce_route
);
3728 * bgp_announce_route_timer_expired
3730 * Callback that is invoked when the route announcement timer for a
3733 static int bgp_announce_route_timer_expired(struct thread
*t
)
3735 struct peer_af
*paf
;
3738 paf
= THREAD_ARG(t
);
3741 if (peer
->status
!= Established
)
3744 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3747 peer_af_announce_route(paf
, 1);
3752 * bgp_announce_route
3754 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3756 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3758 struct peer_af
*paf
;
3759 struct update_subgroup
*subgrp
;
3761 paf
= peer_af_find(peer
, afi
, safi
);
3764 subgrp
= PAF_SUBGRP(paf
);
3767 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3768 * or a refresh has already been triggered.
3770 if (!subgrp
|| paf
->t_announce_route
)
3774 * Start a timer to stagger/delay the announce. This serves
3775 * two purposes - announcement can potentially be combined for
3776 * multiple peers and the announcement doesn't happen in the
3779 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3780 (subgrp
->peer_count
== 1)
3781 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3782 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3783 &paf
->t_announce_route
);
3787 * Announce routes from all AF tables to a peer.
3789 * This should ONLY be called when there is a need to refresh the
3790 * routes to the peer based on a policy change for this peer alone
3791 * or a route refresh request received from the peer.
3792 * The operation will result in splitting the peer from its existing
3793 * subgroups and putting it in new subgroups.
3795 void bgp_announce_route_all(struct peer
*peer
)
3800 FOREACH_AFI_SAFI (afi
, safi
)
3801 bgp_announce_route(peer
, afi
, safi
);
3804 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3805 struct bgp_table
*table
,
3806 struct prefix_rd
*prd
)
3809 struct bgp_node
*rn
;
3810 struct bgp_adj_in
*ain
;
3813 table
= peer
->bgp
->rib
[afi
][safi
];
3815 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3816 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3817 if (ain
->peer
!= peer
)
3820 struct bgp_path_info
*pi
=
3821 bgp_node_get_bgp_path_info(rn
);
3822 uint32_t num_labels
= 0;
3823 mpls_label_t
*label_pnt
= NULL
;
3824 struct bgp_route_evpn evpn
;
3826 if (pi
&& pi
->extra
)
3827 num_labels
= pi
->extra
->num_labels
;
3829 label_pnt
= &pi
->extra
->label
[0];
3831 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3834 memset(&evpn
, 0, sizeof(evpn
));
3836 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3837 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3838 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3839 num_labels
, 1, &evpn
);
3842 bgp_unlock_node(rn
);
3848 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3850 struct bgp_node
*rn
;
3851 struct bgp_table
*table
;
3853 if (peer
->status
!= Established
)
3856 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3857 && (safi
!= SAFI_EVPN
))
3858 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3860 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3861 rn
= bgp_route_next(rn
)) {
3862 table
= bgp_node_get_bgp_table_info(rn
);
3863 if (table
!= NULL
) {
3864 struct prefix_rd prd
;
3866 prd
.family
= AF_UNSPEC
;
3868 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3870 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3877 struct bgp_clear_node_queue
{
3878 struct bgp_node
*rn
;
3881 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3883 struct bgp_clear_node_queue
*cnq
= data
;
3884 struct bgp_node
*rn
= cnq
->rn
;
3885 struct peer
*peer
= wq
->spec
.data
;
3886 struct bgp_path_info
*pi
;
3888 afi_t afi
= bgp_node_table(rn
)->afi
;
3889 safi_t safi
= bgp_node_table(rn
)->safi
;
3894 /* It is possible that we have multiple paths for a prefix from a peer
3895 * if that peer is using AddPath.
3897 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3898 if (pi
->peer
!= peer
)
3901 /* graceful restart STALE flag set. */
3902 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3903 && peer
->nsf
[afi
][safi
]
3904 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3905 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3906 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3908 /* If this is an EVPN route, process for
3910 if (safi
== SAFI_EVPN
)
3911 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3913 /* Handle withdraw for VRF route-leaking and L3VPN */
3914 if (SAFI_UNICAST
== safi
3915 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3916 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3917 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3920 if (SAFI_MPLS_VPN
== safi
&&
3921 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3922 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3925 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3931 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3933 struct bgp_clear_node_queue
*cnq
= data
;
3934 struct bgp_node
*rn
= cnq
->rn
;
3935 struct bgp_table
*table
= bgp_node_table(rn
);
3937 bgp_unlock_node(rn
);
3938 bgp_table_unlock(table
);
3939 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3942 static void bgp_clear_node_complete(struct work_queue
*wq
)
3944 struct peer
*peer
= wq
->spec
.data
;
3946 /* Tickle FSM to start moving again */
3947 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3949 peer_unlock(peer
); /* bgp_clear_route */
3952 static void bgp_clear_node_queue_init(struct peer
*peer
)
3954 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3956 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3957 #undef CLEAR_QUEUE_NAME_LEN
3959 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3960 peer
->clear_node_queue
->spec
.hold
= 10;
3961 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3962 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3963 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3964 peer
->clear_node_queue
->spec
.max_retries
= 0;
3966 /* we only 'lock' this peer reference when the queue is actually active
3968 peer
->clear_node_queue
->spec
.data
= peer
;
3971 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3972 struct bgp_table
*table
)
3974 struct bgp_node
*rn
;
3975 int force
= bm
->process_main_queue
? 0 : 1;
3978 table
= peer
->bgp
->rib
[afi
][safi
];
3980 /* If still no table => afi/safi isn't configured at all or smth. */
3984 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3985 struct bgp_path_info
*pi
, *next
;
3986 struct bgp_adj_in
*ain
;
3987 struct bgp_adj_in
*ain_next
;
3989 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3990 * queued for every clearing peer, regardless of whether it is
3991 * relevant to the peer at hand.
3993 * Overview: There are 3 different indices which need to be
3994 * scrubbed, potentially, when a peer is removed:
3996 * 1 peer's routes visible via the RIB (ie accepted routes)
3997 * 2 peer's routes visible by the (optional) peer's adj-in index
3998 * 3 other routes visible by the peer's adj-out index
4000 * 3 there is no hurry in scrubbing, once the struct peer is
4001 * removed from bgp->peer, we could just GC such deleted peer's
4002 * adj-outs at our leisure.
4004 * 1 and 2 must be 'scrubbed' in some way, at least made
4005 * invisible via RIB index before peer session is allowed to be
4006 * brought back up. So one needs to know when such a 'search' is
4011 * - there'd be a single global queue or a single RIB walker
4012 * - rather than tracking which route_nodes still need to be
4013 * examined on a peer basis, we'd track which peers still
4016 * Given that our per-peer prefix-counts now should be reliable,
4017 * this may actually be achievable. It doesn't seem to be a huge
4018 * problem at this time,
4020 * It is possible that we have multiple paths for a prefix from
4022 * if that peer is using AddPath.
4026 ain_next
= ain
->next
;
4028 if (ain
->peer
== peer
) {
4029 bgp_adj_in_remove(rn
, ain
);
4030 bgp_unlock_node(rn
);
4036 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4038 if (pi
->peer
!= peer
)
4042 bgp_path_info_reap(rn
, pi
);
4044 struct bgp_clear_node_queue
*cnq
;
4046 /* both unlocked in bgp_clear_node_queue_del */
4047 bgp_table_lock(bgp_node_table(rn
));
4050 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4051 sizeof(struct bgp_clear_node_queue
));
4053 work_queue_add(peer
->clear_node_queue
, cnq
);
4061 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4063 struct bgp_node
*rn
;
4064 struct bgp_table
*table
;
4066 if (peer
->clear_node_queue
== NULL
)
4067 bgp_clear_node_queue_init(peer
);
4069 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4070 * Idle until it receives a Clearing_Completed event. This protects
4071 * against peers which flap faster than we can we clear, which could
4074 * a) race with routes from the new session being installed before
4075 * clear_route_node visits the node (to delete the route of that
4077 * b) resource exhaustion, clear_route_node likely leads to an entry
4078 * on the process_main queue. Fast-flapping could cause that queue
4082 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4083 * the unlock will happen upon work-queue completion; other wise, the
4084 * unlock happens at the end of this function.
4086 if (!peer
->clear_node_queue
->thread
)
4089 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4090 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4092 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4093 rn
= bgp_route_next(rn
)) {
4094 table
= bgp_node_get_bgp_table_info(rn
);
4098 bgp_clear_route_table(peer
, afi
, safi
, table
);
4101 /* unlock if no nodes got added to the clear-node-queue. */
4102 if (!peer
->clear_node_queue
->thread
)
4106 void bgp_clear_route_all(struct peer
*peer
)
4111 FOREACH_AFI_SAFI (afi
, safi
)
4112 bgp_clear_route(peer
, afi
, safi
);
4115 rfapiProcessPeerDown(peer
);
4119 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4121 struct bgp_table
*table
;
4122 struct bgp_node
*rn
;
4123 struct bgp_adj_in
*ain
;
4124 struct bgp_adj_in
*ain_next
;
4126 table
= peer
->bgp
->rib
[afi
][safi
];
4128 /* It is possible that we have multiple paths for a prefix from a peer
4129 * if that peer is using AddPath.
4131 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4135 ain_next
= ain
->next
;
4137 if (ain
->peer
== peer
) {
4138 bgp_adj_in_remove(rn
, ain
);
4139 bgp_unlock_node(rn
);
4147 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4149 struct bgp_node
*rn
;
4150 struct bgp_path_info
*pi
;
4151 struct bgp_table
*table
;
4153 if (safi
== SAFI_MPLS_VPN
) {
4154 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4155 rn
= bgp_route_next(rn
)) {
4156 struct bgp_node
*rm
;
4158 /* look for neighbor in tables */
4159 table
= bgp_node_get_bgp_table_info(rn
);
4163 for (rm
= bgp_table_top(table
); rm
;
4164 rm
= bgp_route_next(rm
))
4165 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4167 if (pi
->peer
!= peer
)
4169 if (!CHECK_FLAG(pi
->flags
,
4173 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4178 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4179 rn
= bgp_route_next(rn
))
4180 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4182 if (pi
->peer
!= peer
)
4184 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4186 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4192 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4194 if (peer
->sort
== BGP_PEER_EBGP
4195 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4196 || FILTER_LIST_OUT_NAME(filter
)
4197 || DISTRIBUTE_OUT_NAME(filter
)))
4202 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4204 if (peer
->sort
== BGP_PEER_EBGP
4205 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4206 || FILTER_LIST_IN_NAME(filter
)
4207 || DISTRIBUTE_IN_NAME(filter
)))
4212 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4215 struct bgp_node
*rn
;
4216 struct bgp_path_info
*pi
;
4217 struct bgp_path_info
*next
;
4219 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4220 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4222 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4223 && pi
->type
== ZEBRA_ROUTE_BGP
4224 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4225 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4226 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4228 if (bgp_fibupd_safi(safi
))
4229 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4231 bgp_path_info_reap(rn
, pi
);
4236 /* Delete all kernel routes. */
4237 void bgp_cleanup_routes(struct bgp
*bgp
)
4240 struct bgp_node
*rn
;
4241 struct bgp_table
*table
;
4243 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4244 if (afi
== AFI_L2VPN
)
4246 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4249 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4251 if (afi
!= AFI_L2VPN
) {
4253 safi
= SAFI_MPLS_VPN
;
4254 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4255 rn
= bgp_route_next(rn
)) {
4256 table
= bgp_node_get_bgp_table_info(rn
);
4257 if (table
!= NULL
) {
4258 bgp_cleanup_table(bgp
, table
, safi
);
4259 bgp_table_finish(&table
);
4260 bgp_node_set_bgp_table_info(rn
, NULL
);
4261 bgp_unlock_node(rn
);
4265 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4266 rn
= bgp_route_next(rn
)) {
4267 table
= bgp_node_get_bgp_table_info(rn
);
4268 if (table
!= NULL
) {
4269 bgp_cleanup_table(bgp
, table
, safi
);
4270 bgp_table_finish(&table
);
4271 bgp_node_set_bgp_table_info(rn
, NULL
);
4272 bgp_unlock_node(rn
);
4277 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4278 rn
= bgp_route_next(rn
)) {
4279 table
= bgp_node_get_bgp_table_info(rn
);
4280 if (table
!= NULL
) {
4281 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4282 bgp_table_finish(&table
);
4283 bgp_node_set_bgp_table_info(rn
, NULL
);
4284 bgp_unlock_node(rn
);
4289 void bgp_reset(void)
4292 bgp_zclient_reset();
4293 access_list_reset();
4294 prefix_list_reset();
4297 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4299 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4300 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4301 PEER_CAP_ADDPATH_AF_TX_RCV
));
4304 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4306 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4307 struct bgp_nlri
*packet
)
4316 int addpath_encoded
;
4317 uint32_t addpath_id
;
4320 lim
= pnt
+ packet
->length
;
4322 safi
= packet
->safi
;
4324 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4326 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4327 syntactic validity. If the field is syntactically incorrect,
4328 then the Error Subcode is set to Invalid Network Field. */
4329 for (; pnt
< lim
; pnt
+= psize
) {
4330 /* Clear prefix structure. */
4331 memset(&p
, 0, sizeof(struct prefix
));
4333 if (addpath_encoded
) {
4335 /* When packet overflow occurs return immediately. */
4336 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4339 addpath_id
= ntohl(*((uint32_t *)pnt
));
4340 pnt
+= BGP_ADDPATH_ID_LEN
;
4343 /* Fetch prefix length. */
4344 p
.prefixlen
= *pnt
++;
4345 /* afi/safi validity already verified by caller,
4346 * bgp_update_receive */
4347 p
.family
= afi2family(afi
);
4349 /* Prefix length check. */
4350 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4353 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4354 peer
->host
, p
.prefixlen
, packet
->afi
);
4358 /* Packet size overflow check. */
4359 psize
= PSIZE(p
.prefixlen
);
4361 /* When packet overflow occur return immediately. */
4362 if (pnt
+ psize
> lim
) {
4365 "%s [Error] Update packet error (prefix length %d overflows packet)",
4366 peer
->host
, p
.prefixlen
);
4370 /* Defensive coding, double-check the psize fits in a struct
4372 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4375 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4376 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4380 /* Fetch prefix from NLRI packet. */
4381 memcpy(p
.u
.val
, pnt
, psize
);
4383 /* Check address. */
4384 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4385 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4386 /* From RFC4271 Section 6.3:
4388 * If a prefix in the NLRI field is semantically
4390 * (e.g., an unexpected multicast IP address),
4392 * be logged locally, and the prefix SHOULD be
4397 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4398 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4403 /* Check address. */
4404 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4405 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4410 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4412 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4417 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4422 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4424 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4431 /* Normal process. */
4433 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4434 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4435 NULL
, NULL
, 0, 0, NULL
);
4437 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4438 safi
, ZEBRA_ROUTE_BGP
,
4439 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4442 /* Address family configuration mismatch or maximum-prefix count
4448 /* Packet length consistency check. */
4452 "%s [Error] Update packet error (prefix length mismatch with total length)",
4460 static struct bgp_static
*bgp_static_new(void)
4462 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4465 static void bgp_static_free(struct bgp_static
*bgp_static
)
4467 if (bgp_static
->rmap
.name
)
4468 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4469 route_map_counter_decrement(bgp_static
->rmap
.map
);
4471 if (bgp_static
->eth_s_id
)
4472 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4473 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4476 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4477 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4479 struct bgp_node
*rn
;
4480 struct bgp_path_info
*pi
;
4481 struct bgp_path_info
*new;
4482 struct bgp_path_info rmap_path
;
4484 struct attr
*attr_new
;
4487 int vnc_implicit_withdraw
= 0;
4494 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4496 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4498 attr
.nexthop
= bgp_static
->igpnexthop
;
4499 attr
.med
= bgp_static
->igpmetric
;
4500 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4502 if (bgp_static
->atomic
)
4503 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4505 /* Store label index, if required. */
4506 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4507 attr
.label_index
= bgp_static
->label_index
;
4508 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4511 /* Apply route-map. */
4512 if (bgp_static
->rmap
.name
) {
4513 struct attr attr_tmp
= attr
;
4515 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4516 rmap_path
.peer
= bgp
->peer_self
;
4517 rmap_path
.attr
= &attr_tmp
;
4519 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4521 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4524 bgp
->peer_self
->rmap_type
= 0;
4526 if (ret
== RMAP_DENYMATCH
) {
4527 /* Free uninterned attribute. */
4528 bgp_attr_flush(&attr_tmp
);
4530 /* Unintern original. */
4531 aspath_unintern(&attr
.aspath
);
4532 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4536 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4537 bgp_attr_add_gshut_community(&attr_tmp
);
4539 attr_new
= bgp_attr_intern(&attr_tmp
);
4542 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4543 bgp_attr_add_gshut_community(&attr
);
4545 attr_new
= bgp_attr_intern(&attr
);
4548 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4549 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4550 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4554 if (attrhash_cmp(pi
->attr
, attr_new
)
4555 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4556 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4557 bgp_unlock_node(rn
);
4558 bgp_attr_unintern(&attr_new
);
4559 aspath_unintern(&attr
.aspath
);
4562 /* The attribute is changed. */
4563 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4565 /* Rewrite BGP route information. */
4566 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4567 bgp_path_info_restore(rn
, pi
);
4569 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4571 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4572 && (safi
== SAFI_UNICAST
)) {
4573 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4575 * Implicit withdraw case.
4576 * We have to do this before pi is
4579 ++vnc_implicit_withdraw
;
4580 vnc_import_bgp_del_route(bgp
, p
, pi
);
4581 vnc_import_bgp_exterior_del_route(
4586 bgp_attr_unintern(&pi
->attr
);
4587 pi
->attr
= attr_new
;
4588 pi
->uptime
= bgp_clock();
4590 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4591 && (safi
== SAFI_UNICAST
)) {
4592 if (vnc_implicit_withdraw
) {
4593 vnc_import_bgp_add_route(bgp
, p
, pi
);
4594 vnc_import_bgp_exterior_add_route(
4600 /* Nexthop reachability check. */
4601 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4602 && (safi
== SAFI_UNICAST
4603 || safi
== SAFI_LABELED_UNICAST
)) {
4605 struct bgp
*bgp_nexthop
= bgp
;
4607 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4608 bgp_nexthop
= pi
->extra
->bgp_orig
;
4610 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4612 bgp_path_info_set_flag(rn
, pi
,
4615 if (BGP_DEBUG(nht
, NHT
)) {
4616 char buf1
[INET6_ADDRSTRLEN
];
4617 inet_ntop(p
->family
,
4621 "%s(%s): Route not in table, not advertising",
4622 __FUNCTION__
, buf1
);
4624 bgp_path_info_unset_flag(
4625 rn
, pi
, BGP_PATH_VALID
);
4628 /* Delete the NHT structure if any, if we're
4630 * enabling/disabling import check. We
4631 * deregister the route
4632 * from NHT to avoid overloading NHT and the
4633 * process interaction
4635 bgp_unlink_nexthop(pi
);
4636 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4638 /* Process change. */
4639 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4640 bgp_process(bgp
, rn
, afi
, safi
);
4642 if (SAFI_UNICAST
== safi
4643 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4645 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4646 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4650 bgp_unlock_node(rn
);
4651 aspath_unintern(&attr
.aspath
);
4656 /* Make new BGP info. */
4657 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4659 /* Nexthop reachability check. */
4660 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4661 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4662 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4663 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4665 if (BGP_DEBUG(nht
, NHT
)) {
4666 char buf1
[INET6_ADDRSTRLEN
];
4667 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4670 "%s(%s): Route not in table, not advertising",
4671 __FUNCTION__
, buf1
);
4673 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4676 /* Delete the NHT structure if any, if we're toggling between
4677 * enabling/disabling import check. We deregister the route
4678 * from NHT to avoid overloading NHT and the process interaction
4680 bgp_unlink_nexthop(new);
4682 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4685 /* Aggregate address increment. */
4686 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4688 /* Register new BGP information. */
4689 bgp_path_info_add(rn
, new);
4691 /* route_node_get lock */
4692 bgp_unlock_node(rn
);
4694 /* Process change. */
4695 bgp_process(bgp
, rn
, afi
, safi
);
4697 if (SAFI_UNICAST
== safi
4698 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4699 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4700 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4703 /* Unintern original. */
4704 aspath_unintern(&attr
.aspath
);
4707 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4710 struct bgp_node
*rn
;
4711 struct bgp_path_info
*pi
;
4713 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4715 /* Check selected route and self inserted route. */
4716 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4717 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4718 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4721 /* Withdraw static BGP route from routing table. */
4723 if (SAFI_UNICAST
== safi
4724 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4725 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4726 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4728 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4729 bgp_unlink_nexthop(pi
);
4730 bgp_path_info_delete(rn
, pi
);
4731 bgp_process(bgp
, rn
, afi
, safi
);
4734 /* Unlock bgp_node_lookup. */
4735 bgp_unlock_node(rn
);
4739 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4741 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4742 afi_t afi
, safi_t safi
,
4743 struct prefix_rd
*prd
)
4745 struct bgp_node
*rn
;
4746 struct bgp_path_info
*pi
;
4748 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4750 /* Check selected route and self inserted route. */
4751 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4752 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4753 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4756 /* Withdraw static BGP route from routing table. */
4759 rfapiProcessWithdraw(
4760 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4761 1); /* Kill, since it is an administrative change */
4763 if (SAFI_MPLS_VPN
== safi
4764 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4765 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4767 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4768 bgp_path_info_delete(rn
, pi
);
4769 bgp_process(bgp
, rn
, afi
, safi
);
4772 /* Unlock bgp_node_lookup. */
4773 bgp_unlock_node(rn
);
4776 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4777 struct bgp_static
*bgp_static
, afi_t afi
,
4780 struct bgp_node
*rn
;
4781 struct bgp_path_info
*new;
4782 struct attr
*attr_new
;
4783 struct attr attr
= {0};
4784 struct bgp_path_info
*pi
;
4786 mpls_label_t label
= 0;
4788 uint32_t num_labels
= 0;
4793 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4795 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4798 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4800 attr
.nexthop
= bgp_static
->igpnexthop
;
4801 attr
.med
= bgp_static
->igpmetric
;
4802 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4804 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4805 || (safi
== SAFI_ENCAP
)) {
4806 if (afi
== AFI_IP
) {
4807 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4808 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4811 if (afi
== AFI_L2VPN
) {
4812 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4814 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4815 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4816 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4817 sizeof(struct in6_addr
));
4818 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4819 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4820 struct bgp_encap_type_vxlan bet
;
4821 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4822 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4823 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4825 if (bgp_static
->router_mac
) {
4826 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4829 /* Apply route-map. */
4830 if (bgp_static
->rmap
.name
) {
4831 struct attr attr_tmp
= attr
;
4832 struct bgp_path_info rmap_path
;
4835 rmap_path
.peer
= bgp
->peer_self
;
4836 rmap_path
.attr
= &attr_tmp
;
4838 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4840 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4843 bgp
->peer_self
->rmap_type
= 0;
4845 if (ret
== RMAP_DENYMATCH
) {
4846 /* Free uninterned attribute. */
4847 bgp_attr_flush(&attr_tmp
);
4849 /* Unintern original. */
4850 aspath_unintern(&attr
.aspath
);
4851 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4856 attr_new
= bgp_attr_intern(&attr_tmp
);
4858 attr_new
= bgp_attr_intern(&attr
);
4861 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4862 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4863 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4867 memset(&add
, 0, sizeof(union gw_addr
));
4868 if (attrhash_cmp(pi
->attr
, attr_new
)
4869 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4870 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4871 bgp_unlock_node(rn
);
4872 bgp_attr_unintern(&attr_new
);
4873 aspath_unintern(&attr
.aspath
);
4876 /* The attribute is changed. */
4877 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4879 /* Rewrite BGP route information. */
4880 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4881 bgp_path_info_restore(rn
, pi
);
4883 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4884 bgp_attr_unintern(&pi
->attr
);
4885 pi
->attr
= attr_new
;
4886 pi
->uptime
= bgp_clock();
4889 label
= decode_label(&pi
->extra
->label
[0]);
4892 /* Process change. */
4893 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4894 bgp_process(bgp
, rn
, afi
, safi
);
4896 if (SAFI_MPLS_VPN
== safi
4897 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4898 vpn_leak_to_vrf_update(bgp
, pi
);
4901 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4902 pi
->attr
, afi
, safi
, pi
->type
,
4903 pi
->sub_type
, &label
);
4905 bgp_unlock_node(rn
);
4906 aspath_unintern(&attr
.aspath
);
4912 /* Make new BGP info. */
4913 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4915 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4916 new->extra
= bgp_path_info_extra_new();
4918 new->extra
->label
[0] = bgp_static
->label
;
4919 new->extra
->num_labels
= num_labels
;
4922 label
= decode_label(&bgp_static
->label
);
4925 /* Aggregate address increment. */
4926 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4928 /* Register new BGP information. */
4929 bgp_path_info_add(rn
, new);
4930 /* route_node_get lock */
4931 bgp_unlock_node(rn
);
4933 /* Process change. */
4934 bgp_process(bgp
, rn
, afi
, safi
);
4936 if (SAFI_MPLS_VPN
== safi
4937 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4938 vpn_leak_to_vrf_update(bgp
, new);
4941 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4942 safi
, new->type
, new->sub_type
, &label
);
4945 /* Unintern original. */
4946 aspath_unintern(&attr
.aspath
);
4949 /* Configure static BGP network. When user don't run zebra, static
4950 route should be installed as valid. */
4951 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4952 const char *ip_str
, afi_t afi
, safi_t safi
,
4953 const char *rmap
, int backdoor
, uint32_t label_index
)
4955 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4958 struct bgp_static
*bgp_static
;
4959 struct bgp_node
*rn
;
4960 uint8_t need_update
= 0;
4962 /* Convert IP prefix string to struct prefix. */
4963 ret
= str2prefix(ip_str
, &p
);
4965 vty_out(vty
, "%% Malformed prefix\n");
4966 return CMD_WARNING_CONFIG_FAILED
;
4968 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4969 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4970 return CMD_WARNING_CONFIG_FAILED
;
4977 /* Set BGP static route configuration. */
4978 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4981 vty_out(vty
, "%% Can't find static route specified\n");
4982 return CMD_WARNING_CONFIG_FAILED
;
4985 bgp_static
= bgp_node_get_bgp_static_info(rn
);
4987 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4988 && (label_index
!= bgp_static
->label_index
)) {
4990 "%% label-index doesn't match static route\n");
4991 return CMD_WARNING_CONFIG_FAILED
;
4994 if ((rmap
&& bgp_static
->rmap
.name
)
4995 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4997 "%% route-map name doesn't match static route\n");
4998 return CMD_WARNING_CONFIG_FAILED
;
5001 /* Update BGP RIB. */
5002 if (!bgp_static
->backdoor
)
5003 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5005 /* Clear configuration. */
5006 bgp_static_free(bgp_static
);
5007 bgp_node_set_bgp_static_info(rn
, NULL
);
5008 bgp_unlock_node(rn
);
5009 bgp_unlock_node(rn
);
5012 /* Set BGP static route configuration. */
5013 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5015 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5017 /* Configuration change. */
5018 /* Label index cannot be changed. */
5019 if (bgp_static
->label_index
!= label_index
) {
5020 vty_out(vty
, "%% cannot change label-index\n");
5021 return CMD_WARNING_CONFIG_FAILED
;
5024 /* Check previous routes are installed into BGP. */
5025 if (bgp_static
->valid
5026 && bgp_static
->backdoor
!= backdoor
)
5029 bgp_static
->backdoor
= backdoor
;
5032 if (bgp_static
->rmap
.name
)
5033 XFREE(MTYPE_ROUTE_MAP_NAME
,
5034 bgp_static
->rmap
.name
);
5035 route_map_counter_decrement(
5036 bgp_static
->rmap
.map
);
5037 bgp_static
->rmap
.name
=
5038 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5039 bgp_static
->rmap
.map
=
5040 route_map_lookup_by_name(rmap
);
5041 route_map_counter_increment(
5042 bgp_static
->rmap
.map
);
5044 if (bgp_static
->rmap
.name
)
5045 XFREE(MTYPE_ROUTE_MAP_NAME
,
5046 bgp_static
->rmap
.name
);
5047 route_map_counter_decrement(
5048 bgp_static
->rmap
.map
);
5049 bgp_static
->rmap
.name
= NULL
;
5050 bgp_static
->rmap
.map
= NULL
;
5051 bgp_static
->valid
= 0;
5053 bgp_unlock_node(rn
);
5055 /* New configuration. */
5056 bgp_static
= bgp_static_new();
5057 bgp_static
->backdoor
= backdoor
;
5058 bgp_static
->valid
= 0;
5059 bgp_static
->igpmetric
= 0;
5060 bgp_static
->igpnexthop
.s_addr
= 0;
5061 bgp_static
->label_index
= label_index
;
5064 if (bgp_static
->rmap
.name
)
5065 XFREE(MTYPE_ROUTE_MAP_NAME
,
5066 bgp_static
->rmap
.name
);
5067 route_map_counter_decrement(
5068 bgp_static
->rmap
.map
);
5069 bgp_static
->rmap
.name
=
5070 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5071 bgp_static
->rmap
.map
=
5072 route_map_lookup_by_name(rmap
);
5073 route_map_counter_increment(
5074 bgp_static
->rmap
.map
);
5076 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5079 bgp_static
->valid
= 1;
5081 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5083 if (!bgp_static
->backdoor
)
5084 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5090 void bgp_static_add(struct bgp
*bgp
)
5094 struct bgp_node
*rn
;
5095 struct bgp_node
*rm
;
5096 struct bgp_table
*table
;
5097 struct bgp_static
*bgp_static
;
5099 FOREACH_AFI_SAFI (afi
, safi
)
5100 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5101 rn
= bgp_route_next(rn
)) {
5102 if (!bgp_node_has_bgp_path_info_data(rn
))
5105 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5106 || (safi
== SAFI_EVPN
)) {
5107 table
= bgp_node_get_bgp_table_info(rn
);
5109 for (rm
= bgp_table_top(table
); rm
;
5110 rm
= bgp_route_next(rm
)) {
5112 bgp_node_get_bgp_static_info(
5114 bgp_static_update_safi(bgp
, &rm
->p
,
5121 bgp_node_get_bgp_static_info(rn
), afi
,
5127 /* Called from bgp_delete(). Delete all static routes from the BGP
5129 void bgp_static_delete(struct bgp
*bgp
)
5133 struct bgp_node
*rn
;
5134 struct bgp_node
*rm
;
5135 struct bgp_table
*table
;
5136 struct bgp_static
*bgp_static
;
5138 FOREACH_AFI_SAFI (afi
, safi
)
5139 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5140 rn
= bgp_route_next(rn
)) {
5141 if (!bgp_node_has_bgp_path_info_data(rn
))
5144 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5145 || (safi
== SAFI_EVPN
)) {
5146 table
= bgp_node_get_bgp_table_info(rn
);
5148 for (rm
= bgp_table_top(table
); rm
;
5149 rm
= bgp_route_next(rm
)) {
5151 bgp_node_get_bgp_static_info(
5156 bgp_static_withdraw_safi(
5157 bgp
, &rm
->p
, AFI_IP
, safi
,
5158 (struct prefix_rd
*)&rn
->p
);
5159 bgp_static_free(bgp_static
);
5160 bgp_node_set_bgp_static_info(rn
, NULL
);
5161 bgp_unlock_node(rn
);
5164 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5165 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5166 bgp_static_free(bgp_static
);
5167 bgp_node_set_bgp_static_info(rn
, NULL
);
5168 bgp_unlock_node(rn
);
5173 void bgp_static_redo_import_check(struct bgp
*bgp
)
5177 struct bgp_node
*rn
;
5178 struct bgp_node
*rm
;
5179 struct bgp_table
*table
;
5180 struct bgp_static
*bgp_static
;
5182 /* Use this flag to force reprocessing of the route */
5183 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5184 FOREACH_AFI_SAFI (afi
, safi
) {
5185 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5186 rn
= bgp_route_next(rn
)) {
5187 if (!bgp_node_has_bgp_path_info_data(rn
))
5190 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5191 || (safi
== SAFI_EVPN
)) {
5192 table
= bgp_node_get_bgp_table_info(rn
);
5194 for (rm
= bgp_table_top(table
); rm
;
5195 rm
= bgp_route_next(rm
)) {
5197 bgp_node_get_bgp_static_info(
5199 bgp_static_update_safi(bgp
, &rm
->p
,
5204 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5205 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5210 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5213 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5216 struct bgp_table
*table
;
5217 struct bgp_node
*rn
;
5218 struct bgp_path_info
*pi
;
5220 table
= bgp
->rib
[afi
][safi
];
5221 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5222 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5223 if (pi
->peer
== bgp
->peer_self
5224 && ((pi
->type
== ZEBRA_ROUTE_BGP
5225 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5226 || (pi
->type
!= ZEBRA_ROUTE_BGP
5228 == BGP_ROUTE_REDISTRIBUTE
))) {
5229 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5231 bgp_unlink_nexthop(pi
);
5232 bgp_path_info_delete(rn
, pi
);
5233 bgp_process(bgp
, rn
, afi
, safi
);
5240 * Purge all networks and redistributed routes from routing table.
5241 * Invoked upon the instance going down.
5243 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5248 FOREACH_AFI_SAFI (afi
, safi
)
5249 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5254 * Currently this is used to set static routes for VPN and ENCAP.
5255 * I think it can probably be factored with bgp_static_set.
5257 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5258 const char *ip_str
, const char *rd_str
,
5259 const char *label_str
, const char *rmap_str
,
5260 int evpn_type
, const char *esi
, const char *gwip
,
5261 const char *ethtag
, const char *routermac
)
5263 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5266 struct prefix_rd prd
;
5267 struct bgp_node
*prn
;
5268 struct bgp_node
*rn
;
5269 struct bgp_table
*table
;
5270 struct bgp_static
*bgp_static
;
5271 mpls_label_t label
= MPLS_INVALID_LABEL
;
5272 struct prefix gw_ip
;
5274 /* validate ip prefix */
5275 ret
= str2prefix(ip_str
, &p
);
5277 vty_out(vty
, "%% Malformed prefix\n");
5278 return CMD_WARNING_CONFIG_FAILED
;
5281 if ((afi
== AFI_L2VPN
)
5282 && (bgp_build_evpn_prefix(evpn_type
,
5283 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5284 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5285 return CMD_WARNING_CONFIG_FAILED
;
5288 ret
= str2prefix_rd(rd_str
, &prd
);
5290 vty_out(vty
, "%% Malformed rd\n");
5291 return CMD_WARNING_CONFIG_FAILED
;
5295 unsigned long label_val
;
5296 label_val
= strtoul(label_str
, NULL
, 10);
5297 encode_label(label_val
, &label
);
5300 if (safi
== SAFI_EVPN
) {
5301 if (esi
&& str2esi(esi
, NULL
) == 0) {
5302 vty_out(vty
, "%% Malformed ESI\n");
5303 return CMD_WARNING_CONFIG_FAILED
;
5305 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5306 vty_out(vty
, "%% Malformed Router MAC\n");
5307 return CMD_WARNING_CONFIG_FAILED
;
5310 memset(&gw_ip
, 0, sizeof(struct prefix
));
5311 ret
= str2prefix(gwip
, &gw_ip
);
5313 vty_out(vty
, "%% Malformed GatewayIp\n");
5314 return CMD_WARNING_CONFIG_FAILED
;
5316 if ((gw_ip
.family
== AF_INET
5317 && is_evpn_prefix_ipaddr_v6(
5318 (struct prefix_evpn
*)&p
))
5319 || (gw_ip
.family
== AF_INET6
5320 && is_evpn_prefix_ipaddr_v4(
5321 (struct prefix_evpn
*)&p
))) {
5323 "%% GatewayIp family differs with IP prefix\n");
5324 return CMD_WARNING_CONFIG_FAILED
;
5328 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5329 if (!bgp_node_has_bgp_path_info_data(prn
))
5330 bgp_node_set_bgp_table_info(prn
,
5331 bgp_table_init(bgp
, afi
, safi
));
5332 table
= bgp_node_get_bgp_table_info(prn
);
5334 rn
= bgp_node_get(table
, &p
);
5336 if (bgp_node_has_bgp_path_info_data(rn
)) {
5337 vty_out(vty
, "%% Same network configuration exists\n");
5338 bgp_unlock_node(rn
);
5340 /* New configuration. */
5341 bgp_static
= bgp_static_new();
5342 bgp_static
->backdoor
= 0;
5343 bgp_static
->valid
= 0;
5344 bgp_static
->igpmetric
= 0;
5345 bgp_static
->igpnexthop
.s_addr
= 0;
5346 bgp_static
->label
= label
;
5347 bgp_static
->prd
= prd
;
5350 if (bgp_static
->rmap
.name
)
5351 XFREE(MTYPE_ROUTE_MAP_NAME
,
5352 bgp_static
->rmap
.name
);
5353 route_map_counter_decrement(bgp_static
->rmap
.map
);
5354 bgp_static
->rmap
.name
=
5355 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5356 bgp_static
->rmap
.map
=
5357 route_map_lookup_by_name(rmap_str
);
5358 route_map_counter_increment(bgp_static
->rmap
.map
);
5361 if (safi
== SAFI_EVPN
) {
5363 bgp_static
->eth_s_id
=
5365 sizeof(struct eth_segment_id
));
5366 str2esi(esi
, bgp_static
->eth_s_id
);
5369 bgp_static
->router_mac
=
5370 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5371 (void)prefix_str2mac(routermac
,
5372 bgp_static
->router_mac
);
5375 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5377 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5379 bgp_static
->valid
= 1;
5380 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5386 /* Configure static BGP network. */
5387 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5388 const char *ip_str
, const char *rd_str
,
5389 const char *label_str
, int evpn_type
, const char *esi
,
5390 const char *gwip
, const char *ethtag
)
5392 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5395 struct prefix_rd prd
;
5396 struct bgp_node
*prn
;
5397 struct bgp_node
*rn
;
5398 struct bgp_table
*table
;
5399 struct bgp_static
*bgp_static
;
5400 mpls_label_t label
= MPLS_INVALID_LABEL
;
5402 /* Convert IP prefix string to struct prefix. */
5403 ret
= str2prefix(ip_str
, &p
);
5405 vty_out(vty
, "%% Malformed prefix\n");
5406 return CMD_WARNING_CONFIG_FAILED
;
5409 if ((afi
== AFI_L2VPN
)
5410 && (bgp_build_evpn_prefix(evpn_type
,
5411 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5412 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5413 return CMD_WARNING_CONFIG_FAILED
;
5415 ret
= str2prefix_rd(rd_str
, &prd
);
5417 vty_out(vty
, "%% Malformed rd\n");
5418 return CMD_WARNING_CONFIG_FAILED
;
5422 unsigned long label_val
;
5423 label_val
= strtoul(label_str
, NULL
, 10);
5424 encode_label(label_val
, &label
);
5427 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5428 if (!bgp_node_has_bgp_path_info_data(prn
))
5429 bgp_node_set_bgp_table_info(prn
,
5430 bgp_table_init(bgp
, afi
, safi
));
5432 bgp_unlock_node(prn
);
5433 table
= bgp_node_get_bgp_table_info(prn
);
5435 rn
= bgp_node_lookup(table
, &p
);
5438 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5440 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5441 bgp_static_free(bgp_static
);
5442 bgp_node_set_bgp_static_info(rn
, NULL
);
5443 bgp_unlock_node(rn
);
5444 bgp_unlock_node(rn
);
5446 vty_out(vty
, "%% Can't find the route\n");
5451 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5452 const char *rmap_name
)
5454 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5455 struct bgp_rmap
*rmap
;
5457 rmap
= &bgp
->table_map
[afi
][safi
];
5460 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5461 route_map_counter_decrement(rmap
->map
);
5462 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5463 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5464 route_map_counter_increment(rmap
->map
);
5467 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5468 route_map_counter_decrement(rmap
->map
);
5473 if (bgp_fibupd_safi(safi
))
5474 bgp_zebra_announce_table(bgp
, afi
, safi
);
5479 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5480 const char *rmap_name
)
5482 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5483 struct bgp_rmap
*rmap
;
5485 rmap
= &bgp
->table_map
[afi
][safi
];
5487 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5488 route_map_counter_decrement(rmap
->map
);
5492 if (bgp_fibupd_safi(safi
))
5493 bgp_zebra_announce_table(bgp
, afi
, safi
);
5498 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5501 if (bgp
->table_map
[afi
][safi
].name
) {
5502 vty_out(vty
, " table-map %s\n",
5503 bgp
->table_map
[afi
][safi
].name
);
5507 DEFUN (bgp_table_map
,
5510 "BGP table to RIB route download filter\n"
5511 "Name of the route map\n")
5514 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5515 argv
[idx_word
]->arg
);
5517 DEFUN (no_bgp_table_map
,
5518 no_bgp_table_map_cmd
,
5519 "no table-map WORD",
5521 "BGP table to RIB route download filter\n"
5522 "Name of the route map\n")
5525 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5526 argv
[idx_word
]->arg
);
5532 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5533 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5534 backdoor$backdoor}]",
5536 "Specify a network to announce via BGP\n"
5541 "Route-map to modify the attributes\n"
5542 "Name of the route map\n"
5543 "Label index to associate with the prefix\n"
5544 "Label index value\n"
5545 "Specify a BGP backdoor route\n")
5547 char addr_prefix_str
[BUFSIZ
];
5552 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5555 vty_out(vty
, "%% Inconsistent address and mask\n");
5556 return CMD_WARNING_CONFIG_FAILED
;
5560 return bgp_static_set(
5561 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5562 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5563 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5566 DEFPY(ipv6_bgp_network
,
5567 ipv6_bgp_network_cmd
,
5568 "[no] network X:X::X:X/M$prefix \
5569 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5571 "Specify a network to announce via BGP\n"
5573 "Route-map to modify the attributes\n"
5574 "Name of the route map\n"
5575 "Label index to associate with the prefix\n"
5576 "Label index value\n")
5578 return bgp_static_set(
5579 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5580 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5583 /* Aggreagete address:
5585 advertise-map Set condition to advertise attribute
5586 as-set Generate AS set path information
5587 attribute-map Set attributes of aggregate
5588 route-map Set parameters of aggregate
5589 summary-only Filter more specific routes from updates
5590 suppress-map Conditionally filter more specific routes from updates
5593 struct bgp_aggregate
{
5594 /* Summary-only flag. */
5595 uint8_t summary_only
;
5597 /* AS set generation. */
5600 /* Route-map for aggregated route. */
5601 struct route_map
*map
;
5603 /* Suppress-count. */
5604 unsigned long count
;
5606 /* SAFI configuration. */
5610 static struct bgp_aggregate
*bgp_aggregate_new(void)
5612 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5615 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5617 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5620 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5621 struct aspath
*aspath
,
5622 struct community
*comm
,
5623 struct ecommunity
*ecomm
,
5624 struct lcommunity
*lcomm
)
5626 static struct aspath
*ae
= NULL
;
5629 ae
= aspath_empty();
5634 if (origin
!= pi
->attr
->origin
)
5637 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5640 if (!community_cmp(pi
->attr
->community
, comm
))
5643 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5646 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5649 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5655 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5656 struct prefix
*p
, uint8_t origin
,
5657 struct aspath
*aspath
,
5658 struct community
*community
,
5659 struct ecommunity
*ecommunity
,
5660 struct lcommunity
*lcommunity
,
5661 uint8_t atomic_aggregate
,
5662 struct bgp_aggregate
*aggregate
)
5664 struct bgp_node
*rn
;
5665 struct bgp_table
*table
;
5666 struct bgp_path_info
*pi
, *orig
, *new;
5668 table
= bgp
->rib
[afi
][safi
];
5670 rn
= bgp_node_get(table
, p
);
5672 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5673 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5674 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5677 if (aggregate
->count
> 0) {
5679 * If the aggregate information has not changed
5680 * no need to re-install it again.
5682 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5683 ecommunity
, lcommunity
)) {
5684 bgp_unlock_node(rn
);
5687 aspath_free(aspath
);
5689 community_free(&community
);
5691 ecommunity_free(&ecommunity
);
5693 lcommunity_free(&lcommunity
);
5699 * Mark the old as unusable
5702 bgp_path_info_delete(rn
, pi
);
5704 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5706 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5707 community
, ecommunity
,
5712 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5714 bgp_path_info_add(rn
, new);
5715 bgp_process(bgp
, rn
, afi
, safi
);
5717 for (pi
= orig
; pi
; pi
= pi
->next
)
5718 if (pi
->peer
== bgp
->peer_self
5719 && pi
->type
== ZEBRA_ROUTE_BGP
5720 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5723 /* Withdraw static BGP route from routing table. */
5725 bgp_path_info_delete(rn
, pi
);
5726 bgp_process(bgp
, rn
, afi
, safi
);
5730 bgp_unlock_node(rn
);
5733 /* Update an aggregate as routes are added/removed from the BGP table */
5734 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5735 struct bgp_path_info
*pinew
, afi_t afi
,
5736 safi_t safi
, struct bgp_path_info
*del
,
5737 struct bgp_aggregate
*aggregate
)
5739 struct bgp_table
*table
;
5740 struct bgp_node
*top
;
5741 struct bgp_node
*rn
;
5743 struct aspath
*aspath
= NULL
;
5744 struct aspath
*asmerge
= NULL
;
5745 struct community
*community
= NULL
;
5746 struct community
*commerge
= NULL
;
5747 struct ecommunity
*ecommunity
= NULL
;
5748 struct ecommunity
*ecommerge
= NULL
;
5749 struct lcommunity
*lcommunity
= NULL
;
5750 struct lcommunity
*lcommerge
= NULL
;
5751 struct bgp_path_info
*pi
;
5752 unsigned long match
= 0;
5753 uint8_t atomic_aggregate
= 0;
5755 /* ORIGIN attribute: If at least one route among routes that are
5756 aggregated has ORIGIN with the value INCOMPLETE, then the
5757 aggregated route must have the ORIGIN attribute with the value
5758 INCOMPLETE. Otherwise, if at least one route among routes that
5759 are aggregated has ORIGIN with the value EGP, then the aggregated
5760 route must have the origin attribute with the value EGP. In all
5761 other case the value of the ORIGIN attribute of the aggregated
5762 route is INTERNAL. */
5763 origin
= BGP_ORIGIN_IGP
;
5765 table
= bgp
->rib
[afi
][safi
];
5767 top
= bgp_node_get(table
, p
);
5768 for (rn
= bgp_node_get(table
, p
); rn
;
5769 rn
= bgp_route_next_until(rn
, top
)) {
5770 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5775 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5776 if (BGP_PATH_HOLDDOWN(pi
))
5779 if (del
&& pi
== del
)
5783 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5784 atomic_aggregate
= 1;
5786 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5790 * summary-only aggregate route suppress
5791 * aggregated route announcements.
5793 if (aggregate
->summary_only
) {
5794 (bgp_path_info_extra_get(pi
))->suppress
++;
5795 bgp_path_info_set_flag(rn
, pi
,
5796 BGP_PATH_ATTR_CHANGED
);
5803 * If at least one route among routes that are
5804 * aggregated has ORIGIN with the value INCOMPLETE,
5805 * then the aggregated route MUST have the ORIGIN
5806 * attribute with the value INCOMPLETE. Otherwise, if
5807 * at least one route among routes that are aggregated
5808 * has ORIGIN with the value EGP, then the aggregated
5809 * route MUST have the ORIGIN attribute with the value
5812 if (origin
< pi
->attr
->origin
)
5813 origin
= pi
->attr
->origin
;
5815 if (!aggregate
->as_set
)
5819 * as-set aggregate route generate origin, as path,
5820 * and community aggregation.
5823 asmerge
= aspath_aggregate(aspath
,
5825 aspath_free(aspath
);
5828 aspath
= aspath_dup(pi
->attr
->aspath
);
5830 if (pi
->attr
->community
) {
5832 commerge
= community_merge(
5833 community
, pi
->attr
->community
);
5835 community_uniq_sort(commerge
);
5836 community_free(&commerge
);
5838 community
= community_dup(
5839 pi
->attr
->community
);
5842 if (pi
->attr
->ecommunity
) {
5844 ecommerge
= ecommunity_merge(
5846 pi
->attr
->ecommunity
);
5848 ecommunity_uniq_sort(ecommerge
);
5849 ecommunity_free(&ecommerge
);
5851 ecommunity
= ecommunity_dup(
5852 pi
->attr
->ecommunity
);
5855 if (pi
->attr
->lcommunity
) {
5857 lcommerge
= lcommunity_merge(
5859 pi
->attr
->lcommunity
);
5861 lcommunity_uniq_sort(lcommerge
);
5862 lcommunity_free(&lcommerge
);
5864 lcommunity
= lcommunity_dup(
5865 pi
->attr
->lcommunity
);
5869 bgp_process(bgp
, rn
, afi
, safi
);
5871 bgp_unlock_node(top
);
5876 if (aggregate
->summary_only
)
5877 (bgp_path_info_extra_get(pinew
))->suppress
++;
5879 if (origin
< pinew
->attr
->origin
)
5880 origin
= pinew
->attr
->origin
;
5882 if (aggregate
->as_set
) {
5884 asmerge
= aspath_aggregate(aspath
,
5885 pinew
->attr
->aspath
);
5886 aspath_free(aspath
);
5889 aspath
= aspath_dup(pinew
->attr
->aspath
);
5891 if (pinew
->attr
->community
) {
5893 commerge
= community_merge(
5895 pinew
->attr
->community
);
5897 community_uniq_sort(commerge
);
5898 community_free(&commerge
);
5900 community
= community_dup(
5901 pinew
->attr
->community
);
5904 if (pinew
->attr
->ecommunity
) {
5906 ecommerge
= ecommunity_merge(
5908 pinew
->attr
->ecommunity
);
5910 ecommunity_uniq_sort(ecommerge
);
5911 ecommunity_free(&ecommerge
);
5913 ecommunity
= ecommunity_dup(
5914 pinew
->attr
->ecommunity
);
5917 if (pinew
->attr
->lcommunity
) {
5919 lcommerge
= lcommunity_merge(
5921 pinew
->attr
->lcommunity
);
5923 lcommunity_uniq_sort(lcommerge
);
5924 lcommunity_free(&lcommerge
);
5926 lcommunity
= lcommunity_dup(
5927 pinew
->attr
->lcommunity
);
5932 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5933 ecommunity
, lcommunity
, atomic_aggregate
,
5936 if (aggregate
->count
== 0) {
5938 aspath_free(aspath
);
5940 community_free(&community
);
5942 ecommunity_free(&ecommunity
);
5944 lcommunity_free(&lcommunity
);
5948 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5949 safi_t safi
, struct bgp_aggregate
*aggregate
)
5951 struct bgp_table
*table
;
5952 struct bgp_node
*top
;
5953 struct bgp_node
*rn
;
5954 struct bgp_path_info
*pi
;
5955 unsigned long match
;
5957 table
= bgp
->rib
[afi
][safi
];
5959 /* If routes exists below this node, generate aggregate routes. */
5960 top
= bgp_node_get(table
, p
);
5961 for (rn
= bgp_node_get(table
, p
); rn
;
5962 rn
= bgp_route_next_until(rn
, top
)) {
5963 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5967 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5968 if (BGP_PATH_HOLDDOWN(pi
))
5971 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5974 if (aggregate
->summary_only
&& pi
->extra
) {
5975 pi
->extra
->suppress
--;
5977 if (pi
->extra
->suppress
== 0) {
5978 bgp_path_info_set_flag(
5979 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5986 /* If this node was suppressed, process the change. */
5988 bgp_process(bgp
, rn
, afi
, safi
);
5990 bgp_unlock_node(top
);
5993 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5994 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
5996 struct bgp_node
*child
;
5997 struct bgp_node
*rn
;
5998 struct bgp_aggregate
*aggregate
;
5999 struct bgp_table
*table
;
6001 table
= bgp
->aggregate
[afi
][safi
];
6003 /* No aggregates configured. */
6004 if (bgp_table_top_nolock(table
) == NULL
)
6007 if (p
->prefixlen
== 0)
6010 if (BGP_PATH_HOLDDOWN(pi
))
6013 child
= bgp_node_get(table
, p
);
6015 /* Aggregate address configuration check. */
6016 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6017 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6018 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6019 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
6020 bgp_aggregate_route(bgp
, &rn
->p
, pi
, afi
, safi
, NULL
,
6024 bgp_unlock_node(child
);
6027 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6028 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6030 struct bgp_node
*child
;
6031 struct bgp_node
*rn
;
6032 struct bgp_aggregate
*aggregate
;
6033 struct bgp_table
*table
;
6035 table
= bgp
->aggregate
[afi
][safi
];
6037 /* No aggregates configured. */
6038 if (bgp_table_top_nolock(table
) == NULL
)
6041 if (p
->prefixlen
== 0)
6044 child
= bgp_node_get(table
, p
);
6046 /* Aggregate address configuration check. */
6047 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6048 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6049 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6050 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
6051 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
6055 bgp_unlock_node(child
);
6058 /* Aggregate route attribute. */
6059 #define AGGREGATE_SUMMARY_ONLY 1
6060 #define AGGREGATE_AS_SET 1
6062 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6063 afi_t afi
, safi_t safi
)
6065 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6068 struct bgp_node
*rn
;
6069 struct bgp_aggregate
*aggregate
;
6071 /* Convert string to prefix structure. */
6072 ret
= str2prefix(prefix_str
, &p
);
6074 vty_out(vty
, "Malformed prefix\n");
6075 return CMD_WARNING_CONFIG_FAILED
;
6079 /* Old configuration check. */
6080 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6083 "%% There is no aggregate-address configuration.\n");
6084 return CMD_WARNING_CONFIG_FAILED
;
6087 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6088 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6089 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6090 NULL
, NULL
, 0, aggregate
);
6092 /* Unlock aggregate address configuration. */
6093 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6094 bgp_aggregate_free(aggregate
);
6095 bgp_unlock_node(rn
);
6096 bgp_unlock_node(rn
);
6101 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6102 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6104 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6107 struct bgp_node
*rn
;
6108 struct bgp_aggregate
*aggregate
;
6110 /* Convert string to prefix structure. */
6111 ret
= str2prefix(prefix_str
, &p
);
6113 vty_out(vty
, "Malformed prefix\n");
6114 return CMD_WARNING_CONFIG_FAILED
;
6118 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6119 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6120 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6122 return CMD_WARNING_CONFIG_FAILED
;
6125 /* Old configuration check. */
6126 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6128 if (bgp_node_has_bgp_path_info_data(rn
)) {
6129 vty_out(vty
, "There is already same aggregate network.\n");
6130 /* try to remove the old entry */
6131 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6133 vty_out(vty
, "Error deleting aggregate.\n");
6134 bgp_unlock_node(rn
);
6135 return CMD_WARNING_CONFIG_FAILED
;
6139 /* Make aggregate address structure. */
6140 aggregate
= bgp_aggregate_new();
6141 aggregate
->summary_only
= summary_only
;
6142 aggregate
->as_set
= as_set
;
6143 aggregate
->safi
= safi
;
6144 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6146 /* Aggregate address insert into BGP routing table. */
6147 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
6152 DEFUN (aggregate_address
,
6153 aggregate_address_cmd
,
6154 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6155 "Configure BGP aggregate entries\n"
6156 "Aggregate prefix\n"
6157 "Generate AS set path information\n"
6158 "Filter more specific routes from updates\n"
6159 "Filter more specific routes from updates\n"
6160 "Generate AS set path information\n")
6163 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6164 char *prefix
= argv
[idx
]->arg
;
6166 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6168 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6169 ? AGGREGATE_SUMMARY_ONLY
6172 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6173 summary_only
, as_set
);
6176 DEFUN (aggregate_address_mask
,
6177 aggregate_address_mask_cmd
,
6178 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6179 "Configure BGP aggregate entries\n"
6180 "Aggregate address\n"
6182 "Generate AS set path information\n"
6183 "Filter more specific routes from updates\n"
6184 "Filter more specific routes from updates\n"
6185 "Generate AS set path information\n")
6188 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6189 char *prefix
= argv
[idx
]->arg
;
6190 char *mask
= argv
[idx
+ 1]->arg
;
6192 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6194 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6195 ? AGGREGATE_SUMMARY_ONLY
6198 char prefix_str
[BUFSIZ
];
6199 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6202 vty_out(vty
, "%% Inconsistent address and mask\n");
6203 return CMD_WARNING_CONFIG_FAILED
;
6206 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6207 summary_only
, as_set
);
6210 DEFUN (no_aggregate_address
,
6211 no_aggregate_address_cmd
,
6212 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6214 "Configure BGP aggregate entries\n"
6215 "Aggregate prefix\n"
6216 "Generate AS set path information\n"
6217 "Filter more specific routes from updates\n"
6218 "Filter more specific routes from updates\n"
6219 "Generate AS set path information\n")
6222 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6223 char *prefix
= argv
[idx
]->arg
;
6224 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6227 DEFUN (no_aggregate_address_mask
,
6228 no_aggregate_address_mask_cmd
,
6229 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6231 "Configure BGP aggregate entries\n"
6232 "Aggregate address\n"
6234 "Generate AS set path information\n"
6235 "Filter more specific routes from updates\n"
6236 "Filter more specific routes from updates\n"
6237 "Generate AS set path information\n")
6240 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6241 char *prefix
= argv
[idx
]->arg
;
6242 char *mask
= argv
[idx
+ 1]->arg
;
6244 char prefix_str
[BUFSIZ
];
6245 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6248 vty_out(vty
, "%% Inconsistent address and mask\n");
6249 return CMD_WARNING_CONFIG_FAILED
;
6252 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6255 DEFUN (ipv6_aggregate_address
,
6256 ipv6_aggregate_address_cmd
,
6257 "aggregate-address X:X::X:X/M [summary-only]",
6258 "Configure BGP aggregate entries\n"
6259 "Aggregate prefix\n"
6260 "Filter more specific routes from updates\n")
6263 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6264 char *prefix
= argv
[idx
]->arg
;
6265 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6266 ? AGGREGATE_SUMMARY_ONLY
6268 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6272 DEFUN (no_ipv6_aggregate_address
,
6273 no_ipv6_aggregate_address_cmd
,
6274 "no aggregate-address X:X::X:X/M [summary-only]",
6276 "Configure BGP aggregate entries\n"
6277 "Aggregate prefix\n"
6278 "Filter more specific routes from updates\n")
6281 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6282 char *prefix
= argv
[idx
]->arg
;
6283 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6286 /* Redistribute route treatment. */
6287 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6288 const union g_addr
*nexthop
, ifindex_t ifindex
,
6289 enum nexthop_types_t nhtype
, uint32_t metric
,
6290 uint8_t type
, unsigned short instance
,
6293 struct bgp_path_info
*new;
6294 struct bgp_path_info
*bpi
;
6295 struct bgp_path_info rmap_path
;
6296 struct bgp_node
*bn
;
6298 struct attr
*new_attr
;
6301 struct bgp_redist
*red
;
6303 /* Make default attribute. */
6304 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6307 case NEXTHOP_TYPE_IFINDEX
:
6309 case NEXTHOP_TYPE_IPV4
:
6310 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6311 attr
.nexthop
= nexthop
->ipv4
;
6313 case NEXTHOP_TYPE_IPV6
:
6314 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6315 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6316 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6318 case NEXTHOP_TYPE_BLACKHOLE
:
6319 switch (p
->family
) {
6321 attr
.nexthop
.s_addr
= INADDR_ANY
;
6324 memset(&attr
.mp_nexthop_global
, 0,
6325 sizeof(attr
.mp_nexthop_global
));
6326 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6331 attr
.nh_ifindex
= ifindex
;
6334 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6337 afi
= family2afi(p
->family
);
6339 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6341 struct attr attr_new
;
6343 /* Copy attribute for modification. */
6344 bgp_attr_dup(&attr_new
, &attr
);
6346 if (red
->redist_metric_flag
)
6347 attr_new
.med
= red
->redist_metric
;
6349 /* Apply route-map. */
6350 if (red
->rmap
.name
) {
6351 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6352 rmap_path
.peer
= bgp
->peer_self
;
6353 rmap_path
.attr
= &attr_new
;
6355 SET_FLAG(bgp
->peer_self
->rmap_type
,
6356 PEER_RMAP_TYPE_REDISTRIBUTE
);
6358 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6361 bgp
->peer_self
->rmap_type
= 0;
6363 if (ret
== RMAP_DENYMATCH
) {
6364 /* Free uninterned attribute. */
6365 bgp_attr_flush(&attr_new
);
6367 /* Unintern original. */
6368 aspath_unintern(&attr
.aspath
);
6369 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6374 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6375 bgp_attr_add_gshut_community(&attr_new
);
6377 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6378 SAFI_UNICAST
, p
, NULL
);
6380 new_attr
= bgp_attr_intern(&attr_new
);
6382 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6384 if (bpi
->peer
== bgp
->peer_self
6385 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6389 /* Ensure the (source route) type is updated. */
6391 if (attrhash_cmp(bpi
->attr
, new_attr
)
6392 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6393 bgp_attr_unintern(&new_attr
);
6394 aspath_unintern(&attr
.aspath
);
6395 bgp_unlock_node(bn
);
6398 /* The attribute is changed. */
6399 bgp_path_info_set_flag(bn
, bpi
,
6400 BGP_PATH_ATTR_CHANGED
);
6402 /* Rewrite BGP route information. */
6403 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6404 bgp_path_info_restore(bn
, bpi
);
6406 bgp_aggregate_decrement(
6407 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6408 bgp_attr_unintern(&bpi
->attr
);
6409 bpi
->attr
= new_attr
;
6410 bpi
->uptime
= bgp_clock();
6412 /* Process change. */
6413 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6415 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6416 bgp_unlock_node(bn
);
6417 aspath_unintern(&attr
.aspath
);
6419 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6421 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6423 vpn_leak_from_vrf_update(
6424 bgp_get_default(), bgp
, bpi
);
6430 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6431 bgp
->peer_self
, new_attr
, bn
);
6432 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6434 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6435 bgp_path_info_add(bn
, new);
6436 bgp_unlock_node(bn
);
6437 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6439 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6440 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6442 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6446 /* Unintern original. */
6447 aspath_unintern(&attr
.aspath
);
6450 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6451 unsigned short instance
)
6454 struct bgp_node
*rn
;
6455 struct bgp_path_info
*pi
;
6456 struct bgp_redist
*red
;
6458 afi
= family2afi(p
->family
);
6460 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6462 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6463 SAFI_UNICAST
, p
, NULL
);
6465 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6466 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6470 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6471 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6473 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6476 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6477 bgp_path_info_delete(rn
, pi
);
6478 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6480 bgp_unlock_node(rn
);
6484 /* Withdraw specified route type's route. */
6485 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6486 unsigned short instance
)
6488 struct bgp_node
*rn
;
6489 struct bgp_path_info
*pi
;
6490 struct bgp_table
*table
;
6492 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6494 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6495 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6496 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6497 && pi
->instance
== instance
)
6501 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6502 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6504 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6507 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6509 bgp_path_info_delete(rn
, pi
);
6510 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6515 /* Static function to display route. */
6516 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6523 if (p
->family
== AF_INET
) {
6527 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6530 json_object_string_add(json
, "prefix",
6531 inet_ntop(p
->family
,
6534 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6535 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6536 json_object_string_add(json
, "network", buf2
);
6538 } else if (p
->family
== AF_ETHERNET
) {
6539 prefix2str(p
, buf
, PREFIX_STRLEN
);
6540 len
= vty_out(vty
, "%s", buf
);
6541 } else if (p
->family
== AF_EVPN
) {
6545 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6548 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6549 } else if (p
->family
== AF_FLOWSPEC
) {
6550 route_vty_out_flowspec(vty
, p
, NULL
,
6552 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6553 NLRI_STRING_FORMAT_MIN
, json
);
6558 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6561 json_object_string_add(json
, "prefix",
6562 inet_ntop(p
->family
,
6565 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6566 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6567 json_object_string_add(json
, "network", buf2
);
6574 vty_out(vty
, "\n%*s", 20, " ");
6576 vty_out(vty
, "%*s", len
, " ");
6580 enum bgp_display_type
{
6584 /* Print the short form route status for a bgp_path_info */
6585 static void route_vty_short_status_out(struct vty
*vty
,
6586 struct bgp_path_info
*path
,
6587 json_object
*json_path
)
6591 /* Route status display. */
6592 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6593 json_object_boolean_true_add(json_path
, "removed");
6595 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6596 json_object_boolean_true_add(json_path
, "stale");
6598 if (path
->extra
&& path
->extra
->suppress
)
6599 json_object_boolean_true_add(json_path
, "suppressed");
6601 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6602 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6603 json_object_boolean_true_add(json_path
, "valid");
6606 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6607 json_object_boolean_true_add(json_path
, "history");
6609 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6610 json_object_boolean_true_add(json_path
, "damped");
6612 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6613 json_object_boolean_true_add(json_path
, "bestpath");
6615 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6616 json_object_boolean_true_add(json_path
, "multipath");
6618 /* Internal route. */
6619 if ((path
->peer
->as
)
6620 && (path
->peer
->as
== path
->peer
->local_as
))
6621 json_object_string_add(json_path
, "pathFrom",
6624 json_object_string_add(json_path
, "pathFrom",
6630 /* Route status display. */
6631 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6633 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6635 else if (path
->extra
&& path
->extra
->suppress
)
6637 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6638 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6644 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6646 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6648 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6650 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6655 /* Internal route. */
6656 if (path
->peer
&& (path
->peer
->as
)
6657 && (path
->peer
->as
== path
->peer
->local_as
))
6663 /* called from terminal list command */
6664 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6665 struct bgp_path_info
*path
, int display
, safi_t safi
,
6666 json_object
*json_paths
)
6669 json_object
*json_path
= NULL
;
6670 json_object
*json_nexthops
= NULL
;
6671 json_object
*json_nexthop_global
= NULL
;
6672 json_object
*json_nexthop_ll
= NULL
;
6673 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6675 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6676 bool nexthop_othervrf
= false;
6677 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6678 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6681 json_path
= json_object_new_object();
6683 /* short status lead text */
6684 route_vty_short_status_out(vty
, path
, json_path
);
6687 /* print prefix and mask */
6689 route_vty_out_route(p
, vty
, json_path
);
6691 vty_out(vty
, "%*s", 17, " ");
6693 route_vty_out_route(p
, vty
, json_path
);
6696 /* Print attribute */
6700 json_object_array_add(json_paths
, json_path
);
6708 * If vrf id of nexthop is different from that of prefix,
6709 * set up printable string to append
6711 if (path
->extra
&& path
->extra
->bgp_orig
) {
6712 const char *self
= "";
6717 nexthop_othervrf
= true;
6718 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6720 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6721 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6722 "@%s%s", VRFID_NONE_STR
, self
);
6724 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6725 path
->extra
->bgp_orig
->vrf_id
, self
);
6727 if (path
->extra
->bgp_orig
->inst_type
6728 != BGP_INSTANCE_TYPE_DEFAULT
)
6730 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6732 const char *self
= "";
6737 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6741 * For ENCAP and EVPN routes, nexthop address family is not
6742 * neccessarily the same as the prefix address family.
6743 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6744 * EVPN routes are also exchanged with a MP nexthop. Currently,
6746 * is only IPv4, the value will be present in either
6748 * attr->mp_nexthop_global_in
6750 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6753 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6757 sprintf(nexthop
, "%s",
6758 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6762 sprintf(nexthop
, "%s",
6763 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6767 sprintf(nexthop
, "?");
6772 json_nexthop_global
= json_object_new_object();
6774 json_object_string_add(json_nexthop_global
, "afi",
6775 (af
== AF_INET
) ? "ip" : "ipv6");
6776 json_object_string_add(json_nexthop_global
,
6777 (af
== AF_INET
) ? "ip" : "ipv6",
6779 json_object_boolean_true_add(json_nexthop_global
,
6782 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6783 } else if (safi
== SAFI_EVPN
) {
6785 json_nexthop_global
= json_object_new_object();
6787 json_object_string_add(json_nexthop_global
, "ip",
6788 inet_ntoa(attr
->nexthop
));
6789 json_object_string_add(json_nexthop_global
, "afi",
6791 json_object_boolean_true_add(json_nexthop_global
,
6794 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6796 } else if (safi
== SAFI_FLOWSPEC
) {
6797 if (attr
->nexthop
.s_addr
!= 0) {
6799 json_nexthop_global
= json_object_new_object();
6800 json_object_string_add(
6801 json_nexthop_global
, "ip",
6802 inet_ntoa(attr
->nexthop
));
6803 json_object_string_add(json_nexthop_global
,
6805 json_object_boolean_true_add(
6806 json_nexthop_global
,
6809 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6812 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6814 json_nexthop_global
= json_object_new_object();
6816 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6817 json_object_string_add(
6818 json_nexthop_global
, "ip",
6819 inet_ntoa(attr
->mp_nexthop_global_in
));
6821 json_object_string_add(
6822 json_nexthop_global
, "ip",
6823 inet_ntoa(attr
->nexthop
));
6825 json_object_string_add(json_nexthop_global
, "afi",
6827 json_object_boolean_true_add(json_nexthop_global
,
6832 snprintf(buf
, sizeof(buf
), "%s%s",
6833 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6834 vty_out(vty
, "%-16s", buf
);
6839 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6844 json_nexthop_global
= json_object_new_object();
6845 json_object_string_add(
6846 json_nexthop_global
, "ip",
6847 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6849 json_object_string_add(json_nexthop_global
, "afi",
6851 json_object_string_add(json_nexthop_global
, "scope",
6854 /* We display both LL & GL if both have been
6856 if ((attr
->mp_nexthop_len
== 32)
6857 || (path
->peer
->conf_if
)) {
6858 json_nexthop_ll
= json_object_new_object();
6859 json_object_string_add(
6860 json_nexthop_ll
, "ip",
6862 &attr
->mp_nexthop_local
, buf
,
6864 json_object_string_add(json_nexthop_ll
, "afi",
6866 json_object_string_add(json_nexthop_ll
, "scope",
6869 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6870 &attr
->mp_nexthop_local
)
6872 && !attr
->mp_nexthop_prefer_global
)
6873 json_object_boolean_true_add(
6874 json_nexthop_ll
, "used");
6876 json_object_boolean_true_add(
6877 json_nexthop_global
, "used");
6879 json_object_boolean_true_add(
6880 json_nexthop_global
, "used");
6882 /* Display LL if LL/Global both in table unless
6883 * prefer-global is set */
6884 if (((attr
->mp_nexthop_len
== 32)
6885 && !attr
->mp_nexthop_prefer_global
)
6886 || (path
->peer
->conf_if
)) {
6887 if (path
->peer
->conf_if
) {
6888 len
= vty_out(vty
, "%s",
6889 path
->peer
->conf_if
);
6890 len
= 16 - len
; /* len of IPv6
6896 vty_out(vty
, "\n%*s", 36, " ");
6898 vty_out(vty
, "%*s", len
, " ");
6904 &attr
->mp_nexthop_local
,
6910 vty_out(vty
, "\n%*s", 36, " ");
6912 vty_out(vty
, "%*s", len
, " ");
6918 &attr
->mp_nexthop_global
, buf
,
6924 vty_out(vty
, "\n%*s", 36, " ");
6926 vty_out(vty
, "%*s", len
, " ");
6932 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6936 * Adding "metric" field to match with corresponding
6937 * CLI. "med" will be deprecated in future.
6939 json_object_int_add(json_path
, "med", attr
->med
);
6940 json_object_int_add(json_path
, "metric", attr
->med
);
6942 vty_out(vty
, "%10u", attr
->med
);
6943 else if (!json_paths
)
6947 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6951 * Adding "locPrf" field to match with corresponding
6952 * CLI. "localPref" will be deprecated in future.
6954 json_object_int_add(json_path
, "localpref",
6956 json_object_int_add(json_path
, "locPrf",
6959 vty_out(vty
, "%7u", attr
->local_pref
);
6960 else if (!json_paths
)
6964 json_object_int_add(json_path
, "weight", attr
->weight
);
6966 vty_out(vty
, "%7u ", attr
->weight
);
6970 json_object_string_add(
6971 json_path
, "peerId",
6972 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6980 * Adding "path" field to match with corresponding
6981 * CLI. "aspath" will be deprecated in future.
6983 json_object_string_add(json_path
, "aspath",
6985 json_object_string_add(json_path
, "path",
6988 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6993 json_object_string_add(json_path
, "origin",
6994 bgp_origin_long_str
[attr
->origin
]);
6996 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7000 json_object_boolean_true_add(json_path
,
7001 "announceNexthopSelf");
7002 if (nexthop_othervrf
) {
7003 json_object_string_add(json_path
, "nhVrfName",
7006 json_object_int_add(json_path
, "nhVrfId",
7007 ((nexthop_vrfid
== VRF_UNKNOWN
)
7009 : (int)nexthop_vrfid
));
7014 if (json_nexthop_global
|| json_nexthop_ll
) {
7015 json_nexthops
= json_object_new_array();
7017 if (json_nexthop_global
)
7018 json_object_array_add(json_nexthops
,
7019 json_nexthop_global
);
7021 if (json_nexthop_ll
)
7022 json_object_array_add(json_nexthops
,
7025 json_object_object_add(json_path
, "nexthops",
7029 json_object_array_add(json_paths
, json_path
);
7033 /* prints an additional line, indented, with VNC info, if
7035 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7036 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7041 /* called from terminal list command */
7042 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7043 safi_t safi
, bool use_json
, json_object
*json_ar
)
7045 json_object
*json_status
= NULL
;
7046 json_object
*json_net
= NULL
;
7049 /* Route status display. */
7051 json_status
= json_object_new_object();
7052 json_net
= json_object_new_object();
7059 /* print prefix and mask */
7061 json_object_string_add(
7062 json_net
, "addrPrefix",
7063 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
7064 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
7065 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7066 json_object_string_add(json_net
, "network", buf2
);
7068 route_vty_out_route(p
, vty
, NULL
);
7070 /* Print attribute */
7073 if (p
->family
== AF_INET
7074 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7075 || safi
== SAFI_EVPN
7076 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7077 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7078 || safi
== SAFI_EVPN
)
7079 json_object_string_add(
7080 json_net
, "nextHop",
7082 attr
->mp_nexthop_global_in
));
7084 json_object_string_add(
7085 json_net
, "nextHop",
7086 inet_ntoa(attr
->nexthop
));
7087 } else if (p
->family
== AF_INET6
7088 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7091 json_object_string_add(
7092 json_net
, "nextHopGlobal",
7094 &attr
->mp_nexthop_global
, buf
,
7099 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7100 json_object_int_add(json_net
, "metric",
7103 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7106 * Adding "locPrf" field to match with
7107 * corresponding CLI. "localPref" will be
7108 * deprecated in future.
7110 json_object_int_add(json_net
, "localPref",
7112 json_object_int_add(json_net
, "locPrf",
7116 json_object_int_add(json_net
, "weight", attr
->weight
);
7122 * Adding "path" field to match with
7123 * corresponding CLI. "localPref" will be
7124 * deprecated in future.
7126 json_object_string_add(json_net
, "asPath",
7128 json_object_string_add(json_net
, "path",
7133 json_object_string_add(json_net
, "bgpOriginCode",
7134 bgp_origin_str
[attr
->origin
]);
7136 if (p
->family
== AF_INET
7137 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7138 || safi
== SAFI_EVPN
7139 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7140 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7141 || safi
== SAFI_EVPN
)
7142 vty_out(vty
, "%-16s",
7144 attr
->mp_nexthop_global_in
));
7146 vty_out(vty
, "%-16s",
7147 inet_ntoa(attr
->nexthop
));
7148 } else if (p
->family
== AF_INET6
7149 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7156 &attr
->mp_nexthop_global
, buf
,
7160 vty_out(vty
, "\n%*s", 36, " ");
7162 vty_out(vty
, "%*s", len
, " ");
7165 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7166 vty_out(vty
, "%10u", attr
->med
);
7170 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7171 vty_out(vty
, "%7u", attr
->local_pref
);
7175 vty_out(vty
, "%7u ", attr
->weight
);
7179 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7182 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7186 json_object_boolean_true_add(json_status
, "*");
7187 json_object_boolean_true_add(json_status
, ">");
7188 json_object_object_add(json_net
, "appliedStatusSymbols",
7190 char buf_cut
[BUFSIZ
];
7191 json_object_object_add(
7193 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7199 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7200 struct bgp_path_info
*path
, int display
, safi_t safi
,
7203 json_object
*json_out
= NULL
;
7205 mpls_label_t label
= MPLS_INVALID_LABEL
;
7211 json_out
= json_object_new_object();
7213 /* short status lead text */
7214 route_vty_short_status_out(vty
, path
, json_out
);
7216 /* print prefix and mask */
7219 route_vty_out_route(p
, vty
, NULL
);
7221 vty_out(vty
, "%*s", 17, " ");
7224 /* Print attribute */
7227 if (((p
->family
== AF_INET
)
7228 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7229 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7230 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7231 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7232 || safi
== SAFI_EVPN
) {
7234 json_object_string_add(
7235 json_out
, "mpNexthopGlobalIn",
7237 attr
->mp_nexthop_global_in
));
7239 vty_out(vty
, "%-16s",
7241 attr
->mp_nexthop_global_in
));
7244 json_object_string_add(
7245 json_out
, "nexthop",
7246 inet_ntoa(attr
->nexthop
));
7248 vty_out(vty
, "%-16s",
7249 inet_ntoa(attr
->nexthop
));
7251 } else if (((p
->family
== AF_INET6
)
7252 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7253 || (safi
== SAFI_EVPN
7254 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7255 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7259 if (attr
->mp_nexthop_len
7260 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7262 json_object_string_add(
7263 json_out
, "mpNexthopGlobalIn",
7266 &attr
->mp_nexthop_global
,
7267 buf_a
, sizeof(buf_a
)));
7272 &attr
->mp_nexthop_global
,
7273 buf_a
, sizeof(buf_a
)));
7274 } else if (attr
->mp_nexthop_len
7275 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7278 &attr
->mp_nexthop_global
,
7279 buf_a
, sizeof(buf_a
));
7281 &attr
->mp_nexthop_local
,
7282 buf_b
, sizeof(buf_b
));
7283 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7284 json_object_string_add(
7286 "mpNexthopGlobalLocal", buf_c
);
7288 vty_out(vty
, "%s(%s)",
7291 &attr
->mp_nexthop_global
,
7292 buf_a
, sizeof(buf_a
)),
7295 &attr
->mp_nexthop_local
,
7296 buf_b
, sizeof(buf_b
)));
7301 label
= decode_label(&path
->extra
->label
[0]);
7303 if (bgp_is_valid_label(&label
)) {
7305 json_object_int_add(json_out
, "notag", label
);
7306 json_object_array_add(json
, json_out
);
7308 vty_out(vty
, "notag/%d", label
);
7314 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7315 struct bgp_path_info
*path
, int display
,
7316 json_object
*json_paths
)
7320 json_object
*json_path
= NULL
;
7323 json_path
= json_object_new_object();
7328 /* short status lead text */
7329 route_vty_short_status_out(vty
, path
, json_path
);
7331 /* print prefix and mask */
7333 route_vty_out_route(p
, vty
, NULL
);
7335 vty_out(vty
, "%*s", 17, " ");
7337 /* Print attribute */
7341 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7345 vty_out(vty
, "%-16s",
7346 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7350 vty_out(vty
, "%s(%s)",
7351 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7353 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7360 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7362 vty_out(vty
, "%s", str
);
7363 XFREE(MTYPE_TMP
, str
);
7365 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7367 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7368 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7371 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7374 if (attr
->ecommunity
) {
7376 struct ecommunity_val
*routermac
= ecommunity_lookup(
7377 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7378 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7380 mac
= ecom_mac2str((char *)routermac
->val
);
7382 vty_out(vty
, "/%s", (char *)mac
);
7383 XFREE(MTYPE_TMP
, mac
);
7391 /* dampening route */
7392 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7393 struct bgp_path_info
*path
, int display
,
7394 safi_t safi
, bool use_json
, json_object
*json
)
7398 char timebuf
[BGP_UPTIME_LEN
];
7400 /* short status lead text */
7401 route_vty_short_status_out(vty
, path
, json
);
7403 /* print prefix and mask */
7406 route_vty_out_route(p
, vty
, NULL
);
7408 vty_out(vty
, "%*s", 17, " ");
7411 len
= vty_out(vty
, "%s", path
->peer
->host
);
7415 vty_out(vty
, "\n%*s", 34, " ");
7418 json_object_int_add(json
, "peerHost", len
);
7420 vty_out(vty
, "%*s", len
, " ");
7424 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7428 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7429 BGP_UPTIME_LEN
, use_json
,
7432 /* Print attribute */
7438 json_object_string_add(json
, "asPath",
7441 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7446 json_object_string_add(json
, "origin",
7447 bgp_origin_str
[attr
->origin
]);
7449 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7456 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7457 struct bgp_path_info
*path
, int display
,
7458 safi_t safi
, bool use_json
, json_object
*json
)
7461 struct bgp_damp_info
*bdi
;
7462 char timebuf
[BGP_UPTIME_LEN
];
7468 bdi
= path
->extra
->damp_info
;
7470 /* short status lead text */
7471 route_vty_short_status_out(vty
, path
, json
);
7473 /* print prefix and mask */
7476 route_vty_out_route(p
, vty
, NULL
);
7478 vty_out(vty
, "%*s", 17, " ");
7481 len
= vty_out(vty
, "%s", path
->peer
->host
);
7485 vty_out(vty
, "\n%*s", 33, " ");
7488 json_object_int_add(json
, "peerHost", len
);
7490 vty_out(vty
, "%*s", len
, " ");
7493 len
= vty_out(vty
, "%d", bdi
->flap
);
7500 json_object_int_add(json
, "bdiFlap", len
);
7502 vty_out(vty
, "%*s", len
, " ");
7506 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7509 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7510 BGP_UPTIME_LEN
, 0, NULL
));
7512 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7513 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7515 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7516 BGP_UPTIME_LEN
, use_json
, json
);
7519 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7524 vty_out(vty
, "%*s ", 8, " ");
7527 /* Print attribute */
7533 json_object_string_add(json
, "asPath",
7536 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7541 json_object_string_add(json
, "origin",
7542 bgp_origin_str
[attr
->origin
]);
7544 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7550 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7551 int *first
, const char *header
,
7552 json_object
*json_adv_to
)
7554 char buf1
[INET6_ADDRSTRLEN
];
7555 json_object
*json_peer
= NULL
;
7558 /* 'advertised-to' is a dictionary of peers we have advertised
7560 * prefix too. The key is the peer's IP or swpX, the value is
7562 * hostname if we know it and "" if not.
7564 json_peer
= json_object_new_object();
7567 json_object_string_add(json_peer
, "hostname",
7571 json_object_object_add(json_adv_to
, peer
->conf_if
,
7574 json_object_object_add(
7576 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7580 vty_out(vty
, "%s", header
);
7585 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7587 vty_out(vty
, " %s(%s)", peer
->hostname
,
7590 vty_out(vty
, " %s(%s)", peer
->hostname
,
7591 sockunion2str(&peer
->su
, buf1
,
7595 vty_out(vty
, " %s", peer
->conf_if
);
7598 sockunion2str(&peer
->su
, buf1
,
7604 static void route_vty_out_tx_ids(struct vty
*vty
,
7605 struct bgp_addpath_info_data
*d
)
7609 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7610 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7611 d
->addpath_tx_id
[i
],
7612 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7616 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7617 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7618 json_object
*json_paths
)
7620 char buf
[INET6_ADDRSTRLEN
];
7622 char buf2
[EVPN_ROUTE_STRLEN
];
7624 int sockunion_vty_out(struct vty
*, union sockunion
*);
7626 json_object
*json_bestpath
= NULL
;
7627 json_object
*json_cluster_list
= NULL
;
7628 json_object
*json_cluster_list_list
= NULL
;
7629 json_object
*json_ext_community
= NULL
;
7630 json_object
*json_last_update
= NULL
;
7631 json_object
*json_pmsi
= NULL
;
7632 json_object
*json_nexthop_global
= NULL
;
7633 json_object
*json_nexthop_ll
= NULL
;
7634 json_object
*json_nexthops
= NULL
;
7635 json_object
*json_path
= NULL
;
7636 json_object
*json_peer
= NULL
;
7637 json_object
*json_string
= NULL
;
7638 json_object
*json_adv_to
= NULL
;
7640 struct listnode
*node
, *nnode
;
7642 int addpath_capable
;
7644 unsigned int first_as
;
7646 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7650 json_path
= json_object_new_object();
7651 json_peer
= json_object_new_object();
7652 json_nexthop_global
= json_object_new_object();
7655 if (!json_paths
&& safi
== SAFI_EVPN
) {
7658 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7659 vty_out(vty
, " Route %s", buf2
);
7661 if (path
->extra
&& path
->extra
->num_labels
) {
7662 bgp_evpn_label2str(path
->extra
->label
,
7663 path
->extra
->num_labels
, tag_buf
,
7665 vty_out(vty
, " VNI %s", tag_buf
);
7668 if (path
->extra
&& path
->extra
->parent
) {
7669 struct bgp_path_info
*parent_ri
;
7670 struct bgp_node
*rn
, *prn
;
7672 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7673 rn
= parent_ri
->net
;
7674 if (rn
&& rn
->prn
) {
7676 vty_out(vty
, " Imported from %s:%s\n",
7678 (struct prefix_rd
*)&prn
->p
,
7679 buf1
, sizeof(buf1
)),
7688 /* Line1 display AS-path, Aggregator */
7691 if (!attr
->aspath
->json
)
7692 aspath_str_update(attr
->aspath
, true);
7693 json_object_lock(attr
->aspath
->json
);
7694 json_object_object_add(json_path
, "aspath",
7695 attr
->aspath
->json
);
7697 if (attr
->aspath
->segments
)
7698 aspath_print_vty(vty
, " %s",
7701 vty_out(vty
, " Local");
7705 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7707 json_object_boolean_true_add(json_path
,
7710 vty_out(vty
, ", (removed)");
7713 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7715 json_object_boolean_true_add(json_path
,
7718 vty_out(vty
, ", (stale)");
7721 if (CHECK_FLAG(attr
->flag
,
7722 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7724 json_object_int_add(json_path
, "aggregatorAs",
7725 attr
->aggregator_as
);
7726 json_object_string_add(
7727 json_path
, "aggregatorId",
7728 inet_ntoa(attr
->aggregator_addr
));
7730 vty_out(vty
, ", (aggregated by %u %s)",
7731 attr
->aggregator_as
,
7732 inet_ntoa(attr
->aggregator_addr
));
7736 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7737 PEER_FLAG_REFLECTOR_CLIENT
)) {
7739 json_object_boolean_true_add(
7740 json_path
, "rxedFromRrClient");
7742 vty_out(vty
, ", (Received from a RR-client)");
7745 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7746 PEER_FLAG_RSERVER_CLIENT
)) {
7748 json_object_boolean_true_add(
7749 json_path
, "rxedFromRsClient");
7751 vty_out(vty
, ", (Received from a RS-client)");
7754 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7756 json_object_boolean_true_add(
7757 json_path
, "dampeningHistoryEntry");
7759 vty_out(vty
, ", (history entry)");
7760 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
7762 json_object_boolean_true_add(
7763 json_path
, "dampeningSuppressed");
7765 vty_out(vty
, ", (suppressed due to dampening)");
7771 /* Line2 display Next-hop, Neighbor, Router-id */
7772 /* Display the nexthop */
7773 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7774 || p
->family
== AF_EVPN
)
7775 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7776 || safi
== SAFI_EVPN
7777 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7778 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7779 || safi
== SAFI_EVPN
) {
7781 json_object_string_add(
7782 json_nexthop_global
, "ip",
7784 attr
->mp_nexthop_global_in
));
7788 attr
->mp_nexthop_global_in
));
7791 json_object_string_add(
7792 json_nexthop_global
, "ip",
7793 inet_ntoa(attr
->nexthop
));
7796 inet_ntoa(attr
->nexthop
));
7800 json_object_string_add(json_nexthop_global
,
7804 json_object_string_add(
7805 json_nexthop_global
, "ip",
7807 &attr
->mp_nexthop_global
, buf
,
7809 json_object_string_add(json_nexthop_global
,
7811 json_object_string_add(json_nexthop_global
,
7816 &attr
->mp_nexthop_global
, buf
,
7821 /* Display the IGP cost or 'inaccessible' */
7822 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
7824 json_object_boolean_false_add(
7825 json_nexthop_global
, "accessible");
7827 vty_out(vty
, " (inaccessible)");
7829 if (path
->extra
&& path
->extra
->igpmetric
) {
7831 json_object_int_add(
7832 json_nexthop_global
, "metric",
7833 path
->extra
->igpmetric
);
7835 vty_out(vty
, " (metric %u)",
7836 path
->extra
->igpmetric
);
7839 /* IGP cost is 0, display this only for json */
7842 json_object_int_add(json_nexthop_global
,
7847 json_object_boolean_true_add(
7848 json_nexthop_global
, "accessible");
7851 /* Display peer "from" output */
7852 /* This path was originated locally */
7853 if (path
->peer
== bgp
->peer_self
) {
7855 if (safi
== SAFI_EVPN
7856 || (p
->family
== AF_INET
7857 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7859 json_object_string_add(
7860 json_peer
, "peerId", "0.0.0.0");
7862 vty_out(vty
, " from 0.0.0.0 ");
7865 json_object_string_add(json_peer
,
7868 vty_out(vty
, " from :: ");
7872 json_object_string_add(
7873 json_peer
, "routerId",
7874 inet_ntoa(bgp
->router_id
));
7876 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7879 /* We RXed this path from one of our peers */
7883 json_object_string_add(
7884 json_peer
, "peerId",
7885 sockunion2str(&path
->peer
->su
, buf
,
7887 json_object_string_add(
7888 json_peer
, "routerId",
7890 &path
->peer
->remote_id
, buf1
,
7893 if (path
->peer
->hostname
)
7894 json_object_string_add(
7895 json_peer
, "hostname",
7896 path
->peer
->hostname
);
7898 if (path
->peer
->domainname
)
7899 json_object_string_add(
7900 json_peer
, "domainname",
7901 path
->peer
->domainname
);
7903 if (path
->peer
->conf_if
)
7904 json_object_string_add(
7905 json_peer
, "interface",
7906 path
->peer
->conf_if
);
7908 if (path
->peer
->conf_if
) {
7909 if (path
->peer
->hostname
7912 BGP_FLAG_SHOW_HOSTNAME
))
7913 vty_out(vty
, " from %s(%s)",
7914 path
->peer
->hostname
,
7915 path
->peer
->conf_if
);
7917 vty_out(vty
, " from %s",
7918 path
->peer
->conf_if
);
7920 if (path
->peer
->hostname
7923 BGP_FLAG_SHOW_HOSTNAME
))
7924 vty_out(vty
, " from %s(%s)",
7925 path
->peer
->hostname
,
7928 vty_out(vty
, " from %s",
7936 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7937 vty_out(vty
, " (%s)",
7938 inet_ntoa(attr
->originator_id
));
7940 vty_out(vty
, " (%s)",
7943 &path
->peer
->remote_id
,
7944 buf1
, sizeof(buf1
)));
7949 * Note when vrfid of nexthop is different from that of prefix
7951 if (path
->extra
&& path
->extra
->bgp_orig
) {
7952 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7957 if (path
->extra
->bgp_orig
->inst_type
7958 == BGP_INSTANCE_TYPE_DEFAULT
)
7960 vn
= VRF_DEFAULT_NAME
;
7962 vn
= path
->extra
->bgp_orig
->name
;
7964 json_object_string_add(json_path
, "nhVrfName",
7967 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7968 json_object_int_add(json_path
,
7971 json_object_int_add(json_path
,
7972 "nhVrfId", (int)nexthop_vrfid
);
7975 if (nexthop_vrfid
== VRF_UNKNOWN
)
7976 vty_out(vty
, " vrf ?");
7978 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7984 json_object_boolean_true_add(json_path
,
7985 "announceNexthopSelf");
7987 vty_out(vty
, " announce-nh-self");
7994 /* display the link-local nexthop */
7995 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7997 json_nexthop_ll
= json_object_new_object();
7998 json_object_string_add(
7999 json_nexthop_ll
, "ip",
8001 &attr
->mp_nexthop_local
, buf
,
8003 json_object_string_add(json_nexthop_ll
, "afi",
8005 json_object_string_add(json_nexthop_ll
, "scope",
8008 json_object_boolean_true_add(json_nexthop_ll
,
8011 if (!attr
->mp_nexthop_prefer_global
)
8012 json_object_boolean_true_add(
8013 json_nexthop_ll
, "used");
8015 json_object_boolean_true_add(
8016 json_nexthop_global
, "used");
8018 vty_out(vty
, " (%s) %s\n",
8020 &attr
->mp_nexthop_local
, buf
,
8022 attr
->mp_nexthop_prefer_global
8027 /* If we do not have a link-local nexthop then we must flag the
8031 json_object_boolean_true_add(
8032 json_nexthop_global
, "used");
8035 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8036 * Int/Ext/Local, Atomic, best */
8038 json_object_string_add(
8039 json_path
, "origin",
8040 bgp_origin_long_str
[attr
->origin
]);
8042 vty_out(vty
, " Origin %s",
8043 bgp_origin_long_str
[attr
->origin
]);
8045 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8049 * Adding "metric" field to match with
8050 * corresponding CLI. "med" will be
8051 * deprecated in future.
8053 json_object_int_add(json_path
, "med",
8055 json_object_int_add(json_path
, "metric",
8058 vty_out(vty
, ", metric %u", attr
->med
);
8061 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8063 json_object_int_add(json_path
, "localpref",
8066 vty_out(vty
, ", localpref %u",
8070 if (attr
->weight
!= 0) {
8072 json_object_int_add(json_path
, "weight",
8075 vty_out(vty
, ", weight %u", attr
->weight
);
8078 if (attr
->tag
!= 0) {
8080 json_object_int_add(json_path
, "tag",
8083 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8087 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8089 json_object_boolean_false_add(json_path
,
8092 vty_out(vty
, ", invalid");
8093 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8095 json_object_boolean_true_add(json_path
,
8098 vty_out(vty
, ", valid");
8101 if (path
->peer
!= bgp
->peer_self
) {
8102 if (path
->peer
->as
== path
->peer
->local_as
) {
8103 if (CHECK_FLAG(bgp
->config
,
8104 BGP_CONFIG_CONFEDERATION
)) {
8106 json_object_string_add(
8111 ", confed-internal");
8114 json_object_string_add(
8118 vty_out(vty
, ", internal");
8121 if (bgp_confederation_peers_check(
8122 bgp
, path
->peer
->as
)) {
8124 json_object_string_add(
8129 ", confed-external");
8132 json_object_string_add(
8136 vty_out(vty
, ", external");
8139 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8141 json_object_boolean_true_add(json_path
,
8143 json_object_boolean_true_add(json_path
,
8146 vty_out(vty
, ", aggregated, local");
8148 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8150 json_object_boolean_true_add(json_path
,
8153 vty_out(vty
, ", sourced");
8156 json_object_boolean_true_add(json_path
,
8158 json_object_boolean_true_add(json_path
,
8161 vty_out(vty
, ", sourced, local");
8165 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8167 json_object_boolean_true_add(json_path
,
8170 vty_out(vty
, ", atomic-aggregate");
8173 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8174 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8175 && bgp_path_info_mpath_count(path
))) {
8177 json_object_boolean_true_add(json_path
,
8180 vty_out(vty
, ", multipath");
8183 // Mark the bestpath(s)
8184 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8185 first_as
= aspath_get_first_as(attr
->aspath
);
8190 json_object_new_object();
8191 json_object_int_add(json_bestpath
,
8192 "bestpathFromAs", first_as
);
8195 vty_out(vty
, ", bestpath-from-AS %u",
8199 ", bestpath-from-AS Local");
8203 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8207 json_object_new_object();
8208 json_object_boolean_true_add(json_bestpath
,
8211 vty_out(vty
, ", best");
8215 json_object_object_add(json_path
, "bestpath",
8221 /* Line 4 display Community */
8222 if (attr
->community
) {
8224 if (!attr
->community
->json
)
8225 community_str(attr
->community
, true);
8226 json_object_lock(attr
->community
->json
);
8227 json_object_object_add(json_path
, "community",
8228 attr
->community
->json
);
8230 vty_out(vty
, " Community: %s\n",
8231 attr
->community
->str
);
8235 /* Line 5 display Extended-community */
8236 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8238 json_ext_community
= json_object_new_object();
8239 json_object_string_add(json_ext_community
,
8241 attr
->ecommunity
->str
);
8242 json_object_object_add(json_path
,
8243 "extendedCommunity",
8244 json_ext_community
);
8246 vty_out(vty
, " Extended Community: %s\n",
8247 attr
->ecommunity
->str
);
8251 /* Line 6 display Large community */
8252 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8254 if (!attr
->lcommunity
->json
)
8255 lcommunity_str(attr
->lcommunity
, true);
8256 json_object_lock(attr
->lcommunity
->json
);
8257 json_object_object_add(json_path
,
8259 attr
->lcommunity
->json
);
8261 vty_out(vty
, " Large Community: %s\n",
8262 attr
->lcommunity
->str
);
8266 /* Line 7 display Originator, Cluster-id */
8267 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8268 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8270 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8272 json_object_string_add(
8273 json_path
, "originatorId",
8274 inet_ntoa(attr
->originator_id
));
8276 vty_out(vty
, " Originator: %s",
8277 inet_ntoa(attr
->originator_id
));
8280 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8285 json_object_new_object();
8286 json_cluster_list_list
=
8287 json_object_new_array();
8290 i
< attr
->cluster
->length
/ 4;
8292 json_string
= json_object_new_string(
8296 json_object_array_add(
8297 json_cluster_list_list
,
8301 /* struct cluster_list does not have
8303 * aspath and community do. Add this
8306 json_object_string_add(json_cluster_list,
8307 "string", attr->cluster->str);
8309 json_object_object_add(
8310 json_cluster_list
, "list",
8311 json_cluster_list_list
);
8312 json_object_object_add(
8313 json_path
, "clusterList",
8316 vty_out(vty
, ", Cluster list: ");
8319 i
< attr
->cluster
->length
/ 4;
8333 if (path
->extra
&& path
->extra
->damp_info
)
8334 bgp_damp_info_vty(vty
, path
, json_path
);
8337 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8338 && safi
!= SAFI_EVPN
) {
8339 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8342 json_object_int_add(json_path
, "remoteLabel",
8345 vty_out(vty
, " Remote label: %d\n", label
);
8349 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8351 json_object_int_add(json_path
, "labelIndex",
8354 vty_out(vty
, " Label Index: %d\n",
8358 /* Line 8 display Addpath IDs */
8359 if (path
->addpath_rx_id
8360 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8362 json_object_int_add(json_path
, "addpathRxId",
8363 path
->addpath_rx_id
);
8365 /* Keep backwards compatibility with the old API
8366 * by putting TX All's ID in the old field
8368 json_object_int_add(
8369 json_path
, "addpathTxId",
8370 path
->tx_addpath
.addpath_tx_id
8373 /* ... but create a specific field for each
8376 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8377 json_object_int_add(
8379 bgp_addpath_names(i
)
8385 vty_out(vty
, " AddPath ID: RX %u, ",
8386 path
->addpath_rx_id
);
8388 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8392 /* If we used addpath to TX a non-bestpath we need to display
8393 * "Advertised to" on a path-by-path basis
8395 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8398 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8400 bgp_addpath_encode_tx(peer
, afi
, safi
);
8401 has_adj
= bgp_adj_out_lookup(
8403 bgp_addpath_id_for_peer(
8405 &path
->tx_addpath
));
8407 if ((addpath_capable
&& has_adj
)
8408 || (!addpath_capable
&& has_adj
8409 && CHECK_FLAG(path
->flags
,
8410 BGP_PATH_SELECTED
))) {
8411 if (json_path
&& !json_adv_to
)
8413 json_object_new_object();
8415 route_vty_out_advertised_to(
8424 json_object_object_add(json_path
,
8435 /* Line 9 display Uptime */
8436 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8438 json_last_update
= json_object_new_object();
8439 json_object_int_add(json_last_update
, "epoch", tbuf
);
8440 json_object_string_add(json_last_update
, "string",
8442 json_object_object_add(json_path
, "lastUpdate",
8445 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8447 /* Line 10 display PMSI tunnel attribute, if present */
8448 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8449 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8450 attr
->pmsi_tnl_type
,
8451 PMSI_TNLTYPE_STR_DEFAULT
);
8454 json_pmsi
= json_object_new_object();
8455 json_object_string_add(json_pmsi
,
8457 json_object_int_add(json_pmsi
,
8459 label2vni(&attr
->label
));
8460 json_object_object_add(json_path
, "pmsi",
8464 " PMSI Tunnel Type: %s, label: %d\n",
8465 str
, label2vni(&attr
->label
));
8470 /* We've constructed the json object for this path, add it to the json
8474 if (json_nexthop_global
|| json_nexthop_ll
) {
8475 json_nexthops
= json_object_new_array();
8477 if (json_nexthop_global
)
8478 json_object_array_add(json_nexthops
,
8479 json_nexthop_global
);
8481 if (json_nexthop_ll
)
8482 json_object_array_add(json_nexthops
,
8485 json_object_object_add(json_path
, "nexthops",
8489 json_object_object_add(json_path
, "peer", json_peer
);
8490 json_object_array_add(json_paths
, json_path
);
8495 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8496 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8497 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8499 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8500 const char *prefix_list_str
, afi_t afi
,
8501 safi_t safi
, enum bgp_show_type type
);
8502 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8503 const char *filter
, afi_t afi
, safi_t safi
,
8504 enum bgp_show_type type
);
8505 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8506 const char *rmap_str
, afi_t afi
, safi_t safi
,
8507 enum bgp_show_type type
);
8508 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8509 const char *com
, int exact
, afi_t afi
,
8511 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8512 const char *prefix
, afi_t afi
, safi_t safi
,
8513 enum bgp_show_type type
);
8514 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8515 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8516 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8517 const char *comstr
, int exact
, afi_t afi
,
8518 safi_t safi
, bool use_json
);
8521 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8522 struct bgp_table
*table
, enum bgp_show_type type
,
8523 void *output_arg
, bool use_json
, char *rd
,
8524 int is_last
, unsigned long *output_cum
,
8525 unsigned long *total_cum
,
8526 unsigned long *json_header_depth
)
8528 struct bgp_path_info
*pi
;
8529 struct bgp_node
*rn
;
8532 unsigned long output_count
= 0;
8533 unsigned long total_count
= 0;
8536 json_object
*json_paths
= NULL
;
8539 if (output_cum
&& *output_cum
!= 0)
8542 if (use_json
&& !*json_header_depth
) {
8544 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8545 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8546 " \"localAS\": %u,\n \"routes\": { ",
8547 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8548 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8551 table
->version
, inet_ntoa(bgp
->router_id
),
8552 bgp
->default_local_pref
, bgp
->as
);
8553 *json_header_depth
= 2;
8555 vty_out(vty
, " \"routeDistinguishers\" : {");
8556 ++*json_header_depth
;
8560 if (use_json
&& rd
) {
8561 vty_out(vty
, " \"%s\" : { ", rd
);
8564 /* Start processing of routes. */
8565 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8566 pi
= bgp_node_get_bgp_path_info(rn
);
8572 json_paths
= json_object_new_array();
8576 for (; pi
; pi
= pi
->next
) {
8578 if (type
== bgp_show_type_flap_statistics
8579 || type
== bgp_show_type_flap_neighbor
8580 || type
== bgp_show_type_dampend_paths
8581 || type
== bgp_show_type_damp_neighbor
) {
8582 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8585 if (type
== bgp_show_type_regexp
) {
8586 regex_t
*regex
= output_arg
;
8588 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8592 if (type
== bgp_show_type_prefix_list
) {
8593 struct prefix_list
*plist
= output_arg
;
8595 if (prefix_list_apply(plist
, &rn
->p
)
8599 if (type
== bgp_show_type_filter_list
) {
8600 struct as_list
*as_list
= output_arg
;
8602 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8603 != AS_FILTER_PERMIT
)
8606 if (type
== bgp_show_type_route_map
) {
8607 struct route_map
*rmap
= output_arg
;
8608 struct bgp_path_info path
;
8609 struct attr dummy_attr
;
8612 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8614 path
.peer
= pi
->peer
;
8615 path
.attr
= &dummy_attr
;
8617 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8619 if (ret
== RMAP_DENYMATCH
)
8622 if (type
== bgp_show_type_neighbor
8623 || type
== bgp_show_type_flap_neighbor
8624 || type
== bgp_show_type_damp_neighbor
) {
8625 union sockunion
*su
= output_arg
;
8627 if (pi
->peer
== NULL
8628 || pi
->peer
->su_remote
== NULL
8629 || !sockunion_same(pi
->peer
->su_remote
, su
))
8632 if (type
== bgp_show_type_cidr_only
) {
8633 uint32_t destination
;
8635 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8636 if (IN_CLASSC(destination
)
8637 && rn
->p
.prefixlen
== 24)
8639 if (IN_CLASSB(destination
)
8640 && rn
->p
.prefixlen
== 16)
8642 if (IN_CLASSA(destination
)
8643 && rn
->p
.prefixlen
== 8)
8646 if (type
== bgp_show_type_prefix_longer
) {
8648 if (!prefix_match(p
, &rn
->p
))
8651 if (type
== bgp_show_type_community_all
) {
8652 if (!pi
->attr
->community
)
8655 if (type
== bgp_show_type_community
) {
8656 struct community
*com
= output_arg
;
8658 if (!pi
->attr
->community
8659 || !community_match(pi
->attr
->community
,
8663 if (type
== bgp_show_type_community_exact
) {
8664 struct community
*com
= output_arg
;
8666 if (!pi
->attr
->community
8667 || !community_cmp(pi
->attr
->community
, com
))
8670 if (type
== bgp_show_type_community_list
) {
8671 struct community_list
*list
= output_arg
;
8673 if (!community_list_match(pi
->attr
->community
,
8677 if (type
== bgp_show_type_community_list_exact
) {
8678 struct community_list
*list
= output_arg
;
8680 if (!community_list_exact_match(
8681 pi
->attr
->community
, list
))
8684 if (type
== bgp_show_type_lcommunity
) {
8685 struct lcommunity
*lcom
= output_arg
;
8687 if (!pi
->attr
->lcommunity
8688 || !lcommunity_match(pi
->attr
->lcommunity
,
8692 if (type
== bgp_show_type_lcommunity_list
) {
8693 struct community_list
*list
= output_arg
;
8695 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8699 if (type
== bgp_show_type_lcommunity_all
) {
8700 if (!pi
->attr
->lcommunity
)
8703 if (type
== bgp_show_type_dampend_paths
8704 || type
== bgp_show_type_damp_neighbor
) {
8705 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8706 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8710 if (!use_json
&& header
) {
8711 vty_out(vty
, "BGP table version is %" PRIu64
8712 ", local router ID is %s, vrf id ",
8714 inet_ntoa(bgp
->router_id
));
8715 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8716 vty_out(vty
, "%s", VRFID_NONE_STR
);
8718 vty_out(vty
, "%u", bgp
->vrf_id
);
8720 vty_out(vty
, "Default local pref %u, ",
8721 bgp
->default_local_pref
);
8722 vty_out(vty
, "local AS %u\n", bgp
->as
);
8723 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8724 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8725 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8726 if (type
== bgp_show_type_dampend_paths
8727 || type
== bgp_show_type_damp_neighbor
)
8728 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8729 else if (type
== bgp_show_type_flap_statistics
8730 || type
== bgp_show_type_flap_neighbor
)
8731 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8733 vty_out(vty
, BGP_SHOW_HEADER
);
8736 if (rd
!= NULL
&& !display
&& !output_count
) {
8739 "Route Distinguisher: %s\n",
8742 if (type
== bgp_show_type_dampend_paths
8743 || type
== bgp_show_type_damp_neighbor
)
8744 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
8745 safi
, use_json
, json_paths
);
8746 else if (type
== bgp_show_type_flap_statistics
8747 || type
== bgp_show_type_flap_neighbor
)
8748 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
8749 safi
, use_json
, json_paths
);
8751 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
8763 if (p
->family
== AF_FLOWSPEC
) {
8764 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
8766 bgp_fs_nlri_get_string((unsigned char *)
8767 p
->u
.prefix_flowspec
.ptr
,
8768 p
->u
.prefix_flowspec
8771 NLRI_STRING_FORMAT_MIN
,
8774 vty_out(vty
, "\"%s/%d\": ",
8776 p
->u
.prefix_flowspec
.prefixlen
);
8778 vty_out(vty
, ",\"%s/%d\": ",
8780 p
->u
.prefix_flowspec
.prefixlen
);
8782 prefix2str(p
, buf2
, sizeof(buf2
));
8784 vty_out(vty
, "\"%s\": ", buf2
);
8786 vty_out(vty
, ",\"%s\": ", buf2
);
8789 json_object_to_json_string(json_paths
));
8790 json_object_free(json_paths
);
8797 output_count
+= *output_cum
;
8798 *output_cum
= output_count
;
8801 total_count
+= *total_cum
;
8802 *total_cum
= total_count
;
8806 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8810 for (i
= 0; i
< *json_header_depth
; ++i
)
8811 vty_out(vty
, " } ");
8815 /* No route is displayed */
8816 if (output_count
== 0) {
8817 if (type
== bgp_show_type_normal
)
8819 "No BGP prefixes displayed, %ld exist\n",
8823 "\nDisplayed %ld routes and %ld total paths\n",
8824 output_count
, total_count
);
8831 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8832 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8833 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8835 struct bgp_node
*rn
, *next
;
8836 unsigned long output_cum
= 0;
8837 unsigned long total_cum
= 0;
8838 unsigned long json_header_depth
= 0;
8839 struct bgp_table
*itable
;
8842 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8844 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8845 next
= bgp_route_next(rn
);
8846 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8849 itable
= bgp_node_get_bgp_table_info(rn
);
8850 if (itable
!= NULL
) {
8851 struct prefix_rd prd
;
8852 char rd
[RD_ADDRSTRLEN
];
8854 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8855 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8856 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
8857 use_json
, rd
, next
== NULL
, &output_cum
,
8858 &total_cum
, &json_header_depth
);
8864 if (output_cum
== 0)
8865 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8869 "\nDisplayed %ld routes and %ld total paths\n",
8870 output_cum
, total_cum
);
8874 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8875 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8877 struct bgp_table
*table
;
8878 unsigned long json_header_depth
= 0;
8881 bgp
= bgp_get_default();
8886 vty_out(vty
, "No BGP process is configured\n");
8888 vty_out(vty
, "{}\n");
8892 table
= bgp
->rib
[afi
][safi
];
8893 /* use MPLS and ENCAP specific shows until they are merged */
8894 if (safi
== SAFI_MPLS_VPN
) {
8895 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8896 output_arg
, use_json
);
8899 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8900 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8901 output_arg
, use_json
,
8904 /* labeled-unicast routes live in the unicast table */
8905 else if (safi
== SAFI_LABELED_UNICAST
)
8906 safi
= SAFI_UNICAST
;
8908 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8909 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8912 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8913 safi_t safi
, bool use_json
)
8915 struct listnode
*node
, *nnode
;
8918 bool route_output
= false;
8921 vty_out(vty
, "{\n");
8923 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8924 route_output
= true;
8927 vty_out(vty
, ",\n");
8931 vty_out(vty
, "\"%s\":",
8932 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8936 vty_out(vty
, "\nInstance %s:\n",
8937 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8941 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8946 vty_out(vty
, "}\n");
8947 else if (!route_output
)
8948 vty_out(vty
, "%% BGP instance not found\n");
8951 /* Header of detailed BGP route information */
8952 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8953 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8954 afi_t afi
, safi_t safi
, json_object
*json
)
8956 struct bgp_path_info
*pi
;
8959 struct listnode
*node
, *nnode
;
8960 char buf1
[RD_ADDRSTRLEN
];
8961 char buf2
[INET6_ADDRSTRLEN
];
8962 char buf3
[EVPN_ROUTE_STRLEN
];
8963 char prefix_str
[BUFSIZ
];
8968 int route_filter_translated_v4
= 0;
8969 int route_filter_v4
= 0;
8970 int route_filter_translated_v6
= 0;
8971 int route_filter_v6
= 0;
8974 int accept_own_nexthop
= 0;
8977 int no_advertise
= 0;
8981 int has_valid_label
= 0;
8982 mpls_label_t label
= 0;
8983 json_object
*json_adv_to
= NULL
;
8986 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8988 if (has_valid_label
)
8989 label
= label_pton(&rn
->local_label
);
8992 if (has_valid_label
)
8993 json_object_int_add(json
, "localLabel", label
);
8995 json_object_string_add(
8997 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8999 if (safi
== SAFI_EVPN
)
9000 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9001 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9004 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9005 buf3
, sizeof(buf3
)));
9007 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9008 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9009 ? prefix_rd2str(prd
, buf1
,
9012 safi
== SAFI_MPLS_VPN
? ":" : "",
9013 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9017 if (has_valid_label
)
9018 vty_out(vty
, "Local label: %d\n", label
);
9019 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9020 vty_out(vty
, "not allocated\n");
9023 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9025 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9027 if (pi
->extra
&& pi
->extra
->suppress
)
9030 if (pi
->attr
->community
== NULL
)
9033 no_advertise
+= community_include(
9034 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9035 no_export
+= community_include(pi
->attr
->community
,
9036 COMMUNITY_NO_EXPORT
);
9037 local_as
+= community_include(pi
->attr
->community
,
9038 COMMUNITY_LOCAL_AS
);
9039 accept_own
+= community_include(pi
->attr
->community
,
9040 COMMUNITY_ACCEPT_OWN
);
9041 route_filter_translated_v4
+= community_include(
9042 pi
->attr
->community
,
9043 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9044 route_filter_translated_v6
+= community_include(
9045 pi
->attr
->community
,
9046 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9047 route_filter_v4
+= community_include(
9048 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9049 route_filter_v6
+= community_include(
9050 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9051 llgr_stale
+= community_include(pi
->attr
->community
,
9052 COMMUNITY_LLGR_STALE
);
9053 no_llgr
+= community_include(pi
->attr
->community
,
9055 accept_own_nexthop
+=
9056 community_include(pi
->attr
->community
,
9057 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9058 blackhole
+= community_include(pi
->attr
->community
,
9059 COMMUNITY_BLACKHOLE
);
9060 no_peer
+= community_include(pi
->attr
->community
,
9066 vty_out(vty
, "Paths: (%d available", count
);
9068 vty_out(vty
, ", best #%d", best
);
9069 if (safi
== SAFI_UNICAST
)
9070 vty_out(vty
, ", table %s",
9072 == BGP_INSTANCE_TYPE_DEFAULT
)
9076 vty_out(vty
, ", no best path");
9080 ", accept own local route exported and imported in different VRF");
9081 else if (route_filter_translated_v4
)
9083 ", mark translated RTs for VPNv4 route filtering");
9084 else if (route_filter_v4
)
9086 ", attach RT as-is for VPNv4 route filtering");
9087 else if (route_filter_translated_v6
)
9089 ", mark translated RTs for VPNv6 route filtering");
9090 else if (route_filter_v6
)
9092 ", attach RT as-is for VPNv6 route filtering");
9093 else if (llgr_stale
)
9095 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9098 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9099 else if (accept_own_nexthop
)
9101 ", accept local nexthop");
9103 vty_out(vty
, ", inform peer to blackhole prefix");
9105 vty_out(vty
, ", not advertised to EBGP peer");
9106 else if (no_advertise
)
9107 vty_out(vty
, ", not advertised to any peer");
9109 vty_out(vty
, ", not advertised outside local AS");
9112 ", inform EBGP peer not to advertise to their EBGP peers");
9116 ", Advertisements suppressed by an aggregate.");
9117 vty_out(vty
, ")\n");
9120 /* If we are not using addpath then we can display Advertised to and
9122 * show what peers we advertised the bestpath to. If we are using
9124 * though then we must display Advertised to on a path-by-path basis. */
9125 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9126 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9127 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9128 if (json
&& !json_adv_to
)
9129 json_adv_to
= json_object_new_object();
9131 route_vty_out_advertised_to(
9133 " Advertised to non peer-group peers:\n ",
9140 json_object_object_add(json
, "advertisedTo",
9145 vty_out(vty
, " Not advertised to any peer");
9151 /* Display specified route of BGP table. */
9152 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9153 struct bgp_table
*rib
, const char *ip_str
,
9154 afi_t afi
, safi_t safi
,
9155 struct prefix_rd
*prd
, int prefix_check
,
9156 enum bgp_path_type pathtype
, bool use_json
)
9161 struct prefix match
;
9162 struct bgp_node
*rn
;
9163 struct bgp_node
*rm
;
9164 struct bgp_path_info
*pi
;
9165 struct bgp_table
*table
;
9166 json_object
*json
= NULL
;
9167 json_object
*json_paths
= NULL
;
9169 /* Check IP address argument. */
9170 ret
= str2prefix(ip_str
, &match
);
9172 vty_out(vty
, "address is malformed\n");
9176 match
.family
= afi2family(afi
);
9179 json
= json_object_new_object();
9180 json_paths
= json_object_new_array();
9183 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9184 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9185 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9187 table
= bgp_node_get_bgp_table_info(rn
);
9193 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9197 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9198 bgp_unlock_node(rm
);
9202 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9205 route_vty_out_detail_header(
9207 (struct prefix_rd
*)&rn
->p
,
9208 AFI_IP
, safi
, json
);
9213 if (pathtype
== BGP_PATH_SHOW_ALL
9214 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9215 && CHECK_FLAG(pi
->flags
,
9217 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9218 && (CHECK_FLAG(pi
->flags
,
9220 || CHECK_FLAG(pi
->flags
,
9221 BGP_PATH_SELECTED
))))
9222 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9227 bgp_unlock_node(rm
);
9229 } else if (safi
== SAFI_FLOWSPEC
) {
9230 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9231 &match
, prefix_check
,
9238 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9240 || rn
->p
.prefixlen
== match
.prefixlen
) {
9241 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9244 route_vty_out_detail_header(
9245 vty
, bgp
, rn
, NULL
, afi
,
9251 if (pathtype
== BGP_PATH_SHOW_ALL
9253 == BGP_PATH_SHOW_BESTPATH
9258 == BGP_PATH_SHOW_MULTIPATH
9264 BGP_PATH_SELECTED
))))
9265 route_vty_out_detail(
9266 vty
, bgp
, &rn
->p
, pi
,
9267 afi
, safi
, json_paths
);
9271 bgp_unlock_node(rn
);
9277 json_object_object_add(json
, "paths", json_paths
);
9279 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9280 json
, JSON_C_TO_STRING_PRETTY
));
9281 json_object_free(json
);
9284 vty_out(vty
, "%% Network not in table\n");
9292 /* Display specified route of Main RIB */
9293 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9294 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9295 int prefix_check
, enum bgp_path_type pathtype
,
9299 bgp
= bgp_get_default();
9302 vty_out(vty
, "No BGP process is configured\n");
9304 vty_out(vty
, "{}\n");
9309 /* labeled-unicast routes live in the unicast table */
9310 if (safi
== SAFI_LABELED_UNICAST
)
9311 safi
= SAFI_UNICAST
;
9313 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9314 afi
, safi
, prd
, prefix_check
, pathtype
,
9318 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9319 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9322 struct lcommunity
*lcom
;
9328 b
= buffer_new(1024);
9329 for (i
= 0; i
< argc
; i
++) {
9331 buffer_putc(b
, ' ');
9333 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9335 buffer_putstr(b
, argv
[i
]->arg
);
9339 buffer_putc(b
, '\0');
9341 str
= buffer_getstr(b
);
9344 lcom
= lcommunity_str2com(str
);
9345 XFREE(MTYPE_TMP
, str
);
9347 vty_out(vty
, "%% Large-community malformed\n");
9351 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9355 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9356 const char *lcom
, afi_t afi
, safi_t safi
,
9359 struct community_list
*list
;
9361 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9362 LARGE_COMMUNITY_LIST_MASTER
);
9364 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9369 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9373 DEFUN (show_ip_bgp_large_community_list
,
9374 show_ip_bgp_large_community_list_cmd
,
9375 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9379 BGP_INSTANCE_HELP_STR
9381 BGP_SAFI_WITH_LABEL_HELP_STR
9382 "Display routes matching the large-community-list\n"
9383 "large-community-list number\n"
9384 "large-community-list name\n"
9388 afi_t afi
= AFI_IP6
;
9389 safi_t safi
= SAFI_UNICAST
;
9392 if (argv_find(argv
, argc
, "ip", &idx
))
9394 if (argv_find(argv
, argc
, "view", &idx
)
9395 || argv_find(argv
, argc
, "vrf", &idx
))
9396 vrf
= argv
[++idx
]->arg
;
9397 if (argv_find(argv
, argc
, "ipv4", &idx
)
9398 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9399 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9400 if (argv_find(argv
, argc
, "unicast", &idx
)
9401 || argv_find(argv
, argc
, "multicast", &idx
))
9402 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9405 bool uj
= use_json(argc
, argv
);
9407 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9409 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9413 argv_find(argv
, argc
, "large-community-list", &idx
);
9414 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9417 DEFUN (show_ip_bgp_large_community
,
9418 show_ip_bgp_large_community_cmd
,
9419 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9423 BGP_INSTANCE_HELP_STR
9425 BGP_SAFI_WITH_LABEL_HELP_STR
9426 "Display routes matching the large-communities\n"
9427 "List of large-community numbers\n"
9431 afi_t afi
= AFI_IP6
;
9432 safi_t safi
= SAFI_UNICAST
;
9435 if (argv_find(argv
, argc
, "ip", &idx
))
9437 if (argv_find(argv
, argc
, "view", &idx
)
9438 || argv_find(argv
, argc
, "vrf", &idx
))
9439 vrf
= argv
[++idx
]->arg
;
9440 if (argv_find(argv
, argc
, "ipv4", &idx
)
9441 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9442 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9443 if (argv_find(argv
, argc
, "unicast", &idx
)
9444 || argv_find(argv
, argc
, "multicast", &idx
))
9445 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9448 bool uj
= use_json(argc
, argv
);
9450 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9452 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9456 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9457 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9459 return bgp_show(vty
, bgp
, afi
, safi
,
9460 bgp_show_type_lcommunity_all
, NULL
, uj
);
9463 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9467 /* BGP route print out function without JSON */
9470 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9471 <dampening <parameters>\
9476 |community-list <(1-500)|WORD> [exact-match]\
9477 |A.B.C.D/M longer-prefixes\
9478 |X:X::X:X/M longer-prefixes\
9483 BGP_INSTANCE_HELP_STR
9485 BGP_SAFI_WITH_LABEL_HELP_STR
9486 "Display detailed information about dampening\n"
9487 "Display detail of configured dampening parameters\n"
9488 "Display routes matching the route-map\n"
9489 "A route-map to match on\n"
9490 "Display routes conforming to the prefix-list\n"
9491 "Prefix-list name\n"
9492 "Display routes conforming to the filter-list\n"
9493 "Regular expression access list name\n"
9494 "BGP RIB advertisement statistics\n"
9495 "Display routes matching the community-list\n"
9496 "community-list number\n"
9497 "community-list name\n"
9498 "Exact match of the communities\n"
9500 "Display route and more specific routes\n"
9502 "Display route and more specific routes\n")
9504 afi_t afi
= AFI_IP6
;
9505 safi_t safi
= SAFI_UNICAST
;
9506 int exact_match
= 0;
9507 struct bgp
*bgp
= NULL
;
9510 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9515 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9516 if (argv_find(argv
, argc
, "parameters", &idx
))
9517 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9520 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9521 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9522 safi
, bgp_show_type_prefix_list
);
9524 if (argv_find(argv
, argc
, "filter-list", &idx
))
9525 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9526 safi
, bgp_show_type_filter_list
);
9528 if (argv_find(argv
, argc
, "statistics", &idx
))
9529 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9531 if (argv_find(argv
, argc
, "route-map", &idx
))
9532 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9533 safi
, bgp_show_type_route_map
);
9535 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9536 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9537 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9539 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9540 exact_match
, afi
, safi
);
9543 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9544 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9545 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9547 bgp_show_type_prefix_longer
);
9552 /* BGP route print out function with JSON */
9553 DEFUN (show_ip_bgp_json
,
9554 show_ip_bgp_json_cmd
,
9555 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9557 |dampening <flap-statistics|dampened-paths>\
9558 |community [AA:NN|local-AS|no-advertise|no-export\
9559 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9560 |accept-own|accept-own-nexthop|route-filter-v6\
9561 |route-filter-v4|route-filter-translated-v6\
9562 |route-filter-translated-v4] [exact-match]\
9567 BGP_INSTANCE_HELP_STR
9569 BGP_SAFI_WITH_LABEL_HELP_STR
9570 "Display only routes with non-natural netmasks\n"
9571 "Display detailed information about dampening\n"
9572 "Display flap statistics of routes\n"
9573 "Display paths suppressed due to dampening\n"
9574 "Display routes matching the communities\n"
9576 "Do not send outside local AS (well-known community)\n"
9577 "Do not advertise to any peer (well-known community)\n"
9578 "Do not export to next AS (well-known community)\n"
9579 "Graceful shutdown (well-known community)\n"
9580 "Do not export to any peer (well-known community)\n"
9581 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9582 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9583 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9584 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9585 "Should accept VPN route with local nexthop (well-known community)\n"
9586 "RT VPNv6 route filtering (well-known community)\n"
9587 "RT VPNv4 route filtering (well-known community)\n"
9588 "RT translated VPNv6 route filtering (well-known community)\n"
9589 "RT translated VPNv4 route filtering (well-known community)\n"
9590 "Exact match of the communities\n"
9593 afi_t afi
= AFI_IP6
;
9594 safi_t safi
= SAFI_UNICAST
;
9595 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9596 struct bgp
*bgp
= NULL
;
9598 int exact_match
= 0;
9599 bool uj
= use_json(argc
, argv
);
9604 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9609 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9610 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9613 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9614 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9615 return bgp_show(vty
, bgp
, afi
, safi
,
9616 bgp_show_type_dampend_paths
, NULL
, uj
);
9617 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9618 return bgp_show(vty
, bgp
, afi
, safi
,
9619 bgp_show_type_flap_statistics
, NULL
,
9623 if (argv_find(argv
, argc
, "community", &idx
)) {
9624 char *maybecomm
= NULL
;
9625 char *community
= NULL
;
9627 if (idx
+ 1 < argc
) {
9628 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
9629 maybecomm
= argv
[idx
+ 1]->arg
;
9631 maybecomm
= argv
[idx
+ 1]->text
;
9634 if (maybecomm
&& !strmatch(maybecomm
, "json")
9635 && !strmatch(maybecomm
, "exact-match"))
9636 community
= maybecomm
;
9638 if (argv_find(argv
, argc
, "exact-match", &idx
))
9642 return bgp_show_community(vty
, bgp
, community
,
9643 exact_match
, afi
, safi
, uj
);
9645 return (bgp_show(vty
, bgp
, afi
, safi
,
9646 bgp_show_type_community_all
, NULL
,
9650 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9653 DEFUN (show_ip_bgp_route
,
9654 show_ip_bgp_route_cmd
,
9655 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9656 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9660 BGP_INSTANCE_HELP_STR
9662 BGP_SAFI_WITH_LABEL_HELP_STR
9663 "Network in the BGP routing table to display\n"
9665 "Network in the BGP routing table to display\n"
9667 "Display only the bestpath\n"
9668 "Display only multipaths\n"
9671 int prefix_check
= 0;
9673 afi_t afi
= AFI_IP6
;
9674 safi_t safi
= SAFI_UNICAST
;
9675 char *prefix
= NULL
;
9676 struct bgp
*bgp
= NULL
;
9677 enum bgp_path_type path_type
;
9678 bool uj
= use_json(argc
, argv
);
9682 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9689 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9693 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9694 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9695 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9697 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9698 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9701 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9702 && afi
!= AFI_IP6
) {
9704 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9707 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9710 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9714 prefix
= argv
[idx
]->arg
;
9716 /* [<bestpath|multipath>] */
9717 if (argv_find(argv
, argc
, "bestpath", &idx
))
9718 path_type
= BGP_PATH_SHOW_BESTPATH
;
9719 else if (argv_find(argv
, argc
, "multipath", &idx
))
9720 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9722 path_type
= BGP_PATH_SHOW_ALL
;
9724 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9728 DEFUN (show_ip_bgp_regexp
,
9729 show_ip_bgp_regexp_cmd
,
9730 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9734 BGP_INSTANCE_HELP_STR
9736 BGP_SAFI_WITH_LABEL_HELP_STR
9737 "Display routes matching the AS path regular expression\n"
9738 "A regular-expression to match the BGP AS paths\n")
9740 afi_t afi
= AFI_IP6
;
9741 safi_t safi
= SAFI_UNICAST
;
9742 struct bgp
*bgp
= NULL
;
9745 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9750 // get index of regex
9751 argv_find(argv
, argc
, "regexp", &idx
);
9754 char *regstr
= argv_concat(argv
, argc
, idx
);
9755 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9756 bgp_show_type_regexp
);
9757 XFREE(MTYPE_TMP
, regstr
);
9761 DEFUN (show_ip_bgp_instance_all
,
9762 show_ip_bgp_instance_all_cmd
,
9763 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9767 BGP_INSTANCE_ALL_HELP_STR
9769 BGP_SAFI_WITH_LABEL_HELP_STR
9773 safi_t safi
= SAFI_UNICAST
;
9774 struct bgp
*bgp
= NULL
;
9776 bool uj
= use_json(argc
, argv
);
9781 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9786 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9790 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9791 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9796 regex
= bgp_regcomp(regstr
);
9798 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9802 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9803 bgp_regex_free(regex
);
9807 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9808 const char *prefix_list_str
, afi_t afi
,
9809 safi_t safi
, enum bgp_show_type type
)
9811 struct prefix_list
*plist
;
9813 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9814 if (plist
== NULL
) {
9815 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9820 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9823 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9824 const char *filter
, afi_t afi
, safi_t safi
,
9825 enum bgp_show_type type
)
9827 struct as_list
*as_list
;
9829 as_list
= as_list_lookup(filter
);
9830 if (as_list
== NULL
) {
9831 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9836 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9839 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9840 const char *rmap_str
, afi_t afi
, safi_t safi
,
9841 enum bgp_show_type type
)
9843 struct route_map
*rmap
;
9845 rmap
= route_map_lookup_by_name(rmap_str
);
9847 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9851 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9854 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9855 const char *comstr
, int exact
, afi_t afi
,
9856 safi_t safi
, bool use_json
)
9858 struct community
*com
;
9861 com
= community_str2com(comstr
);
9863 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9867 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9868 (exact
? bgp_show_type_community_exact
9869 : bgp_show_type_community
),
9871 community_free(&com
);
9876 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9877 const char *com
, int exact
, afi_t afi
,
9880 struct community_list
*list
;
9882 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
9884 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9888 return bgp_show(vty
, bgp
, afi
, safi
,
9889 (exact
? bgp_show_type_community_list_exact
9890 : bgp_show_type_community_list
),
9894 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9895 const char *prefix
, afi_t afi
, safi_t safi
,
9896 enum bgp_show_type type
)
9903 ret
= str2prefix(prefix
, p
);
9905 vty_out(vty
, "%% Malformed Prefix\n");
9909 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9914 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9915 const char *ip_str
, bool use_json
)
9921 /* Get peer sockunion. */
9922 ret
= str2sockunion(ip_str
, &su
);
9924 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9926 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9930 json_object
*json_no
= NULL
;
9931 json_no
= json_object_new_object();
9932 json_object_string_add(
9934 "malformedAddressOrName",
9936 vty_out(vty
, "%s\n",
9937 json_object_to_json_string_ext(
9939 JSON_C_TO_STRING_PRETTY
));
9940 json_object_free(json_no
);
9943 "%% Malformed address or name: %s\n",
9951 /* Peer structure lookup. */
9952 peer
= peer_lookup(bgp
, &su
);
9955 json_object
*json_no
= NULL
;
9956 json_no
= json_object_new_object();
9957 json_object_string_add(json_no
, "warning",
9958 "No such neighbor in this view/vrf");
9959 vty_out(vty
, "%s\n",
9960 json_object_to_json_string_ext(
9961 json_no
, JSON_C_TO_STRING_PRETTY
));
9962 json_object_free(json_no
);
9964 vty_out(vty
, "No such neighbor in this view/vrf\n");
9972 BGP_STATS_MAXBITLEN
= 0,
9976 BGP_STATS_UNAGGREGATEABLE
,
9977 BGP_STATS_MAX_AGGREGATEABLE
,
9978 BGP_STATS_AGGREGATES
,
9980 BGP_STATS_ASPATH_COUNT
,
9981 BGP_STATS_ASPATH_MAXHOPS
,
9982 BGP_STATS_ASPATH_TOTHOPS
,
9983 BGP_STATS_ASPATH_MAXSIZE
,
9984 BGP_STATS_ASPATH_TOTSIZE
,
9985 BGP_STATS_ASN_HIGHEST
,
9989 static const char *table_stats_strs
[] = {
9990 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9991 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9992 [BGP_STATS_RIB
] = "Total Advertisements",
9993 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9994 [BGP_STATS_MAX_AGGREGATEABLE
] =
9995 "Maximum aggregateable prefixes",
9996 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9997 [BGP_STATS_SPACE
] = "Address space advertised",
9998 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9999 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10000 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10001 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10002 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10003 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10004 [BGP_STATS_MAX
] = NULL
,
10007 struct bgp_table_stats
{
10008 struct bgp_table
*table
;
10009 unsigned long long counts
[BGP_STATS_MAX
];
10010 double total_space
;
10014 #define TALLY_SIGFIG 100000
10015 static unsigned long
10016 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10018 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10019 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10020 unsigned long ret
= newtot
/ count
;
10022 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10029 static int bgp_table_stats_walker(struct thread
*t
)
10031 struct bgp_node
*rn
;
10032 struct bgp_node
*top
;
10033 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10034 unsigned int space
= 0;
10036 if (!(top
= bgp_table_top(ts
->table
)))
10039 switch (top
->p
.family
) {
10041 space
= IPV4_MAX_BITLEN
;
10044 space
= IPV6_MAX_BITLEN
;
10048 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10050 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10051 struct bgp_path_info
*pi
;
10052 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10053 unsigned int pinum
= 0;
10058 if (!bgp_node_has_bgp_path_info_data(rn
))
10061 ts
->counts
[BGP_STATS_PREFIXES
]++;
10062 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10065 ts
->counts
[BGP_STATS_AVGPLEN
]
10066 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10067 ts
->counts
[BGP_STATS_AVGPLEN
],
10071 /* check if the prefix is included by any other announcements */
10072 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10073 prn
= bgp_node_parent_nolock(prn
);
10075 if (prn
== NULL
|| prn
== top
) {
10076 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10077 /* announced address space */
10080 pow(2.0, space
- rn
->p
.prefixlen
);
10081 } else if (bgp_node_has_bgp_path_info_data(prn
))
10082 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10084 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10086 ts
->counts
[BGP_STATS_RIB
]++;
10089 && (CHECK_FLAG(pi
->attr
->flag
,
10091 BGP_ATTR_ATOMIC_AGGREGATE
))))
10092 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10094 /* as-path stats */
10095 if (pi
->attr
&& pi
->attr
->aspath
) {
10096 unsigned int hops
=
10097 aspath_count_hops(pi
->attr
->aspath
);
10098 unsigned int size
=
10099 aspath_size(pi
->attr
->aspath
);
10100 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10102 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10104 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10105 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
10108 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10109 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
10112 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10113 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10115 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10116 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10117 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10119 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10120 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10121 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10124 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10125 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
10133 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10136 struct bgp_table_stats ts
;
10139 if (!bgp
->rib
[afi
][safi
]) {
10140 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10142 return CMD_WARNING
;
10145 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10147 /* labeled-unicast routes live in the unicast table */
10148 if (safi
== SAFI_LABELED_UNICAST
)
10149 safi
= SAFI_UNICAST
;
10151 memset(&ts
, 0, sizeof(ts
));
10152 ts
.table
= bgp
->rib
[afi
][safi
];
10153 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10155 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10156 if (!table_stats_strs
[i
])
10161 case BGP_STATS_ASPATH_AVGHOPS
:
10162 case BGP_STATS_ASPATH_AVGSIZE
:
10163 case BGP_STATS_AVGPLEN
:
10164 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10165 vty_out (vty
, "%12.2f",
10166 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10169 case BGP_STATS_ASPATH_TOTHOPS
:
10170 case BGP_STATS_ASPATH_TOTSIZE
:
10171 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10172 vty_out(vty
, "%12.2f",
10174 ? (float)ts
.counts
[i
]
10176 [BGP_STATS_ASPATH_COUNT
]
10179 case BGP_STATS_TOTPLEN
:
10180 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10181 vty_out(vty
, "%12.2f",
10183 ? (float)ts
.counts
[i
]
10185 [BGP_STATS_PREFIXES
]
10188 case BGP_STATS_SPACE
:
10189 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10190 vty_out(vty
, "%12g\n", ts
.total_space
);
10192 if (afi
== AFI_IP6
) {
10193 vty_out(vty
, "%30s: ", "/32 equivalent ");
10194 vty_out(vty
, "%12g\n",
10195 ts
.total_space
* pow(2.0, -128 + 32));
10196 vty_out(vty
, "%30s: ", "/48 equivalent ");
10197 vty_out(vty
, "%12g\n",
10198 ts
.total_space
* pow(2.0, -128 + 48));
10200 vty_out(vty
, "%30s: ", "% announced ");
10201 vty_out(vty
, "%12.2f\n",
10202 ts
.total_space
* 100. * pow(2.0, -32));
10203 vty_out(vty
, "%30s: ", "/8 equivalent ");
10204 vty_out(vty
, "%12.2f\n",
10205 ts
.total_space
* pow(2.0, -32 + 8));
10206 vty_out(vty
, "%30s: ", "/24 equivalent ");
10207 vty_out(vty
, "%12.2f\n",
10208 ts
.total_space
* pow(2.0, -32 + 24));
10212 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10213 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10216 vty_out(vty
, "\n");
10218 return CMD_SUCCESS
;
10230 PCOUNT_PFCNT
, /* the figure we display to users */
10234 static const char *pcount_strs
[] = {
10235 [PCOUNT_ADJ_IN
] = "Adj-in",
10236 [PCOUNT_DAMPED
] = "Damped",
10237 [PCOUNT_REMOVED
] = "Removed",
10238 [PCOUNT_HISTORY
] = "History",
10239 [PCOUNT_STALE
] = "Stale",
10240 [PCOUNT_VALID
] = "Valid",
10241 [PCOUNT_ALL
] = "All RIB",
10242 [PCOUNT_COUNTED
] = "PfxCt counted",
10243 [PCOUNT_PFCNT
] = "Useable",
10244 [PCOUNT_MAX
] = NULL
,
10247 struct peer_pcounts
{
10248 unsigned int count
[PCOUNT_MAX
];
10249 const struct peer
*peer
;
10250 const struct bgp_table
*table
;
10253 static int bgp_peer_count_walker(struct thread
*t
)
10255 struct bgp_node
*rn
;
10256 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10257 const struct peer
*peer
= pc
->peer
;
10259 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10260 struct bgp_adj_in
*ain
;
10261 struct bgp_path_info
*pi
;
10263 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10264 if (ain
->peer
== peer
)
10265 pc
->count
[PCOUNT_ADJ_IN
]++;
10267 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10269 if (pi
->peer
!= peer
)
10272 pc
->count
[PCOUNT_ALL
]++;
10274 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10275 pc
->count
[PCOUNT_DAMPED
]++;
10276 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10277 pc
->count
[PCOUNT_HISTORY
]++;
10278 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10279 pc
->count
[PCOUNT_REMOVED
]++;
10280 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10281 pc
->count
[PCOUNT_STALE
]++;
10282 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10283 pc
->count
[PCOUNT_VALID
]++;
10284 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10285 pc
->count
[PCOUNT_PFCNT
]++;
10287 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10288 pc
->count
[PCOUNT_COUNTED
]++;
10289 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10291 EC_LIB_DEVELOPMENT
,
10292 "Attempting to count but flags say it is unusable");
10294 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10296 EC_LIB_DEVELOPMENT
,
10297 "Not counted but flags say we should");
10304 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10305 safi_t safi
, bool use_json
)
10307 struct peer_pcounts pcounts
= {.peer
= peer
};
10309 json_object
*json
= NULL
;
10310 json_object
*json_loop
= NULL
;
10313 json
= json_object_new_object();
10314 json_loop
= json_object_new_object();
10317 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10318 || !peer
->bgp
->rib
[afi
][safi
]) {
10320 json_object_string_add(
10322 "No such neighbor or address family");
10323 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10324 json_object_free(json
);
10326 vty_out(vty
, "%% No such neighbor or address family\n");
10328 return CMD_WARNING
;
10331 memset(&pcounts
, 0, sizeof(pcounts
));
10332 pcounts
.peer
= peer
;
10333 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10335 /* in-place call via thread subsystem so as to record execution time
10336 * stats for the thread-walk (i.e. ensure this can't be blamed on
10337 * on just vty_read()).
10339 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10342 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10343 json_object_string_add(json
, "multiProtocol",
10344 afi_safi_print(afi
, safi
));
10345 json_object_int_add(json
, "pfxCounter",
10346 peer
->pcount
[afi
][safi
]);
10348 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10349 json_object_int_add(json_loop
, pcount_strs
[i
],
10352 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10354 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10355 json_object_string_add(json
, "pfxctDriftFor",
10357 json_object_string_add(
10358 json
, "recommended",
10359 "Please report this bug, with the above command output");
10361 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10362 json
, JSON_C_TO_STRING_PRETTY
));
10363 json_object_free(json
);
10367 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10368 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10369 peer
->hostname
, peer
->host
,
10370 afi_safi_print(afi
, safi
));
10372 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10373 afi_safi_print(afi
, safi
));
10376 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10377 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10379 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10380 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10383 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10384 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10386 "Please report this bug, with the above command output\n");
10390 return CMD_SUCCESS
;
10393 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10394 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10395 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10396 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10400 BGP_INSTANCE_HELP_STR
10403 "Detailed information on TCP and BGP neighbor connections\n"
10404 "Neighbor to display information about\n"
10405 "Neighbor to display information about\n"
10406 "Neighbor on BGP configured interface\n"
10407 "Display detailed prefix count information\n"
10410 afi_t afi
= AFI_IP6
;
10411 safi_t safi
= SAFI_UNICAST
;
10414 struct bgp
*bgp
= NULL
;
10415 bool uj
= use_json(argc
, argv
);
10420 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10423 return CMD_WARNING
;
10425 argv_find(argv
, argc
, "neighbors", &idx
);
10426 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10428 return CMD_WARNING
;
10430 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10433 #ifdef KEEP_OLD_VPN_COMMANDS
10434 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10435 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10436 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10441 "Display information about all VPNv4 NLRIs\n"
10442 "Detailed information on TCP and BGP neighbor connections\n"
10443 "Neighbor to display information about\n"
10444 "Neighbor to display information about\n"
10445 "Neighbor on BGP configured interface\n"
10446 "Display detailed prefix count information\n"
10451 bool uj
= use_json(argc
, argv
);
10453 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10455 return CMD_WARNING
;
10457 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10460 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10461 show_ip_bgp_vpn_all_route_prefix_cmd
,
10462 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10467 "Display information about all VPNv4 NLRIs\n"
10468 "Network in the BGP routing table to display\n"
10469 "Network in the BGP routing table to display\n"
10473 char *network
= NULL
;
10474 struct bgp
*bgp
= bgp_get_default();
10476 vty_out(vty
, "Can't find default instance\n");
10477 return CMD_WARNING
;
10480 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10481 network
= argv
[idx
]->arg
;
10482 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10483 network
= argv
[idx
]->arg
;
10485 vty_out(vty
, "Unable to figure out Network\n");
10486 return CMD_WARNING
;
10489 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10490 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10492 #endif /* KEEP_OLD_VPN_COMMANDS */
10494 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10495 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10496 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10502 "Display information about all EVPN NLRIs\n"
10503 "Network in the BGP routing table to display\n"
10504 "Network in the BGP routing table to display\n"
10508 char *network
= NULL
;
10510 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10511 network
= argv
[idx
]->arg
;
10512 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10513 network
= argv
[idx
]->arg
;
10515 vty_out(vty
, "Unable to figure out Network\n");
10516 return CMD_WARNING
;
10518 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10519 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10522 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10523 safi_t safi
, enum bgp_show_adj_route_type type
,
10524 const char *rmap_name
, bool use_json
,
10527 struct bgp_table
*table
;
10528 struct bgp_adj_in
*ain
;
10529 struct bgp_adj_out
*adj
;
10530 unsigned long output_count
;
10531 unsigned long filtered_count
;
10532 struct bgp_node
*rn
;
10538 struct update_subgroup
*subgrp
;
10539 json_object
*json_scode
= NULL
;
10540 json_object
*json_ocode
= NULL
;
10541 json_object
*json_ar
= NULL
;
10542 struct peer_af
*paf
;
10543 bool route_filtered
;
10546 json_scode
= json_object_new_object();
10547 json_ocode
= json_object_new_object();
10548 json_ar
= json_object_new_object();
10550 json_object_string_add(json_scode
, "suppressed", "s");
10551 json_object_string_add(json_scode
, "damped", "d");
10552 json_object_string_add(json_scode
, "history", "h");
10553 json_object_string_add(json_scode
, "valid", "*");
10554 json_object_string_add(json_scode
, "best", ">");
10555 json_object_string_add(json_scode
, "multipath", "=");
10556 json_object_string_add(json_scode
, "internal", "i");
10557 json_object_string_add(json_scode
, "ribFailure", "r");
10558 json_object_string_add(json_scode
, "stale", "S");
10559 json_object_string_add(json_scode
, "removed", "R");
10561 json_object_string_add(json_ocode
, "igp", "i");
10562 json_object_string_add(json_ocode
, "egp", "e");
10563 json_object_string_add(json_ocode
, "incomplete", "?");
10570 json_object_string_add(json
, "alert", "no BGP");
10571 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10572 json_object_free(json
);
10574 vty_out(vty
, "%% No bgp\n");
10578 table
= bgp
->rib
[afi
][safi
];
10580 output_count
= filtered_count
= 0;
10581 subgrp
= peer_subgroup(peer
, afi
, safi
);
10583 if (type
== bgp_show_adj_route_advertised
&& subgrp
10584 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10586 json_object_int_add(json
, "bgpTableVersion",
10588 json_object_string_add(json
, "bgpLocalRouterId",
10589 inet_ntoa(bgp
->router_id
));
10590 json_object_int_add(json
, "defaultLocPrf",
10591 bgp
->default_local_pref
);
10592 json_object_int_add(json
, "localAS", bgp
->as
);
10593 json_object_object_add(json
, "bgpStatusCodes",
10595 json_object_object_add(json
, "bgpOriginCodes",
10597 json_object_string_add(
10598 json
, "bgpOriginatingDefaultNetwork",
10599 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10601 vty_out(vty
, "BGP table version is %" PRIu64
10602 ", local router ID is %s, vrf id ",
10603 table
->version
, inet_ntoa(bgp
->router_id
));
10604 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10605 vty_out(vty
, "%s", VRFID_NONE_STR
);
10607 vty_out(vty
, "%u", bgp
->vrf_id
);
10608 vty_out(vty
, "\n");
10609 vty_out(vty
, "Default local pref %u, ",
10610 bgp
->default_local_pref
);
10611 vty_out(vty
, "local AS %u\n", bgp
->as
);
10612 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10613 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10614 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10616 vty_out(vty
, "Originating default network %s\n\n",
10617 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10622 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10623 if (type
== bgp_show_adj_route_received
10624 || type
== bgp_show_adj_route_filtered
) {
10625 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10626 if (ain
->peer
!= peer
|| !ain
->attr
)
10631 json_object_int_add(
10632 json
, "bgpTableVersion",
10634 json_object_string_add(
10636 "bgpLocalRouterId",
10639 json_object_int_add(json
,
10641 bgp
->default_local_pref
);
10642 json_object_int_add(json
,
10643 "localAS", bgp
->as
);
10644 json_object_object_add(
10645 json
, "bgpStatusCodes",
10647 json_object_object_add(
10648 json
, "bgpOriginCodes",
10652 "BGP table version is 0, local router ID is %s, vrf id ",
10655 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10661 vty_out(vty
, "\n");
10663 "Default local pref %u, ",
10664 bgp
->default_local_pref
);
10665 vty_out(vty
, "local AS %u\n",
10668 BGP_SHOW_SCODE_HEADER
);
10670 BGP_SHOW_NCODE_HEADER
);
10672 BGP_SHOW_OCODE_HEADER
);
10678 vty_out(vty
, BGP_SHOW_HEADER
);
10682 bgp_attr_dup(&attr
, ain
->attr
);
10683 route_filtered
= false;
10685 /* Filter prefix using distribute list,
10686 * filter list or prefix list
10688 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10689 safi
)) == FILTER_DENY
)
10690 route_filtered
= true;
10692 /* Filter prefix using route-map */
10693 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10694 afi
, safi
, rmap_name
);
10696 if (type
== bgp_show_adj_route_filtered
&&
10697 !route_filtered
&& ret
!= RMAP_DENY
) {
10698 bgp_attr_undup(&attr
, ain
->attr
);
10702 if (type
== bgp_show_adj_route_received
&&
10703 (route_filtered
|| ret
== RMAP_DENY
))
10706 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10707 use_json
, json_ar
);
10708 bgp_attr_undup(&attr
, ain
->attr
);
10711 } else if (type
== bgp_show_adj_route_advertised
) {
10712 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
10713 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10714 if (paf
->peer
!= peer
|| !adj
->attr
)
10719 json_object_int_add(
10723 json_object_string_add(
10725 "bgpLocalRouterId",
10728 json_object_int_add(
10729 json
, "defaultLocPrf",
10730 bgp
->default_local_pref
10732 json_object_int_add(
10735 json_object_object_add(
10739 json_object_object_add(
10745 "BGP table version is %" PRIu64
10746 ", local router ID is %s, vrf id ",
10759 vty_out(vty
, "\n");
10761 "Default local pref %u, ",
10762 bgp
->default_local_pref
10768 BGP_SHOW_SCODE_HEADER
);
10770 BGP_SHOW_NCODE_HEADER
);
10772 BGP_SHOW_OCODE_HEADER
);
10783 bgp_attr_dup(&attr
, adj
->attr
);
10784 ret
= bgp_output_modifier(
10785 peer
, &rn
->p
, &attr
, afi
, safi
,
10788 if (ret
!= RMAP_DENY
) {
10789 route_vty_out_tmp(vty
, &rn
->p
,
10798 bgp_attr_undup(&attr
, adj
->attr
);
10804 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10805 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10806 json_object_int_add(json
, "filteredPrefixCounter",
10809 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10810 json
, JSON_C_TO_STRING_PRETTY
));
10811 json_object_free(json
);
10812 } else if (output_count
> 0) {
10813 if (filtered_count
> 0)
10815 "\nTotal number of prefixes %ld (%ld filtered)\n",
10816 output_count
, filtered_count
);
10818 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10823 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10824 safi_t safi
, enum bgp_show_adj_route_type type
,
10825 const char *rmap_name
, bool use_json
)
10827 json_object
*json
= NULL
;
10830 json
= json_object_new_object();
10832 /* labeled-unicast routes live in the unicast table */
10833 if (safi
== SAFI_LABELED_UNICAST
)
10834 safi
= SAFI_UNICAST
;
10836 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10838 json_object_string_add(
10840 "No such neighbor or address family");
10841 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10842 json_object_free(json
);
10844 vty_out(vty
, "%% No such neighbor or address family\n");
10846 return CMD_WARNING
;
10849 if ((type
== bgp_show_adj_route_received
10850 || type
== bgp_show_adj_route_filtered
)
10851 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10852 PEER_FLAG_SOFT_RECONFIG
)) {
10854 json_object_string_add(
10856 "Inbound soft reconfiguration not enabled");
10857 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10858 json_object_free(json
);
10861 "%% Inbound soft reconfiguration not enabled\n");
10863 return CMD_WARNING
;
10866 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10868 return CMD_SUCCESS
;
10871 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10872 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10873 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10874 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10878 BGP_INSTANCE_HELP_STR
10880 BGP_SAFI_WITH_LABEL_HELP_STR
10881 "Detailed information on TCP and BGP neighbor connections\n"
10882 "Neighbor to display information about\n"
10883 "Neighbor to display information about\n"
10884 "Neighbor on BGP configured interface\n"
10885 "Display the routes advertised to a BGP neighbor\n"
10886 "Display the received routes from neighbor\n"
10887 "Display the filtered routes received from neighbor\n"
10888 "Route-map to modify the attributes\n"
10889 "Name of the route map\n"
10892 afi_t afi
= AFI_IP6
;
10893 safi_t safi
= SAFI_UNICAST
;
10894 char *rmap_name
= NULL
;
10895 char *peerstr
= NULL
;
10896 struct bgp
*bgp
= NULL
;
10898 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10900 bool uj
= use_json(argc
, argv
);
10905 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10908 return CMD_WARNING
;
10910 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10911 argv_find(argv
, argc
, "neighbors", &idx
);
10912 peerstr
= argv
[++idx
]->arg
;
10914 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10916 return CMD_WARNING
;
10918 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10919 type
= bgp_show_adj_route_advertised
;
10920 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10921 type
= bgp_show_adj_route_received
;
10922 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10923 type
= bgp_show_adj_route_filtered
;
10925 if (argv_find(argv
, argc
, "route-map", &idx
))
10926 rmap_name
= argv
[++idx
]->arg
;
10928 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10931 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10932 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10933 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10939 "Address Family modifier\n"
10940 "Detailed information on TCP and BGP neighbor connections\n"
10941 "Neighbor to display information about\n"
10942 "Neighbor to display information about\n"
10943 "Neighbor on BGP configured interface\n"
10944 "Display information received from a BGP neighbor\n"
10945 "Display the prefixlist filter\n"
10948 afi_t afi
= AFI_IP6
;
10949 safi_t safi
= SAFI_UNICAST
;
10950 char *peerstr
= NULL
;
10953 union sockunion su
;
10959 /* show [ip] bgp */
10960 if (argv_find(argv
, argc
, "ip", &idx
))
10962 /* [<ipv4|ipv6> [unicast]] */
10963 if (argv_find(argv
, argc
, "ipv4", &idx
))
10965 if (argv_find(argv
, argc
, "ipv6", &idx
))
10967 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10968 argv_find(argv
, argc
, "neighbors", &idx
);
10969 peerstr
= argv
[++idx
]->arg
;
10971 bool uj
= use_json(argc
, argv
);
10973 ret
= str2sockunion(peerstr
, &su
);
10975 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10978 vty_out(vty
, "{}\n");
10981 "%% Malformed address or name: %s\n",
10983 return CMD_WARNING
;
10986 peer
= peer_lookup(NULL
, &su
);
10989 vty_out(vty
, "{}\n");
10991 vty_out(vty
, "No peer\n");
10992 return CMD_WARNING
;
10996 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10997 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11000 vty_out(vty
, "Address Family: %s\n",
11001 afi_safi_print(afi
, safi
));
11002 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11005 vty_out(vty
, "{}\n");
11007 vty_out(vty
, "No functional output\n");
11010 return CMD_SUCCESS
;
11013 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11014 afi_t afi
, safi_t safi
,
11015 enum bgp_show_type type
, bool use_json
)
11017 /* labeled-unicast routes live in the unicast table */
11018 if (safi
== SAFI_LABELED_UNICAST
)
11019 safi
= SAFI_UNICAST
;
11021 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11023 json_object
*json_no
= NULL
;
11024 json_no
= json_object_new_object();
11025 json_object_string_add(
11026 json_no
, "warning",
11027 "No such neighbor or address family");
11028 vty_out(vty
, "%s\n",
11029 json_object_to_json_string(json_no
));
11030 json_object_free(json_no
);
11032 vty_out(vty
, "%% No such neighbor or address family\n");
11033 return CMD_WARNING
;
11036 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11039 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11040 show_ip_bgp_flowspec_routes_detailed_cmd
,
11041 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11045 BGP_INSTANCE_HELP_STR
11048 "Detailed information on flowspec entries\n"
11051 afi_t afi
= AFI_IP
;
11052 safi_t safi
= SAFI_UNICAST
;
11053 struct bgp
*bgp
= NULL
;
11055 bool uj
= use_json(argc
, argv
);
11060 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11063 return CMD_WARNING
;
11065 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11068 DEFUN (show_ip_bgp_neighbor_routes
,
11069 show_ip_bgp_neighbor_routes_cmd
,
11070 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11071 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11075 BGP_INSTANCE_HELP_STR
11077 BGP_SAFI_WITH_LABEL_HELP_STR
11078 "Detailed information on TCP and BGP neighbor connections\n"
11079 "Neighbor to display information about\n"
11080 "Neighbor to display information about\n"
11081 "Neighbor on BGP configured interface\n"
11082 "Display flap statistics of the routes learned from neighbor\n"
11083 "Display the dampened routes received from neighbor\n"
11084 "Display routes learned from neighbor\n"
11087 char *peerstr
= NULL
;
11088 struct bgp
*bgp
= NULL
;
11089 afi_t afi
= AFI_IP6
;
11090 safi_t safi
= SAFI_UNICAST
;
11092 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11094 bool uj
= use_json(argc
, argv
);
11099 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11102 return CMD_WARNING
;
11104 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11105 argv_find(argv
, argc
, "neighbors", &idx
);
11106 peerstr
= argv
[++idx
]->arg
;
11108 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11110 return CMD_WARNING
;
11112 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11113 sh_type
= bgp_show_type_flap_neighbor
;
11114 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11115 sh_type
= bgp_show_type_damp_neighbor
;
11116 else if (argv_find(argv
, argc
, "routes", &idx
))
11117 sh_type
= bgp_show_type_neighbor
;
11119 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11122 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11124 struct bgp_distance
{
11125 /* Distance value for the IP source prefix. */
11128 /* Name of the access-list to be matched. */
11132 DEFUN (show_bgp_afi_vpn_rd_route
,
11133 show_bgp_afi_vpn_rd_route_cmd
,
11134 "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]",
11138 "Address Family modifier\n"
11139 "Display information for a route distinguisher\n"
11140 "Route Distinguisher\n"
11141 "Network in the BGP routing table to display\n"
11142 "Network in the BGP routing table to display\n"
11146 struct prefix_rd prd
;
11147 afi_t afi
= AFI_MAX
;
11150 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11151 vty_out(vty
, "%% Malformed Address Family\n");
11152 return CMD_WARNING
;
11155 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11157 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11158 return CMD_WARNING
;
11161 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11162 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11165 static struct bgp_distance
*bgp_distance_new(void)
11167 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11170 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11172 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11175 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11176 const char *ip_str
, const char *access_list_str
)
11183 struct bgp_node
*rn
;
11184 struct bgp_distance
*bdistance
;
11186 afi
= bgp_node_afi(vty
);
11187 safi
= bgp_node_safi(vty
);
11189 ret
= str2prefix(ip_str
, &p
);
11191 vty_out(vty
, "Malformed prefix\n");
11192 return CMD_WARNING_CONFIG_FAILED
;
11195 distance
= atoi(distance_str
);
11197 /* Get BGP distance node. */
11198 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11199 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11201 bgp_unlock_node(rn
);
11203 bdistance
= bgp_distance_new();
11204 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11207 /* Set distance value. */
11208 bdistance
->distance
= distance
;
11210 /* Reset access-list configuration. */
11211 if (bdistance
->access_list
) {
11212 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11213 bdistance
->access_list
= NULL
;
11215 if (access_list_str
)
11216 bdistance
->access_list
=
11217 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11219 return CMD_SUCCESS
;
11222 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11223 const char *ip_str
, const char *access_list_str
)
11230 struct bgp_node
*rn
;
11231 struct bgp_distance
*bdistance
;
11233 afi
= bgp_node_afi(vty
);
11234 safi
= bgp_node_safi(vty
);
11236 ret
= str2prefix(ip_str
, &p
);
11238 vty_out(vty
, "Malformed prefix\n");
11239 return CMD_WARNING_CONFIG_FAILED
;
11242 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11243 (struct prefix
*)&p
);
11245 vty_out(vty
, "Can't find specified prefix\n");
11246 return CMD_WARNING_CONFIG_FAILED
;
11249 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11250 distance
= atoi(distance_str
);
11252 if (bdistance
->distance
!= distance
) {
11253 vty_out(vty
, "Distance does not match configured\n");
11254 return CMD_WARNING_CONFIG_FAILED
;
11257 if (bdistance
->access_list
)
11258 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11259 bgp_distance_free(bdistance
);
11261 bgp_node_set_bgp_path_info(rn
, NULL
);
11262 bgp_unlock_node(rn
);
11263 bgp_unlock_node(rn
);
11265 return CMD_SUCCESS
;
11268 /* Apply BGP information to distance method. */
11269 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11270 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11272 struct bgp_node
*rn
;
11275 struct bgp_distance
*bdistance
;
11276 struct access_list
*alist
;
11277 struct bgp_static
*bgp_static
;
11282 peer
= pinfo
->peer
;
11284 /* Check source address. */
11285 sockunion2hostprefix(&peer
->su
, &q
);
11286 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11288 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11289 bgp_unlock_node(rn
);
11291 if (bdistance
->access_list
) {
11292 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11294 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11295 return bdistance
->distance
;
11297 return bdistance
->distance
;
11300 /* Backdoor check. */
11301 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11303 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11304 bgp_unlock_node(rn
);
11306 if (bgp_static
->backdoor
) {
11307 if (bgp
->distance_local
[afi
][safi
])
11308 return bgp
->distance_local
[afi
][safi
];
11310 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11314 if (peer
->sort
== BGP_PEER_EBGP
) {
11315 if (bgp
->distance_ebgp
[afi
][safi
])
11316 return bgp
->distance_ebgp
[afi
][safi
];
11317 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11319 if (bgp
->distance_ibgp
[afi
][safi
])
11320 return bgp
->distance_ibgp
[afi
][safi
];
11321 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11325 DEFUN (bgp_distance
,
11327 "distance bgp (1-255) (1-255) (1-255)",
11328 "Define an administrative distance\n"
11330 "Distance for routes external to the AS\n"
11331 "Distance for routes internal to the AS\n"
11332 "Distance for local routes\n")
11334 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11335 int idx_number
= 2;
11336 int idx_number_2
= 3;
11337 int idx_number_3
= 4;
11341 afi
= bgp_node_afi(vty
);
11342 safi
= bgp_node_safi(vty
);
11344 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11345 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11346 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11347 return CMD_SUCCESS
;
11350 DEFUN (no_bgp_distance
,
11351 no_bgp_distance_cmd
,
11352 "no distance bgp [(1-255) (1-255) (1-255)]",
11354 "Define an administrative distance\n"
11356 "Distance for routes external to the AS\n"
11357 "Distance for routes internal to the AS\n"
11358 "Distance for local routes\n")
11360 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11364 afi
= bgp_node_afi(vty
);
11365 safi
= bgp_node_safi(vty
);
11367 bgp
->distance_ebgp
[afi
][safi
] = 0;
11368 bgp
->distance_ibgp
[afi
][safi
] = 0;
11369 bgp
->distance_local
[afi
][safi
] = 0;
11370 return CMD_SUCCESS
;
11374 DEFUN (bgp_distance_source
,
11375 bgp_distance_source_cmd
,
11376 "distance (1-255) A.B.C.D/M",
11377 "Define an administrative distance\n"
11378 "Administrative distance\n"
11379 "IP source prefix\n")
11381 int idx_number
= 1;
11382 int idx_ipv4_prefixlen
= 2;
11383 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11384 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11385 return CMD_SUCCESS
;
11388 DEFUN (no_bgp_distance_source
,
11389 no_bgp_distance_source_cmd
,
11390 "no distance (1-255) A.B.C.D/M",
11392 "Define an administrative distance\n"
11393 "Administrative distance\n"
11394 "IP source prefix\n")
11396 int idx_number
= 2;
11397 int idx_ipv4_prefixlen
= 3;
11398 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11399 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11400 return CMD_SUCCESS
;
11403 DEFUN (bgp_distance_source_access_list
,
11404 bgp_distance_source_access_list_cmd
,
11405 "distance (1-255) A.B.C.D/M WORD",
11406 "Define an administrative distance\n"
11407 "Administrative distance\n"
11408 "IP source prefix\n"
11409 "Access list name\n")
11411 int idx_number
= 1;
11412 int idx_ipv4_prefixlen
= 2;
11414 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11415 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11416 return CMD_SUCCESS
;
11419 DEFUN (no_bgp_distance_source_access_list
,
11420 no_bgp_distance_source_access_list_cmd
,
11421 "no distance (1-255) A.B.C.D/M WORD",
11423 "Define an administrative distance\n"
11424 "Administrative distance\n"
11425 "IP source prefix\n"
11426 "Access list name\n")
11428 int idx_number
= 2;
11429 int idx_ipv4_prefixlen
= 3;
11431 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11432 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11433 return CMD_SUCCESS
;
11436 DEFUN (ipv6_bgp_distance_source
,
11437 ipv6_bgp_distance_source_cmd
,
11438 "distance (1-255) X:X::X:X/M",
11439 "Define an administrative distance\n"
11440 "Administrative distance\n"
11441 "IP source prefix\n")
11443 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11444 return CMD_SUCCESS
;
11447 DEFUN (no_ipv6_bgp_distance_source
,
11448 no_ipv6_bgp_distance_source_cmd
,
11449 "no distance (1-255) X:X::X:X/M",
11451 "Define an administrative distance\n"
11452 "Administrative distance\n"
11453 "IP source prefix\n")
11455 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11456 return CMD_SUCCESS
;
11459 DEFUN (ipv6_bgp_distance_source_access_list
,
11460 ipv6_bgp_distance_source_access_list_cmd
,
11461 "distance (1-255) X:X::X:X/M WORD",
11462 "Define an administrative distance\n"
11463 "Administrative distance\n"
11464 "IP source prefix\n"
11465 "Access list name\n")
11467 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11468 return CMD_SUCCESS
;
11471 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11472 no_ipv6_bgp_distance_source_access_list_cmd
,
11473 "no distance (1-255) X:X::X:X/M WORD",
11475 "Define an administrative distance\n"
11476 "Administrative distance\n"
11477 "IP source prefix\n"
11478 "Access list name\n")
11480 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11481 return CMD_SUCCESS
;
11484 DEFUN (bgp_damp_set
,
11486 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11487 "BGP Specific commands\n"
11488 "Enable route-flap dampening\n"
11489 "Half-life time for the penalty\n"
11490 "Value to start reusing a route\n"
11491 "Value to start suppressing a route\n"
11492 "Maximum duration to suppress a stable route\n")
11494 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11495 int idx_half_life
= 2;
11497 int idx_suppress
= 4;
11498 int idx_max_suppress
= 5;
11499 int half
= DEFAULT_HALF_LIFE
* 60;
11500 int reuse
= DEFAULT_REUSE
;
11501 int suppress
= DEFAULT_SUPPRESS
;
11502 int max
= 4 * half
;
11505 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11506 reuse
= atoi(argv
[idx_reuse
]->arg
);
11507 suppress
= atoi(argv
[idx_suppress
]->arg
);
11508 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11509 } else if (argc
== 3) {
11510 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11514 if (suppress
< reuse
) {
11516 "Suppress value cannot be less than reuse value \n");
11520 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11521 reuse
, suppress
, max
);
11524 DEFUN (bgp_damp_unset
,
11525 bgp_damp_unset_cmd
,
11526 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11528 "BGP Specific commands\n"
11529 "Enable route-flap dampening\n"
11530 "Half-life time for the penalty\n"
11531 "Value to start reusing a route\n"
11532 "Value to start suppressing a route\n"
11533 "Maximum duration to suppress a stable route\n")
11535 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11536 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11539 /* Display specified route of BGP table. */
11540 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11541 const char *ip_str
, afi_t afi
, safi_t safi
,
11542 struct prefix_rd
*prd
, int prefix_check
)
11545 struct prefix match
;
11546 struct bgp_node
*rn
;
11547 struct bgp_node
*rm
;
11548 struct bgp_path_info
*pi
;
11549 struct bgp_path_info
*pi_temp
;
11551 struct bgp_table
*table
;
11553 /* BGP structure lookup. */
11555 bgp
= bgp_lookup_by_name(view_name
);
11557 vty_out(vty
, "%% Can't find BGP instance %s\n",
11559 return CMD_WARNING
;
11562 bgp
= bgp_get_default();
11564 vty_out(vty
, "%% No BGP process is configured\n");
11565 return CMD_WARNING
;
11569 /* Check IP address argument. */
11570 ret
= str2prefix(ip_str
, &match
);
11572 vty_out(vty
, "%% address is malformed\n");
11573 return CMD_WARNING
;
11576 match
.family
= afi2family(afi
);
11578 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11579 || (safi
== SAFI_EVPN
)) {
11580 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11581 rn
= bgp_route_next(rn
)) {
11582 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11584 table
= bgp_node_get_bgp_table_info(rn
);
11587 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11591 || rm
->p
.prefixlen
== match
.prefixlen
) {
11592 pi
= bgp_node_get_bgp_path_info(rm
);
11594 if (pi
->extra
&& pi
->extra
->damp_info
) {
11595 pi_temp
= pi
->next
;
11596 bgp_damp_info_free(
11597 pi
->extra
->damp_info
,
11605 bgp_unlock_node(rm
);
11608 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11611 || rn
->p
.prefixlen
== match
.prefixlen
) {
11612 pi
= bgp_node_get_bgp_path_info(rn
);
11614 if (pi
->extra
&& pi
->extra
->damp_info
) {
11615 pi_temp
= pi
->next
;
11616 bgp_damp_info_free(
11617 pi
->extra
->damp_info
,
11625 bgp_unlock_node(rn
);
11629 return CMD_SUCCESS
;
11632 DEFUN (clear_ip_bgp_dampening
,
11633 clear_ip_bgp_dampening_cmd
,
11634 "clear ip bgp dampening",
11638 "Clear route flap dampening information\n")
11640 bgp_damp_info_clean();
11641 return CMD_SUCCESS
;
11644 DEFUN (clear_ip_bgp_dampening_prefix
,
11645 clear_ip_bgp_dampening_prefix_cmd
,
11646 "clear ip bgp dampening A.B.C.D/M",
11650 "Clear route flap dampening information\n"
11653 int idx_ipv4_prefixlen
= 4;
11654 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11655 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11658 DEFUN (clear_ip_bgp_dampening_address
,
11659 clear_ip_bgp_dampening_address_cmd
,
11660 "clear ip bgp dampening A.B.C.D",
11664 "Clear route flap dampening information\n"
11665 "Network to clear damping information\n")
11668 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11669 SAFI_UNICAST
, NULL
, 0);
11672 DEFUN (clear_ip_bgp_dampening_address_mask
,
11673 clear_ip_bgp_dampening_address_mask_cmd
,
11674 "clear ip bgp dampening A.B.C.D A.B.C.D",
11678 "Clear route flap dampening information\n"
11679 "Network to clear damping information\n"
11683 int idx_ipv4_2
= 5;
11685 char prefix_str
[BUFSIZ
];
11687 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11690 vty_out(vty
, "%% Inconsistent address and mask\n");
11691 return CMD_WARNING
;
11694 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11698 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
11700 struct vty
*vty
= arg
;
11701 struct peer
*peer
= bucket
->data
;
11702 char buf
[SU_ADDRSTRLEN
];
11704 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
11705 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
11708 DEFUN (show_bgp_peerhash
,
11709 show_bgp_peerhash_cmd
,
11710 "show bgp peerhash",
11713 "Display information about the BGP peerhash\n")
11715 struct list
*instances
= bm
->bgp
;
11716 struct listnode
*node
;
11719 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
11720 vty_out(vty
, "BGP: %s\n", bgp
->name
);
11721 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
11725 return CMD_SUCCESS
;
11728 /* also used for encap safi */
11729 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11730 afi_t afi
, safi_t safi
)
11732 struct bgp_node
*prn
;
11733 struct bgp_node
*rn
;
11734 struct bgp_table
*table
;
11736 struct prefix_rd
*prd
;
11737 struct bgp_static
*bgp_static
;
11738 mpls_label_t label
;
11739 char buf
[SU_ADDRSTRLEN
];
11740 char rdbuf
[RD_ADDRSTRLEN
];
11742 /* Network configuration. */
11743 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11744 prn
= bgp_route_next(prn
)) {
11745 table
= bgp_node_get_bgp_table_info(prn
);
11749 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11750 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11751 if (bgp_static
== NULL
)
11755 prd
= (struct prefix_rd
*)&prn
->p
;
11757 /* "network" configuration display. */
11758 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11759 label
= decode_label(&bgp_static
->label
);
11761 vty_out(vty
, " network %s/%d rd %s",
11762 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11764 p
->prefixlen
, rdbuf
);
11765 if (safi
== SAFI_MPLS_VPN
)
11766 vty_out(vty
, " label %u", label
);
11768 if (bgp_static
->rmap
.name
)
11769 vty_out(vty
, " route-map %s",
11770 bgp_static
->rmap
.name
);
11772 if (bgp_static
->backdoor
)
11773 vty_out(vty
, " backdoor");
11775 vty_out(vty
, "\n");
11780 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11781 afi_t afi
, safi_t safi
)
11783 struct bgp_node
*prn
;
11784 struct bgp_node
*rn
;
11785 struct bgp_table
*table
;
11787 struct prefix_rd
*prd
;
11788 struct bgp_static
*bgp_static
;
11789 char buf
[PREFIX_STRLEN
* 2];
11790 char buf2
[SU_ADDRSTRLEN
];
11791 char rdbuf
[RD_ADDRSTRLEN
];
11793 /* Network configuration. */
11794 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11795 prn
= bgp_route_next(prn
)) {
11796 table
= bgp_node_get_bgp_table_info(prn
);
11800 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11801 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11802 if (bgp_static
== NULL
)
11805 char *macrouter
= NULL
;
11808 if (bgp_static
->router_mac
)
11809 macrouter
= prefix_mac2str(
11810 bgp_static
->router_mac
, NULL
, 0);
11811 if (bgp_static
->eth_s_id
)
11812 esi
= esi2str(bgp_static
->eth_s_id
);
11814 prd
= (struct prefix_rd
*)&prn
->p
;
11816 /* "network" configuration display. */
11817 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11818 if (p
->u
.prefix_evpn
.route_type
== 5) {
11819 char local_buf
[PREFIX_STRLEN
];
11820 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11821 struct prefix_evpn
*)p
)
11825 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11826 local_buf
, PREFIX_STRLEN
);
11827 sprintf(buf
, "%s/%u", local_buf
,
11828 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11830 prefix2str(p
, buf
, sizeof(buf
));
11833 if (bgp_static
->gatewayIp
.family
== AF_INET
11834 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11835 inet_ntop(bgp_static
->gatewayIp
.family
,
11836 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11839 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11841 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11842 decode_label(&bgp_static
->label
), esi
, buf2
,
11846 XFREE(MTYPE_TMP
, macrouter
);
11848 XFREE(MTYPE_TMP
, esi
);
11853 /* Configuration of static route announcement and aggregate
11855 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11858 struct bgp_node
*rn
;
11860 struct bgp_static
*bgp_static
;
11861 struct bgp_aggregate
*bgp_aggregate
;
11862 char buf
[SU_ADDRSTRLEN
];
11864 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11865 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11869 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11870 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11874 /* Network configuration. */
11875 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11876 rn
= bgp_route_next(rn
)) {
11877 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11878 if (bgp_static
== NULL
)
11883 /* "network" configuration display. */
11884 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11885 uint32_t destination
;
11886 struct in_addr netmask
;
11888 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11889 masklen2ip(p
->prefixlen
, &netmask
);
11890 vty_out(vty
, " network %s",
11891 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11894 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11895 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11896 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11897 || p
->u
.prefix4
.s_addr
== 0) {
11898 /* Natural mask is not display. */
11900 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11902 vty_out(vty
, " network %s/%d",
11903 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11908 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11909 vty_out(vty
, " label-index %u",
11910 bgp_static
->label_index
);
11912 if (bgp_static
->rmap
.name
)
11913 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11915 if (bgp_static
->backdoor
)
11916 vty_out(vty
, " backdoor");
11918 vty_out(vty
, "\n");
11921 /* Aggregate-address configuration. */
11922 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11923 rn
= bgp_route_next(rn
)) {
11924 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
11925 if (bgp_aggregate
== NULL
)
11930 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11931 struct in_addr netmask
;
11933 masklen2ip(p
->prefixlen
, &netmask
);
11934 vty_out(vty
, " aggregate-address %s %s",
11935 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11937 inet_ntoa(netmask
));
11939 vty_out(vty
, " aggregate-address %s/%d",
11940 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11945 if (bgp_aggregate
->as_set
)
11946 vty_out(vty
, " as-set");
11948 if (bgp_aggregate
->summary_only
)
11949 vty_out(vty
, " summary-only");
11951 vty_out(vty
, "\n");
11955 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11958 struct bgp_node
*rn
;
11959 struct bgp_distance
*bdistance
;
11961 /* Distance configuration. */
11962 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11963 && bgp
->distance_local
[afi
][safi
]
11964 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11965 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11966 || bgp
->distance_local
[afi
][safi
]
11967 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11968 vty_out(vty
, " distance bgp %d %d %d\n",
11969 bgp
->distance_ebgp
[afi
][safi
],
11970 bgp
->distance_ibgp
[afi
][safi
],
11971 bgp
->distance_local
[afi
][safi
]);
11974 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11975 rn
= bgp_route_next(rn
)) {
11976 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11977 if (bdistance
!= NULL
) {
11978 char buf
[PREFIX_STRLEN
];
11980 vty_out(vty
, " distance %d %s %s\n",
11981 bdistance
->distance
,
11982 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11983 bdistance
->access_list
? bdistance
->access_list
11989 /* Allocate routing table structure and install commands. */
11990 void bgp_route_init(void)
11995 /* Init BGP distance table. */
11996 FOREACH_AFI_SAFI (afi
, safi
)
11997 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11999 /* IPv4 BGP commands. */
12000 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12001 install_element(BGP_NODE
, &bgp_network_cmd
);
12002 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12004 install_element(BGP_NODE
, &aggregate_address_cmd
);
12005 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12006 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12007 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12009 /* IPv4 unicast configuration. */
12010 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12011 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12012 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12014 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12015 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12016 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12017 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12019 /* IPv4 multicast configuration. */
12020 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12021 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12022 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12023 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12024 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12025 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12026 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12028 /* IPv4 labeled-unicast configuration. */
12029 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12030 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12031 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12032 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12033 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12035 install_element(VIEW_NODE
,
12036 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12037 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12038 install_element(VIEW_NODE
,
12039 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12040 #ifdef KEEP_OLD_VPN_COMMANDS
12041 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12042 #endif /* KEEP_OLD_VPN_COMMANDS */
12043 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12044 install_element(VIEW_NODE
,
12045 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
12047 /* BGP dampening clear commands */
12048 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12049 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12051 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12052 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12055 install_element(ENABLE_NODE
,
12056 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12057 #ifdef KEEP_OLD_VPN_COMMANDS
12058 install_element(ENABLE_NODE
,
12059 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12060 #endif /* KEEP_OLD_VPN_COMMANDS */
12062 /* New config IPv6 BGP commands. */
12063 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12064 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12065 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12067 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12068 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12070 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12072 install_element(BGP_NODE
, &bgp_distance_cmd
);
12073 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12074 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12075 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12076 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12077 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12078 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12079 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12080 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12081 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12082 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12083 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12084 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12085 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12086 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12087 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12088 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12089 install_element(BGP_IPV4M_NODE
,
12090 &no_bgp_distance_source_access_list_cmd
);
12091 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12092 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12093 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12094 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12095 install_element(BGP_IPV6_NODE
,
12096 &ipv6_bgp_distance_source_access_list_cmd
);
12097 install_element(BGP_IPV6_NODE
,
12098 &no_ipv6_bgp_distance_source_access_list_cmd
);
12099 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12100 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12101 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12102 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12103 install_element(BGP_IPV6M_NODE
,
12104 &ipv6_bgp_distance_source_access_list_cmd
);
12105 install_element(BGP_IPV6M_NODE
,
12106 &no_ipv6_bgp_distance_source_access_list_cmd
);
12108 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12109 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12110 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12111 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12113 /* IPv4 Multicast Mode */
12114 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12115 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12117 /* Large Communities */
12118 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12119 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12121 /* show bgp ipv4 flowspec detailed */
12122 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12124 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12127 void bgp_route_finish(void)
12132 FOREACH_AFI_SAFI (afi
, safi
) {
12133 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12134 bgp_distance_table
[afi
][safi
] = NULL
;