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
= NULL
;
179 new->bgp_fs_iprule
= NULL
;
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, e
->damp_info
->afi
,
197 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
200 /* FIXME: since multiple e may have the same e->parent
201 * and e->parent->net is holding a refcount for each
202 * of them, we need to do some fudging here.
204 * WARNING: if bpi->net->lock drops to 0, bpi may be
205 * freed as well (because bpi->net was holding the
206 * last reference to bpi) => write after free!
210 bpi
= bgp_path_info_lock(bpi
);
211 refcount
= bpi
->net
->lock
- 1;
212 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
215 bgp_path_info_unlock(bpi
);
217 bgp_path_info_unlock(e
->parent
);
222 bgp_unlock(e
->bgp_orig
);
224 if ((*extra
)->bgp_fs_iprule
)
225 list_delete(&((*extra
)->bgp_fs_iprule
));
226 if ((*extra
)->bgp_fs_pbr
)
227 list_delete(&((*extra
)->bgp_fs_pbr
));
228 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
233 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
234 * allocated if required.
236 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
239 pi
->extra
= bgp_path_info_extra_new();
243 /* Free bgp route information. */
244 static void bgp_path_info_free(struct bgp_path_info
*path
)
247 bgp_attr_unintern(&path
->attr
);
249 bgp_unlink_nexthop(path
);
250 bgp_path_info_extra_free(&path
->extra
);
251 bgp_path_info_mpath_free(&path
->mpath
);
253 bgp_addpath_free_info_data(&path
->tx_addpath
,
254 &path
->net
->tx_addpath
);
256 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
258 XFREE(MTYPE_BGP_ROUTE
, path
);
261 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
267 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
269 assert(path
&& path
->lock
> 0);
272 if (path
->lock
== 0) {
274 zlog_debug ("%s: unlocked and freeing", __func__
);
275 zlog_backtrace (LOG_DEBUG
);
277 bgp_path_info_free(path
);
284 zlog_debug ("%s: unlocked to 1", __func__
);
285 zlog_backtrace (LOG_DEBUG
);
292 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
294 struct bgp_path_info
*top
;
296 top
= bgp_node_get_bgp_path_info(rn
);
302 bgp_node_set_bgp_path_info(rn
, pi
);
304 bgp_path_info_lock(pi
);
306 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
309 /* Do the actual removal of info from RIB, for use by bgp_process
310 completion callback *only* */
311 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
314 pi
->next
->prev
= pi
->prev
;
316 pi
->prev
->next
= pi
->next
;
318 bgp_node_set_bgp_path_info(rn
, pi
->next
);
320 bgp_path_info_mpath_dequeue(pi
);
321 bgp_path_info_unlock(pi
);
325 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
327 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
328 /* set of previous already took care of pcount */
329 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
332 /* undo the effects of a previous call to bgp_path_info_delete; typically
333 called when a route is deleted and then quickly re-added before the
334 deletion has been processed */
335 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
337 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
338 /* unset of previous already took care of pcount */
339 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
342 /* Adjust pcount as required */
343 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
345 struct bgp_table
*table
;
347 assert(rn
&& bgp_node_table(rn
));
348 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
350 table
= bgp_node_table(rn
);
352 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
355 if (!BGP_PATH_COUNTABLE(pi
)
356 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
358 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
360 /* slight hack, but more robust against errors. */
361 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
362 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
364 flog_err(EC_LIB_DEVELOPMENT
,
365 "Asked to decrement 0 prefix count for peer");
366 } else if (BGP_PATH_COUNTABLE(pi
)
367 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
368 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
369 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
373 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
374 struct bgp_path_info
*pi2
)
376 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
379 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
380 * This is here primarily to keep prefix-count in check.
382 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
385 SET_FLAG(pi
->flags
, flag
);
387 /* early bath if we know it's not a flag that changes countability state
389 if (!CHECK_FLAG(flag
,
390 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
393 bgp_pcount_adjust(rn
, pi
);
396 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
399 UNSET_FLAG(pi
->flags
, flag
);
401 /* early bath if we know it's not a flag that changes countability state
403 if (!CHECK_FLAG(flag
,
404 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
407 bgp_pcount_adjust(rn
, pi
);
410 /* Get MED value. If MED value is missing and "bgp bestpath
411 missing-as-worst" is specified, treat it as the worst value. */
412 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
414 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
417 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
424 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
426 if (pi
->addpath_rx_id
)
427 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
430 sprintf(buf
, "path %s", pi
->peer
->host
);
433 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
435 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
436 struct bgp_path_info
*exist
, int *paths_eq
,
437 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
438 char *pfx_buf
, afi_t afi
, safi_t safi
)
440 struct attr
*newattr
, *existattr
;
441 bgp_peer_sort_t new_sort
;
442 bgp_peer_sort_t exist_sort
;
448 uint32_t exist_weight
;
449 uint32_t newm
, existm
;
450 struct in_addr new_id
;
451 struct in_addr exist_id
;
454 int internal_as_route
;
457 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
458 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
460 uint32_t exist_mm_seq
;
468 zlog_debug("%s: new is NULL", pfx_buf
);
473 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
477 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
483 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
484 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
485 pfx_buf
, new_buf
, new->flags
, exist_buf
,
490 existattr
= exist
->attr
;
492 /* For EVPN routes, we cannot just go by local vs remote, we have to
493 * look at the MAC mobility sequence number, if present.
495 if (safi
== SAFI_EVPN
) {
496 /* This is an error condition described in RFC 7432 Section
498 * states that in this scenario "the PE MUST alert the operator"
500 * does not state what other action to take. In order to provide
502 * consistency in this scenario we are going to prefer the path
506 if (newattr
->sticky
!= existattr
->sticky
) {
508 prefix2str(&new->net
->p
, pfx_buf
,
510 * PREFIX2STR_BUFFER
);
511 bgp_path_info_path_with_addpath_rx_str(new,
513 bgp_path_info_path_with_addpath_rx_str(
517 if (newattr
->sticky
&& !existattr
->sticky
) {
520 "%s: %s wins over %s due to sticky MAC flag",
521 pfx_buf
, new_buf
, exist_buf
);
525 if (!newattr
->sticky
&& existattr
->sticky
) {
528 "%s: %s loses to %s due to sticky MAC flag",
529 pfx_buf
, new_buf
, exist_buf
);
534 new_mm_seq
= mac_mobility_seqnum(newattr
);
535 exist_mm_seq
= mac_mobility_seqnum(existattr
);
537 if (new_mm_seq
> exist_mm_seq
) {
540 "%s: %s wins over %s due to MM seq %u > %u",
541 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
546 if (new_mm_seq
< exist_mm_seq
) {
549 "%s: %s loses to %s due to MM seq %u < %u",
550 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
556 * if sequence numbers are the same path with the lowest IP
559 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
563 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
564 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
565 inet_ntoa(new->attr
->nexthop
));
571 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
572 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
573 inet_ntoa(new->attr
->nexthop
));
578 /* 1. Weight check. */
579 new_weight
= newattr
->weight
;
580 exist_weight
= existattr
->weight
;
582 if (new_weight
> exist_weight
) {
584 zlog_debug("%s: %s wins over %s due to weight %d > %d",
585 pfx_buf
, new_buf
, exist_buf
, new_weight
,
590 if (new_weight
< exist_weight
) {
592 zlog_debug("%s: %s loses to %s due to weight %d < %d",
593 pfx_buf
, new_buf
, exist_buf
, new_weight
,
598 /* 2. Local preference check. */
599 new_pref
= exist_pref
= bgp
->default_local_pref
;
601 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
602 new_pref
= newattr
->local_pref
;
603 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
604 exist_pref
= existattr
->local_pref
;
606 if (new_pref
> exist_pref
) {
609 "%s: %s wins over %s due to localpref %d > %d",
610 pfx_buf
, new_buf
, exist_buf
, new_pref
,
615 if (new_pref
< exist_pref
) {
618 "%s: %s loses to %s due to localpref %d < %d",
619 pfx_buf
, new_buf
, exist_buf
, new_pref
,
624 /* 3. Local route check. We prefer:
626 * - BGP_ROUTE_AGGREGATE
627 * - BGP_ROUTE_REDISTRIBUTE
629 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
630 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
633 "%s: %s wins over %s due to preferred BGP_ROUTE type",
634 pfx_buf
, new_buf
, exist_buf
);
638 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
639 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
642 "%s: %s loses to %s due to preferred BGP_ROUTE type",
643 pfx_buf
, new_buf
, exist_buf
);
647 /* 4. AS path length check. */
648 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
649 int exist_hops
= aspath_count_hops(existattr
->aspath
);
650 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
652 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
655 aspath_hops
= aspath_count_hops(newattr
->aspath
);
656 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
658 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
661 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
662 pfx_buf
, new_buf
, exist_buf
,
664 (exist_hops
+ exist_confeds
));
668 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
671 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
672 pfx_buf
, new_buf
, exist_buf
,
674 (exist_hops
+ exist_confeds
));
678 int newhops
= aspath_count_hops(newattr
->aspath
);
680 if (newhops
< exist_hops
) {
683 "%s: %s wins over %s due to aspath hopcount %d < %d",
684 pfx_buf
, new_buf
, exist_buf
,
685 newhops
, exist_hops
);
689 if (newhops
> exist_hops
) {
692 "%s: %s loses to %s due to aspath hopcount %d > %d",
693 pfx_buf
, new_buf
, exist_buf
,
694 newhops
, exist_hops
);
700 /* 5. Origin check. */
701 if (newattr
->origin
< existattr
->origin
) {
703 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
704 pfx_buf
, new_buf
, exist_buf
,
705 bgp_origin_long_str
[newattr
->origin
],
706 bgp_origin_long_str
[existattr
->origin
]);
710 if (newattr
->origin
> existattr
->origin
) {
712 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
713 pfx_buf
, new_buf
, exist_buf
,
714 bgp_origin_long_str
[newattr
->origin
],
715 bgp_origin_long_str
[existattr
->origin
]);
720 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
721 && aspath_count_hops(existattr
->aspath
) == 0);
722 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
723 && aspath_count_confeds(existattr
->aspath
) > 0
724 && aspath_count_hops(newattr
->aspath
) == 0
725 && aspath_count_hops(existattr
->aspath
) == 0);
727 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
728 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
729 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
730 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
731 || internal_as_route
) {
732 new_med
= bgp_med_value(new->attr
, bgp
);
733 exist_med
= bgp_med_value(exist
->attr
, bgp
);
735 if (new_med
< exist_med
) {
738 "%s: %s wins over %s due to MED %d < %d",
739 pfx_buf
, new_buf
, exist_buf
, new_med
,
744 if (new_med
> exist_med
) {
747 "%s: %s loses to %s due to MED %d > %d",
748 pfx_buf
, new_buf
, exist_buf
, new_med
,
754 /* 7. Peer type check. */
755 new_sort
= new->peer
->sort
;
756 exist_sort
= exist
->peer
->sort
;
758 if (new_sort
== BGP_PEER_EBGP
759 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
762 "%s: %s wins over %s due to eBGP peer > iBGP peer",
763 pfx_buf
, new_buf
, exist_buf
);
767 if (exist_sort
== BGP_PEER_EBGP
768 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
771 "%s: %s loses to %s due to iBGP peer < eBGP peer",
772 pfx_buf
, new_buf
, exist_buf
);
776 /* 8. IGP metric check. */
780 newm
= new->extra
->igpmetric
;
782 existm
= exist
->extra
->igpmetric
;
787 "%s: %s wins over %s due to IGP metric %d < %d",
788 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
795 "%s: %s loses to %s due to IGP metric %d > %d",
796 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
800 /* 9. Same IGP metric. Compare the cluster list length as
801 representative of IGP hops metric. Rewrite the metric value
802 pair (newm, existm) with the cluster list length. Prefer the
803 path with smaller cluster list length. */
804 if (newm
== existm
) {
805 if (peer_sort(new->peer
) == BGP_PEER_IBGP
806 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
807 && (mpath_cfg
== NULL
809 mpath_cfg
->ibgp_flags
,
810 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
811 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
812 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
817 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
818 pfx_buf
, new_buf
, exist_buf
,
826 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
827 pfx_buf
, new_buf
, exist_buf
,
834 /* 10. confed-external vs. confed-internal */
835 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
836 if (new_sort
== BGP_PEER_CONFED
837 && exist_sort
== BGP_PEER_IBGP
) {
840 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
841 pfx_buf
, new_buf
, exist_buf
);
845 if (exist_sort
== BGP_PEER_CONFED
846 && new_sort
== BGP_PEER_IBGP
) {
849 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
850 pfx_buf
, new_buf
, exist_buf
);
855 /* 11. Maximum path check. */
856 if (newm
== existm
) {
857 /* If one path has a label but the other does not, do not treat
858 * them as equals for multipath
860 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
862 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
865 "%s: %s and %s cannot be multipath, one has a label while the other does not",
866 pfx_buf
, new_buf
, exist_buf
);
867 } else if (bgp_flag_check(bgp
,
868 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
871 * For the two paths, all comparison steps till IGP
873 * have succeeded - including AS_PATH hop count. Since
875 * bestpath as-path multipath-relax' knob is on, we
877 * an exact match of AS_PATH. Thus, mark the paths are
879 * That will trigger both these paths to get into the
887 "%s: %s and %s are equal via multipath-relax",
888 pfx_buf
, new_buf
, exist_buf
);
889 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
890 if (aspath_cmp(new->attr
->aspath
,
891 exist
->attr
->aspath
)) {
896 "%s: %s and %s are equal via matching aspaths",
897 pfx_buf
, new_buf
, exist_buf
);
899 } else if (new->peer
->as
== exist
->peer
->as
) {
904 "%s: %s and %s are equal via same remote-as",
905 pfx_buf
, new_buf
, exist_buf
);
909 * TODO: If unequal cost ibgp multipath is enabled we can
910 * mark the paths as equal here instead of returning
915 "%s: %s wins over %s after IGP metric comparison",
916 pfx_buf
, new_buf
, exist_buf
);
919 "%s: %s loses to %s after IGP metric comparison",
920 pfx_buf
, new_buf
, exist_buf
);
925 /* 12. If both paths are external, prefer the path that was received
926 first (the oldest one). This step minimizes route-flap, since a
927 newer path won't displace an older one, even if it was the
928 preferred route based on the additional decision criteria below. */
929 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
930 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
931 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
934 "%s: %s wins over %s due to oldest external",
935 pfx_buf
, new_buf
, exist_buf
);
939 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
942 "%s: %s loses to %s due to oldest external",
943 pfx_buf
, new_buf
, exist_buf
);
948 /* 13. Router-ID comparision. */
949 /* If one of the paths is "stale", the corresponding peer router-id will
950 * be 0 and would always win over the other path. If originator id is
951 * used for the comparision, it will decide which path is better.
953 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
954 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
956 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
957 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
958 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
960 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
962 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
965 "%s: %s wins over %s due to Router-ID comparison",
966 pfx_buf
, new_buf
, exist_buf
);
970 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
973 "%s: %s loses to %s due to Router-ID comparison",
974 pfx_buf
, new_buf
, exist_buf
);
978 /* 14. Cluster length comparision. */
979 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
980 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
982 if (new_cluster
< exist_cluster
) {
985 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
986 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
991 if (new_cluster
> exist_cluster
) {
994 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
995 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1000 /* 15. Neighbor address comparision. */
1001 /* Do this only if neither path is "stale" as stale paths do not have
1002 * valid peer information (as the connection may or may not be up).
1004 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1007 "%s: %s wins over %s due to latter path being STALE",
1008 pfx_buf
, new_buf
, exist_buf
);
1012 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1015 "%s: %s loses to %s due to former path being STALE",
1016 pfx_buf
, new_buf
, exist_buf
);
1020 /* locally configured routes to advertise do not have su_remote */
1021 if (new->peer
->su_remote
== NULL
)
1023 if (exist
->peer
->su_remote
== NULL
)
1026 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1031 "%s: %s loses to %s due to Neighor IP comparison",
1032 pfx_buf
, new_buf
, exist_buf
);
1039 "%s: %s wins over %s due to Neighor IP comparison",
1040 pfx_buf
, new_buf
, exist_buf
);
1045 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1046 pfx_buf
, new_buf
, exist_buf
);
1051 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1052 * is preferred, or 0 if they are the same (usually will only occur if
1053 * multipath is enabled
1054 * This version is compatible with */
1055 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1056 struct bgp_path_info
*exist
, char *pfx_buf
,
1057 afi_t afi
, safi_t safi
)
1061 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1075 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1076 struct attr
*attr
, afi_t afi
,
1079 struct bgp_filter
*filter
;
1081 filter
= &peer
->filter
[afi
][safi
];
1083 #define FILTER_EXIST_WARN(F, f, filter) \
1084 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1085 zlog_debug("%s: Could not find configured input %s-list %s!", \
1086 peer->host, #f, F##_IN_NAME(filter));
1088 if (DISTRIBUTE_IN_NAME(filter
)) {
1089 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1091 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1095 if (PREFIX_LIST_IN_NAME(filter
)) {
1096 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1098 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1102 if (FILTER_LIST_IN_NAME(filter
)) {
1103 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1105 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1110 return FILTER_PERMIT
;
1111 #undef FILTER_EXIST_WARN
1114 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1115 struct attr
*attr
, afi_t afi
,
1118 struct bgp_filter
*filter
;
1120 filter
= &peer
->filter
[afi
][safi
];
1122 #define FILTER_EXIST_WARN(F, f, filter) \
1123 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1124 zlog_debug("%s: Could not find configured output %s-list %s!", \
1125 peer->host, #f, F##_OUT_NAME(filter));
1127 if (DISTRIBUTE_OUT_NAME(filter
)) {
1128 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1130 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1134 if (PREFIX_LIST_OUT_NAME(filter
)) {
1135 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1137 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1142 if (FILTER_LIST_OUT_NAME(filter
)) {
1143 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1145 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1150 return FILTER_PERMIT
;
1151 #undef FILTER_EXIST_WARN
1154 /* If community attribute includes no_export then return 1. */
1155 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1157 if (attr
->community
) {
1158 /* NO_ADVERTISE check. */
1159 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1162 /* NO_EXPORT check. */
1163 if (peer
->sort
== BGP_PEER_EBGP
1164 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1167 /* NO_EXPORT_SUBCONFED check. */
1168 if (peer
->sort
== BGP_PEER_EBGP
1169 || peer
->sort
== BGP_PEER_CONFED
)
1170 if (community_include(attr
->community
,
1171 COMMUNITY_NO_EXPORT_SUBCONFED
))
1177 /* Route reflection loop check. */
1178 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1180 struct in_addr cluster_id
;
1182 if (attr
->cluster
) {
1183 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1184 cluster_id
= peer
->bgp
->cluster_id
;
1186 cluster_id
= peer
->bgp
->router_id
;
1188 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1194 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1195 struct attr
*attr
, afi_t afi
, safi_t safi
,
1196 const char *rmap_name
)
1198 struct bgp_filter
*filter
;
1199 struct bgp_path_info rmap_path
;
1200 route_map_result_t ret
;
1201 struct route_map
*rmap
= NULL
;
1203 filter
= &peer
->filter
[afi
][safi
];
1205 /* Apply default weight value. */
1206 if (peer
->weight
[afi
][safi
])
1207 attr
->weight
= peer
->weight
[afi
][safi
];
1210 rmap
= route_map_lookup_by_name(rmap_name
);
1215 if (ROUTE_MAP_IN_NAME(filter
)) {
1216 rmap
= ROUTE_MAP_IN(filter
);
1223 /* RFC 8212 to prevent route leaks.
1224 * This specification intends to improve this situation by requiring the
1225 * explicit configuration of both BGP Import and Export Policies for any
1226 * External BGP (EBGP) session such as customers, peers, or
1227 * confederation boundaries for all enabled address families. Through
1228 * codification of the aforementioned requirement, operators will
1229 * benefit from consistent behavior across different BGP
1232 if (peer
->bgp
->ebgp_requires_policy
1233 == DEFAULT_EBGP_POLICY_ENABLED
)
1234 if (!bgp_inbound_policy_exists(peer
, filter
))
1237 /* Route map apply. */
1239 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1240 /* Duplicate current value to new strucutre for modification. */
1241 rmap_path
.peer
= peer
;
1242 rmap_path
.attr
= attr
;
1244 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1246 /* Apply BGP route map to the attribute. */
1247 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1249 peer
->rmap_type
= 0;
1251 if (ret
== RMAP_DENYMATCH
)
1257 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1258 struct attr
*attr
, afi_t afi
, safi_t safi
,
1259 const char *rmap_name
)
1261 struct bgp_path_info rmap_path
;
1262 route_map_result_t ret
;
1263 struct route_map
*rmap
= NULL
;
1267 * So if we get to this point and have no rmap_name
1268 * we want to just show the output as it currently
1274 /* Apply default weight value. */
1275 if (peer
->weight
[afi
][safi
])
1276 attr
->weight
= peer
->weight
[afi
][safi
];
1278 rmap
= route_map_lookup_by_name(rmap_name
);
1281 * If we have a route map name and we do not find
1282 * the routemap that means we have an implicit
1288 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1289 /* Route map apply. */
1290 /* Duplicate current value to new strucutre for modification. */
1291 rmap_path
.peer
= peer
;
1292 rmap_path
.attr
= attr
;
1294 rmap_type
= peer
->rmap_type
;
1295 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1297 /* Apply BGP route map to the attribute. */
1298 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1300 peer
->rmap_type
= rmap_type
;
1302 if (ret
== RMAP_DENYMATCH
)
1304 * caller has multiple error paths with bgp_attr_flush()
1311 /* If this is an EBGP peer with remove-private-AS */
1312 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1313 struct peer
*peer
, struct attr
*attr
)
1315 if (peer
->sort
== BGP_PEER_EBGP
1316 && (peer_af_flag_check(peer
, afi
, safi
,
1317 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1318 || peer_af_flag_check(peer
, afi
, safi
,
1319 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1320 || peer_af_flag_check(peer
, afi
, safi
,
1321 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1322 || peer_af_flag_check(peer
, afi
, safi
,
1323 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1324 // Take action on the entire aspath
1325 if (peer_af_flag_check(peer
, afi
, safi
,
1326 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1327 || peer_af_flag_check(peer
, afi
, safi
,
1328 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1329 if (peer_af_flag_check(
1331 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1332 attr
->aspath
= aspath_replace_private_asns(
1333 attr
->aspath
, bgp
->as
);
1335 // The entire aspath consists of private ASNs so create
1337 else if (aspath_private_as_check(attr
->aspath
))
1338 attr
->aspath
= aspath_empty_get();
1340 // There are some public and some private ASNs, remove
1343 attr
->aspath
= aspath_remove_private_asns(
1347 // 'all' was not specified so the entire aspath must be private
1349 // for us to do anything
1350 else if (aspath_private_as_check(attr
->aspath
)) {
1351 if (peer_af_flag_check(
1353 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1354 attr
->aspath
= aspath_replace_private_asns(
1355 attr
->aspath
, bgp
->as
);
1357 attr
->aspath
= aspath_empty_get();
1362 /* If this is an EBGP peer with as-override */
1363 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1364 struct peer
*peer
, struct attr
*attr
)
1366 if (peer
->sort
== BGP_PEER_EBGP
1367 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1368 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1369 attr
->aspath
= aspath_replace_specific_asn(
1370 attr
->aspath
, peer
->as
, bgp
->as
);
1374 void bgp_attr_add_gshut_community(struct attr
*attr
)
1376 struct community
*old
;
1377 struct community
*new;
1378 struct community
*merge
;
1379 struct community
*gshut
;
1381 old
= attr
->community
;
1382 gshut
= community_str2com("graceful-shutdown");
1387 merge
= community_merge(community_dup(old
), gshut
);
1389 if (old
->refcnt
== 0)
1390 community_free(&old
);
1392 new = community_uniq_sort(merge
);
1393 community_free(&merge
);
1395 new = community_dup(gshut
);
1398 community_free(&gshut
);
1399 attr
->community
= new;
1400 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1402 /* When we add the graceful-shutdown community we must also
1403 * lower the local-preference */
1404 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1405 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1409 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1411 if (family
== AF_INET
) {
1412 attr
->nexthop
.s_addr
= 0;
1413 attr
->mp_nexthop_global_in
.s_addr
= 0;
1415 if (family
== AF_INET6
)
1416 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1417 if (family
== AF_EVPN
)
1418 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1421 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1422 struct update_subgroup
*subgrp
, struct prefix
*p
,
1425 struct bgp_filter
*filter
;
1428 struct peer
*onlypeer
;
1430 struct attr
*piattr
;
1431 char buf
[PREFIX_STRLEN
];
1437 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1439 if (DISABLE_BGP_ANNOUNCE
)
1442 afi
= SUBGRP_AFI(subgrp
);
1443 safi
= SUBGRP_SAFI(subgrp
);
1444 peer
= SUBGRP_PEER(subgrp
);
1446 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1447 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1450 filter
= &peer
->filter
[afi
][safi
];
1451 bgp
= SUBGRP_INST(subgrp
);
1452 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1456 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1457 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1458 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1461 * direct and direct_ext type routes originate internally even
1462 * though they can have peer pointers that reference other
1465 prefix2str(p
, buf
, PREFIX_STRLEN
);
1466 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1472 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1473 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1474 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1475 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1477 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1482 /* With addpath we may be asked to TX all kinds of paths so make sure
1484 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1485 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1486 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1490 /* If this is not the bestpath then check to see if there is an enabled
1492 * feature that requires us to advertise it */
1493 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1494 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1499 /* Aggregate-address suppress check. */
1500 if (pi
->extra
&& pi
->extra
->suppress
)
1501 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1506 * If we are doing VRF 2 VRF leaking via the import
1507 * statement, we want to prevent the route going
1508 * off box as that the RT and RD created are localy
1509 * significant and globaly useless.
1511 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1512 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1515 /* If it's labeled safi, make sure the route has a valid label. */
1516 if (safi
== SAFI_LABELED_UNICAST
) {
1517 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1518 if (!bgp_is_valid_label(&label
)) {
1519 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1520 zlog_debug("u%" PRIu64
":s%" PRIu64
1521 " %s/%d is filtered - no label (%p)",
1522 subgrp
->update_group
->id
, subgrp
->id
,
1523 inet_ntop(p
->family
, &p
->u
.prefix
,
1524 buf
, SU_ADDRSTRLEN
),
1525 p
->prefixlen
, &label
);
1530 /* Do not send back route to sender. */
1531 if (onlypeer
&& from
== onlypeer
) {
1535 /* Do not send the default route in the BGP table if the neighbor is
1536 * configured for default-originate */
1537 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1538 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1539 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1541 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1545 /* Transparency check. */
1546 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1547 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1552 /* If community is not disabled check the no-export and local. */
1553 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1554 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1556 "subgrpannouncecheck: community filter check fail");
1560 /* If the attribute has originator-id and it is same as remote
1562 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1563 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1564 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1566 "%s [Update:SEND] %s originator-id is same as "
1569 prefix2str(p
, buf
, sizeof(buf
)));
1573 /* ORF prefix-list filter check */
1574 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1575 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1576 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1577 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1578 if (peer
->orf_plist
[afi
][safi
]) {
1579 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1581 if (bgp_debug_update(NULL
, p
,
1582 subgrp
->update_group
, 0))
1584 "%s [Update:SEND] %s is filtered via ORF",
1592 /* Output filter check. */
1593 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1594 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1595 zlog_debug("%s [Update:SEND] %s is filtered",
1596 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1600 #ifdef BGP_SEND_ASPATH_CHECK
1601 /* AS path loop check. */
1602 if (onlypeer
&& aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1603 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1605 "%s [Update:SEND] suppress announcement to peer AS %u "
1606 "that is part of AS path.",
1607 onlypeer
->host
, onlypeer
->as
);
1610 #endif /* BGP_SEND_ASPATH_CHECK */
1612 /* If we're a CONFED we need to loop check the CONFED ID too */
1613 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1614 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1615 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1617 "%s [Update:SEND] suppress announcement to peer AS %u"
1619 peer
->host
, bgp
->confed_id
);
1624 /* Route-Reflect check. */
1625 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1630 /* IBGP reflection check. */
1631 if (reflect
&& !samepeer_safe
) {
1632 /* A route from a Client peer. */
1633 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1634 PEER_FLAG_REFLECTOR_CLIENT
)) {
1635 /* Reflect to all the Non-Client peers and also to the
1636 Client peers other than the originator. Originator
1638 is already done. So there is noting to do. */
1639 /* no bgp client-to-client reflection check. */
1640 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1641 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1642 PEER_FLAG_REFLECTOR_CLIENT
))
1645 /* A route from a Non-client peer. Reflect to all other
1647 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1648 PEER_FLAG_REFLECTOR_CLIENT
))
1653 /* For modify attribute, copy it to temporary structure. */
1654 bgp_attr_dup(attr
, piattr
);
1656 /* If local-preference is not set. */
1657 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1658 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1659 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1660 attr
->local_pref
= bgp
->default_local_pref
;
1663 /* If originator-id is not set and the route is to be reflected,
1664 set the originator id */
1666 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1667 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1668 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1671 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1673 if (peer
->sort
== BGP_PEER_EBGP
1674 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1675 if (from
!= bgp
->peer_self
&& !transparent
1676 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1677 PEER_FLAG_MED_UNCHANGED
))
1679 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1682 /* Since the nexthop attribute can vary per peer, it is not explicitly
1684 * in announce check, only certain flags and length (or number of
1686 * -- for IPv6/MP_REACH) are set here in order to guide the update
1688 * code in setting the nexthop(s) on a per peer basis in
1690 * Typically, the source nexthop in the attribute is preserved but in
1692 * scenarios where we know it will always be overwritten, we reset the
1693 * nexthop to "0" in an attempt to achieve better Update packing. An
1694 * example of this is when a prefix from each of 2 IBGP peers needs to
1696 * announced to an EBGP peer (and they have the same attributes barring
1700 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1702 #define NEXTHOP_IS_V6 \
1703 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1704 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1705 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1706 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1708 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1710 * the peer (group) is configured to receive link-local nexthop
1712 * and it is available in the prefix OR we're not reflecting the route,
1713 * link-local nexthop address is valid and
1714 * the peer (group) to whom we're going to announce is on a shared
1716 * and this is either a self-originated route or the peer is EBGP.
1717 * By checking if nexthop LL address is valid we are sure that
1718 * we do not announce LL address as `::`.
1720 if (NEXTHOP_IS_V6
) {
1721 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1722 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1723 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1724 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1726 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
1727 && peer
->shared_network
1728 && (from
== bgp
->peer_self
1729 || peer
->sort
== BGP_PEER_EBGP
))) {
1730 attr
->mp_nexthop_len
=
1731 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1734 /* Clear off link-local nexthop in source, whenever it is not
1736 * ensure more prefixes share the same attribute for
1739 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1740 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1741 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1744 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1745 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1747 /* Route map & unsuppress-map apply. */
1748 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1749 struct bgp_path_info rmap_path
;
1750 struct bgp_path_info_extra dummy_rmap_path_extra
;
1751 struct attr dummy_attr
;
1753 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1754 rmap_path
.peer
= peer
;
1755 rmap_path
.attr
= attr
;
1758 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1759 sizeof(struct bgp_path_info_extra
));
1760 rmap_path
.extra
= &dummy_rmap_path_extra
;
1763 /* don't confuse inbound and outbound setting */
1764 RESET_FLAG(attr
->rmap_change_flags
);
1767 * The route reflector is not allowed to modify the attributes
1768 * of the reflected IBGP routes unless explicitly allowed.
1770 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1771 && !bgp_flag_check(bgp
,
1772 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1773 bgp_attr_dup(&dummy_attr
, attr
);
1774 rmap_path
.attr
= &dummy_attr
;
1777 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1779 if (pi
->extra
&& pi
->extra
->suppress
)
1780 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1781 RMAP_BGP
, &rmap_path
);
1783 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1784 RMAP_BGP
, &rmap_path
);
1786 peer
->rmap_type
= 0;
1788 if (ret
== RMAP_DENYMATCH
) {
1789 bgp_attr_flush(attr
);
1794 /* RFC 8212 to prevent route leaks.
1795 * This specification intends to improve this situation by requiring the
1796 * explicit configuration of both BGP Import and Export Policies for any
1797 * External BGP (EBGP) session such as customers, peers, or
1798 * confederation boundaries for all enabled address families. Through
1799 * codification of the aforementioned requirement, operators will
1800 * benefit from consistent behavior across different BGP
1803 if (peer
->bgp
->ebgp_requires_policy
1804 == DEFAULT_EBGP_POLICY_ENABLED
)
1805 if (!bgp_outbound_policy_exists(peer
, filter
))
1808 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1809 if (peer
->sort
== BGP_PEER_IBGP
1810 || peer
->sort
== BGP_PEER_CONFED
) {
1811 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1812 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1814 bgp_attr_add_gshut_community(attr
);
1818 /* After route-map has been applied, we check to see if the nexthop to
1819 * be carried in the attribute (that is used for the announcement) can
1820 * be cleared off or not. We do this in all cases where we would be
1821 * setting the nexthop to "ourselves". For IPv6, we only need to
1823 * the global nexthop here; the link-local nexthop would have been
1825 * already, and if not, it is required by the update formation code.
1826 * Also see earlier comments in this function.
1829 * If route-map has performed some operation on the nexthop or the peer
1830 * configuration says to pass it unchanged, we cannot reset the nexthop
1831 * here, so only attempt to do it if these aren't true. Note that the
1832 * route-map handler itself might have cleared the nexthop, if for
1834 * it is configured as 'peer-address'.
1836 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1837 piattr
->rmap_change_flags
)
1839 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1840 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1841 /* We can reset the nexthop, if setting (or forcing) it to
1843 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1844 PEER_FLAG_NEXTHOP_SELF
)
1845 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1846 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1848 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1849 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1850 subgroup_announce_reset_nhop(
1851 (peer_cap_enhe(peer
, afi
, safi
)
1855 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1856 /* Can also reset the nexthop if announcing to EBGP, but
1858 * no peer in the subgroup is on a shared subnet.
1859 * Note: 3rd party nexthop currently implemented for
1862 if (!bgp_subgrp_multiaccess_check_v4(piattr
->nexthop
,
1864 subgroup_announce_reset_nhop(
1865 (peer_cap_enhe(peer
, afi
, safi
)
1869 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1871 * This flag is used for leaked vpn-vrf routes
1873 int family
= p
->family
;
1875 if (peer_cap_enhe(peer
, afi
, safi
))
1878 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1880 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1881 __func__
, family2str(family
));
1882 subgroup_announce_reset_nhop(family
, attr
);
1885 /* If IPv6/MP and nexthop does not have any override and happens
1887 * be a link-local address, reset it so that we don't pass along
1889 * source's link-local IPv6 address to recipients who may not be
1891 * the same interface.
1893 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1894 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1895 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1902 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1903 struct bgp_maxpaths_cfg
*mpath_cfg
,
1904 struct bgp_path_info_pair
*result
, afi_t afi
,
1907 struct bgp_path_info
*new_select
;
1908 struct bgp_path_info
*old_select
;
1909 struct bgp_path_info
*pi
;
1910 struct bgp_path_info
*pi1
;
1911 struct bgp_path_info
*pi2
;
1912 struct bgp_path_info
*nextpi
= NULL
;
1913 int paths_eq
, do_mpath
, debug
;
1914 struct list mp_list
;
1915 char pfx_buf
[PREFIX2STR_BUFFER
];
1916 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1918 bgp_mp_list_init(&mp_list
);
1920 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1922 debug
= bgp_debug_bestpath(&rn
->p
);
1925 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1927 /* bgp deterministic-med */
1929 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1931 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1932 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1934 bgp_path_info_unset_flag(rn
, pi1
,
1935 BGP_PATH_DMED_SELECTED
);
1937 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1939 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1941 if (BGP_PATH_HOLDDOWN(pi1
))
1943 if (pi1
->peer
!= bgp
->peer_self
)
1944 if (pi1
->peer
->status
!= Established
)
1949 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
1950 if (CHECK_FLAG(pi2
->flags
,
1951 BGP_PATH_DMED_CHECK
))
1953 if (BGP_PATH_HOLDDOWN(pi2
))
1955 if (pi2
->peer
!= bgp
->peer_self
1958 PEER_STATUS_NSF_WAIT
))
1959 if (pi2
->peer
->status
1963 if (!aspath_cmp_left(pi1
->attr
->aspath
,
1965 && !aspath_cmp_left_confed(
1970 if (bgp_path_info_cmp(
1971 bgp
, pi2
, new_select
,
1972 &paths_eq
, mpath_cfg
, debug
,
1973 pfx_buf
, afi
, safi
)) {
1974 bgp_path_info_unset_flag(
1976 BGP_PATH_DMED_SELECTED
);
1980 bgp_path_info_set_flag(
1981 rn
, pi2
, BGP_PATH_DMED_CHECK
);
1984 bgp_path_info_set_flag(rn
, new_select
,
1985 BGP_PATH_DMED_CHECK
);
1986 bgp_path_info_set_flag(rn
, new_select
,
1987 BGP_PATH_DMED_SELECTED
);
1990 bgp_path_info_path_with_addpath_rx_str(
1991 new_select
, path_buf
);
1992 zlog_debug("%s: %s is the bestpath from AS %u",
1994 aspath_get_first_as(
1995 new_select
->attr
->aspath
));
2000 /* Check old selected route and new selected route. */
2003 for (pi
= bgp_node_get_bgp_path_info(rn
);
2004 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2005 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2008 if (BGP_PATH_HOLDDOWN(pi
)) {
2009 /* reap REMOVED routes, if needs be
2010 * selected route must stay for a while longer though
2012 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2013 && (pi
!= old_select
))
2014 bgp_path_info_reap(rn
, pi
);
2017 zlog_debug("%s: pi %p in holddown", __func__
,
2023 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2024 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2025 if (pi
->peer
->status
!= Established
) {
2029 "%s: pi %p non self peer %s not estab state",
2030 __func__
, pi
, pi
->peer
->host
);
2035 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2036 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2037 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2039 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2043 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2045 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2046 debug
, pfx_buf
, afi
, safi
)) {
2051 /* Now that we know which path is the bestpath see if any of the other
2053 * qualify as multipaths
2057 bgp_path_info_path_with_addpath_rx_str(new_select
,
2060 sprintf(path_buf
, "NONE");
2062 "%s: After path selection, newbest is %s oldbest was %s",
2064 old_select
? old_select
->peer
->host
: "NONE");
2067 if (do_mpath
&& new_select
) {
2068 for (pi
= bgp_node_get_bgp_path_info(rn
);
2069 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2072 bgp_path_info_path_with_addpath_rx_str(
2075 if (pi
== new_select
) {
2078 "%s: %s is the bestpath, add to the multipath list",
2080 bgp_mp_list_add(&mp_list
, pi
);
2084 if (BGP_PATH_HOLDDOWN(pi
))
2087 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2088 && !CHECK_FLAG(pi
->peer
->sflags
,
2089 PEER_STATUS_NSF_WAIT
))
2090 if (pi
->peer
->status
!= Established
)
2093 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2096 "%s: %s has the same nexthop as the bestpath, skip it",
2101 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2102 mpath_cfg
, debug
, pfx_buf
, afi
, safi
);
2107 "%s: %s is equivalent to the bestpath, add to the multipath list",
2109 bgp_mp_list_add(&mp_list
, pi
);
2114 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2116 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2117 bgp_mp_list_clear(&mp_list
);
2119 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2121 result
->old
= old_select
;
2122 result
->new = new_select
;
2128 * A new route/change in bestpath of an existing route. Evaluate the path
2129 * for advertisement to the subgroup.
2131 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2132 struct bgp_path_info
*selected
,
2133 struct bgp_node
*rn
,
2134 uint32_t addpath_tx_id
)
2137 struct peer
*onlypeer
;
2143 afi
= SUBGRP_AFI(subgrp
);
2144 safi
= SUBGRP_SAFI(subgrp
);
2145 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2148 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2149 char buf_prefix
[PREFIX_STRLEN
];
2150 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2151 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2155 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2156 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2157 PEER_STATUS_ORF_WAIT_REFRESH
))
2160 memset(&attr
, 0, sizeof(struct attr
));
2161 /* It's initialized in bgp_announce_check() */
2163 /* Announcement to the subgroup. If the route is filtered withdraw it.
2166 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2167 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2169 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2173 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2175 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2182 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2183 * This is called at the end of route processing.
2185 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2187 struct bgp_path_info
*pi
;
2189 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2190 if (BGP_PATH_HOLDDOWN(pi
))
2192 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2193 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2198 * Has the route changed from the RIB's perspective? This is invoked only
2199 * if the route selection returns the same best route as earlier - to
2200 * determine if we need to update zebra or not.
2202 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2203 struct bgp_path_info
*selected
)
2205 struct bgp_path_info
*mpinfo
;
2207 /* If this is multipath, check all selected paths for any nexthop
2208 * change or attribute change. Some attribute changes (e.g., community)
2209 * aren't of relevance to the RIB, but we'll update zebra to ensure
2210 * we handle the case of BGP nexthop change. This is the behavior
2211 * when the best path has an attribute change anyway.
2213 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2214 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2218 * If this is multipath, check all selected paths for any nexthop change
2220 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2221 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2222 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2223 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2227 /* Nothing has changed from the RIB's perspective. */
2231 struct bgp_process_queue
{
2233 STAILQ_HEAD(, bgp_node
) pqueue
;
2234 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2236 unsigned int queued
;
2240 * old_select = The old best path
2241 * new_select = the new best path
2243 * if (!old_select && new_select)
2244 * We are sending new information on.
2246 * if (old_select && new_select) {
2247 * if (new_select != old_select)
2248 * We have a new best path send a change
2250 * We've received a update with new attributes that needs
2254 * if (old_select && !new_select)
2255 * We have no eligible route that we can announce or the rn
2258 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2259 afi_t afi
, safi_t safi
)
2261 struct bgp_path_info
*new_select
;
2262 struct bgp_path_info
*old_select
;
2263 struct bgp_path_info_pair old_and_new
;
2264 char pfx_buf
[PREFIX2STR_BUFFER
];
2267 /* Is it end of initial update? (after startup) */
2269 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2270 sizeof(bgp
->update_delay_zebra_resume_time
));
2272 bgp
->main_zebra_update_hold
= 0;
2273 FOREACH_AFI_SAFI (afi
, safi
) {
2274 if (bgp_fibupd_safi(safi
))
2275 bgp_zebra_announce_table(bgp
, afi
, safi
);
2277 bgp
->main_peers_update_hold
= 0;
2279 bgp_start_routeadv(bgp
);
2283 struct prefix
*p
= &rn
->p
;
2285 debug
= bgp_debug_bestpath(&rn
->p
);
2287 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2288 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2289 afi2str(afi
), safi2str(safi
));
2292 /* Best path selection. */
2293 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2295 old_select
= old_and_new
.old
;
2296 new_select
= old_and_new
.new;
2298 /* Do we need to allocate or free labels?
2299 * Right now, since we only deal with per-prefix labels, it is not
2300 * necessary to do this upon changes to best path. Exceptions:
2301 * - label index has changed -> recalculate resulting label
2302 * - path_info sub_type changed -> switch to/from implicit-null
2303 * - no valid label (due to removed static label binding) -> get new one
2305 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2308 || bgp_label_index_differs(new_select
, old_select
)
2309 || new_select
->sub_type
!= old_select
->sub_type
2310 || !bgp_is_valid_label(&rn
->local_label
)) {
2311 /* Enforced penultimate hop popping:
2312 * implicit-null for local routes, aggregate
2313 * and redistributed routes
2315 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2316 || new_select
->sub_type
2317 == BGP_ROUTE_AGGREGATE
2318 || new_select
->sub_type
2319 == BGP_ROUTE_REDISTRIBUTE
) {
2322 BGP_NODE_REGISTERED_FOR_LABEL
))
2323 bgp_unregister_for_label(rn
);
2324 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2326 bgp_set_valid_label(&rn
->local_label
);
2328 bgp_register_for_label(rn
, new_select
);
2330 } else if (CHECK_FLAG(rn
->flags
,
2331 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2332 bgp_unregister_for_label(rn
);
2334 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2335 bgp_unregister_for_label(rn
);
2339 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2341 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2342 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2343 old_select
, new_select
);
2346 /* If best route remains the same and this is not due to user-initiated
2347 * clear, see exactly what needs to be done.
2349 if (old_select
&& old_select
== new_select
2350 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2351 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2352 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2353 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2355 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2356 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2358 if (bgp_fibupd_safi(safi
)
2359 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2361 if (new_select
->type
== ZEBRA_ROUTE_BGP
2362 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2363 || new_select
->sub_type
2364 == BGP_ROUTE_IMPORTED
))
2366 bgp_zebra_announce(rn
, p
, old_select
,
2370 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2371 bgp_zebra_clear_route_change_flags(rn
);
2373 /* If there is a change of interest to peers, reannounce the
2375 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2376 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2377 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2379 /* unicast routes must also be annouced to
2380 * labeled-unicast update-groups */
2381 if (safi
== SAFI_UNICAST
)
2382 group_announce_route(bgp
, afi
,
2383 SAFI_LABELED_UNICAST
, rn
,
2386 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2387 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2390 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2394 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2396 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2398 /* bestpath has changed; bump version */
2399 if (old_select
|| new_select
) {
2400 bgp_bump_version(rn
);
2402 if (!bgp
->t_rmap_def_originate_eval
) {
2406 update_group_refresh_default_originate_route_map
,
2407 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2408 &bgp
->t_rmap_def_originate_eval
);
2413 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2416 zlog_debug("%s: setting SELECTED flag", __func__
);
2417 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2418 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2419 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2423 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2424 if (old_select
!= new_select
) {
2426 vnc_import_bgp_exterior_del_route(bgp
, p
,
2428 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2431 vnc_import_bgp_exterior_add_route(bgp
, p
,
2433 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2439 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2441 /* unicast routes must also be annouced to labeled-unicast update-groups
2443 if (safi
== SAFI_UNICAST
)
2444 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2448 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2449 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2450 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2451 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2452 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2453 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2455 /* if this is an evpn imported type-5 prefix,
2456 * we need to withdraw the route first to clear
2457 * the nh neigh and the RMAC entry.
2460 is_route_parent_evpn(old_select
))
2461 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2463 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2465 /* Withdraw the route from the kernel. */
2466 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2467 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2468 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2469 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2471 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2475 /* advertise/withdraw type-5 routes */
2476 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2477 if (advertise_type5_routes(bgp
, afi
) &&
2479 is_route_injectable_into_evpn(new_select
)) {
2481 /* apply the route-map */
2482 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2485 ret
= route_map_apply(
2486 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2487 &rn
->p
, RMAP_BGP
, new_select
);
2488 if (ret
== RMAP_MATCH
)
2489 bgp_evpn_advertise_type5_route(
2490 bgp
, &rn
->p
, new_select
->attr
,
2493 bgp_evpn_withdraw_type5_route(
2494 bgp
, &rn
->p
, afi
, safi
);
2496 bgp_evpn_advertise_type5_route(bgp
,
2502 } else if (advertise_type5_routes(bgp
, afi
) &&
2504 is_route_injectable_into_evpn(old_select
))
2505 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2508 /* Clear any route change flags. */
2509 bgp_zebra_clear_route_change_flags(rn
);
2511 /* Reap old select bgp_path_info, if it has been removed */
2512 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2513 bgp_path_info_reap(rn
, old_select
);
2515 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2519 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2521 struct bgp_process_queue
*pqnode
= data
;
2522 struct bgp
*bgp
= pqnode
->bgp
;
2523 struct bgp_table
*table
;
2524 struct bgp_node
*rn
;
2527 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2528 bgp_process_main_one(bgp
, NULL
, 0, 0);
2529 /* should always have dedicated wq call */
2530 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2534 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2535 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2536 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2537 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2538 table
= bgp_node_table(rn
);
2539 /* note, new RNs may be added as part of processing */
2540 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2542 bgp_unlock_node(rn
);
2543 bgp_table_unlock(table
);
2549 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2551 struct bgp_process_queue
*pqnode
= data
;
2553 bgp_unlock(pqnode
->bgp
);
2555 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2558 void bgp_process_queue_init(void)
2560 if (!bm
->process_main_queue
)
2561 bm
->process_main_queue
=
2562 work_queue_new(bm
->master
, "process_main_queue");
2564 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2565 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2566 bm
->process_main_queue
->spec
.max_retries
= 0;
2567 bm
->process_main_queue
->spec
.hold
= 50;
2568 /* Use a higher yield value of 50ms for main queue processing */
2569 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2572 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2574 struct bgp_process_queue
*pqnode
;
2576 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2577 sizeof(struct bgp_process_queue
));
2579 /* unlocked in bgp_processq_del */
2580 pqnode
->bgp
= bgp_lock(bgp
);
2581 STAILQ_INIT(&pqnode
->pqueue
);
2586 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2588 #define ARBITRARY_PROCESS_QLEN 10000
2589 struct work_queue
*wq
= bm
->process_main_queue
;
2590 struct bgp_process_queue
*pqnode
;
2591 int pqnode_reuse
= 0;
2593 /* already scheduled for processing? */
2594 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2600 /* Add route nodes to an existing work queue item until reaching the
2601 limit only if is from the same BGP view and it's not an EOIU marker
2603 if (work_queue_item_count(wq
)) {
2604 struct work_queue_item
*item
= work_queue_last_item(wq
);
2605 pqnode
= item
->data
;
2607 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2608 || pqnode
->bgp
!= bgp
2609 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2610 pqnode
= bgp_processq_alloc(bgp
);
2614 pqnode
= bgp_processq_alloc(bgp
);
2615 /* all unlocked in bgp_process_wq */
2616 bgp_table_lock(bgp_node_table(rn
));
2618 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2621 /* can't be enqueued twice */
2622 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2623 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2627 work_queue_add(wq
, pqnode
);
2632 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2634 struct bgp_process_queue
*pqnode
;
2636 if (bm
->process_main_queue
== NULL
)
2639 pqnode
= bgp_processq_alloc(bgp
);
2641 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2642 work_queue_add(bm
->process_main_queue
, pqnode
);
2645 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2649 peer
= THREAD_ARG(thread
);
2650 peer
->t_pmax_restart
= NULL
;
2652 if (bgp_debug_neighbor_events(peer
))
2654 "%s Maximum-prefix restart timer expired, restore peering",
2657 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2658 zlog_debug("%s: %s peer_clear failed",
2659 __PRETTY_FUNCTION__
, peer
->host
);
2664 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2668 iana_safi_t pkt_safi
;
2670 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2673 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2674 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2675 PEER_STATUS_PREFIX_LIMIT
)
2680 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2681 " exceed, limit %" PRIu32
,
2682 afi_safi_print(afi
, safi
), peer
->host
,
2683 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2684 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2686 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2687 PEER_FLAG_MAX_PREFIX_WARNING
))
2690 /* Convert AFI, SAFI to values for packet. */
2691 pkt_afi
= afi_int2iana(afi
);
2692 pkt_safi
= safi_int2iana(safi
);
2696 ndata
[0] = (pkt_afi
>> 8);
2698 ndata
[2] = pkt_safi
;
2699 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2700 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2701 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2702 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2704 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2705 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2706 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2710 /* Dynamic peers will just close their connection. */
2711 if (peer_dynamic_neighbor(peer
))
2714 /* restart timer start */
2715 if (peer
->pmax_restart
[afi
][safi
]) {
2716 peer
->v_pmax_restart
=
2717 peer
->pmax_restart
[afi
][safi
] * 60;
2719 if (bgp_debug_neighbor_events(peer
))
2721 "%s Maximum-prefix restart timer started for %d secs",
2722 peer
->host
, peer
->v_pmax_restart
);
2724 BGP_TIMER_ON(peer
->t_pmax_restart
,
2725 bgp_maximum_prefix_restart_timer
,
2726 peer
->v_pmax_restart
);
2731 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2732 PEER_STATUS_PREFIX_LIMIT
);
2734 if (peer
->pcount
[afi
][safi
]
2735 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2736 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2737 PEER_STATUS_PREFIX_THRESHOLD
)
2742 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
2744 afi_safi_print(afi
, safi
), peer
->host
,
2745 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2746 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2747 PEER_STATUS_PREFIX_THRESHOLD
);
2749 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2750 PEER_STATUS_PREFIX_THRESHOLD
);
2754 /* Unconditionally remove the route from the RIB, without taking
2755 * damping into consideration (eg, because the session went down)
2757 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2758 struct peer
*peer
, afi_t afi
, safi_t safi
)
2760 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2762 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2763 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2765 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2768 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2769 struct peer
*peer
, afi_t afi
, safi_t safi
,
2770 struct prefix_rd
*prd
)
2772 /* apply dampening, if result is suppressed, we'll be retaining
2773 * the bgp_path_info in the RIB for historical reference.
2775 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2776 && peer
->sort
== BGP_PEER_EBGP
)
2777 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2778 == BGP_DAMP_SUPPRESSED
) {
2779 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2785 if (safi
== SAFI_MPLS_VPN
) {
2786 struct bgp_node
*prn
= NULL
;
2787 struct bgp_table
*table
= NULL
;
2789 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2790 (struct prefix
*)prd
);
2791 if (bgp_node_has_bgp_path_info_data(prn
)) {
2792 table
= bgp_node_get_bgp_table_info(prn
);
2794 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2795 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2797 bgp_unlock_node(prn
);
2799 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2800 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2802 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2803 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2809 /* If this is an EVPN route, process for un-import. */
2810 if (safi
== SAFI_EVPN
)
2811 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2813 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2816 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2817 struct peer
*peer
, struct attr
*attr
,
2818 struct bgp_node
*rn
)
2820 struct bgp_path_info
*new;
2822 /* Make new BGP info. */
2823 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2825 new->instance
= instance
;
2826 new->sub_type
= sub_type
;
2829 new->uptime
= bgp_clock();
2834 static void overlay_index_update(struct attr
*attr
,
2835 struct eth_segment_id
*eth_s_id
,
2836 union gw_addr
*gw_ip
)
2841 if (eth_s_id
== NULL
) {
2842 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2843 sizeof(struct eth_segment_id
));
2845 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2846 sizeof(struct eth_segment_id
));
2848 if (gw_ip
== NULL
) {
2849 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2851 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2852 sizeof(union gw_addr
));
2856 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2857 struct eth_segment_id
*eth_s_id
,
2858 union gw_addr
*gw_ip
)
2860 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2861 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2863 struct eth_segment_id esi
;
2867 if (afi
!= AFI_L2VPN
)
2870 memset(&temp
, 0, sizeof(temp
));
2871 path_eth_s_id
= &temp
.esi
;
2872 path_gw_ip
= &temp
.ip
;
2874 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2877 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2878 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2881 if (gw_ip
== NULL
) {
2882 memset(&temp
, 0, sizeof(temp
));
2883 path_gw_ip_remote
= &temp
.ip
;
2885 path_gw_ip_remote
= gw_ip
;
2887 if (eth_s_id
== NULL
) {
2888 memset(&temp
, 0, sizeof(temp
));
2889 path_eth_s_id_remote
= &temp
.esi
;
2891 path_eth_s_id_remote
= eth_s_id
;
2893 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2896 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2897 sizeof(struct eth_segment_id
));
2900 /* Check if received nexthop is valid or not. */
2901 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2906 /* Only validated for unicast and multicast currently. */
2907 /* Also valid for EVPN where the nexthop is an IP address. */
2908 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2911 /* If NEXT_HOP is present, validate it. */
2912 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2913 if (attr
->nexthop
.s_addr
== 0
2914 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2915 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2919 /* If MP_NEXTHOP is present, validate it. */
2920 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2921 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2922 * it is not an IPv6 link-local address.
2924 if (attr
->mp_nexthop_len
) {
2925 switch (attr
->mp_nexthop_len
) {
2926 case BGP_ATTR_NHLEN_IPV4
:
2927 case BGP_ATTR_NHLEN_VPNV4
:
2928 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2929 || IPV4_CLASS_DE(ntohl(
2930 attr
->mp_nexthop_global_in
.s_addr
))
2931 || bgp_nexthop_self(bgp
,
2932 attr
->mp_nexthop_global_in
));
2935 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2936 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2937 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2938 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2939 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2940 || IN6_IS_ADDR_MULTICAST(
2941 &attr
->mp_nexthop_global
));
2953 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2954 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2955 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2956 uint32_t num_labels
, int soft_reconfig
,
2957 struct bgp_route_evpn
*evpn
)
2960 int aspath_loop_count
= 0;
2961 struct bgp_node
*rn
;
2963 struct attr new_attr
;
2964 struct attr
*attr_new
;
2965 struct bgp_path_info
*pi
;
2966 struct bgp_path_info
*new;
2967 struct bgp_path_info_extra
*extra
;
2969 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2971 int do_loop_check
= 1;
2972 int has_valid_label
= 0;
2974 int vnc_implicit_withdraw
= 0;
2978 memset(&new_attr
, 0, sizeof(struct attr
));
2979 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2980 new_attr
.label
= MPLS_INVALID_LABEL
;
2983 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2984 /* TODO: Check to see if we can get rid of "is_valid_label" */
2985 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2986 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2988 has_valid_label
= bgp_is_valid_label(label
);
2990 /* When peer's soft reconfiguration enabled. Record input packet in
2993 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2994 && peer
!= bgp
->peer_self
)
2995 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2997 /* Check previously received route. */
2998 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
2999 if (pi
->peer
== peer
&& pi
->type
== type
3000 && pi
->sub_type
== sub_type
3001 && pi
->addpath_rx_id
== addpath_id
)
3004 /* AS path local-as loop check. */
3005 if (peer
->change_local_as
) {
3006 if (peer
->allowas_in
[afi
][safi
])
3007 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3008 else if (!CHECK_FLAG(peer
->flags
,
3009 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3010 aspath_loop_count
= 1;
3012 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3013 > aspath_loop_count
) {
3014 reason
= "as-path contains our own AS;";
3019 /* If the peer is configured for "allowas-in origin" and the last ASN in
3021 * as-path is our ASN then we do not need to call aspath_loop_check
3023 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3024 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3027 /* AS path loop check. */
3028 if (do_loop_check
) {
3029 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3030 > peer
->allowas_in
[afi
][safi
]
3031 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3032 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3033 > peer
->allowas_in
[afi
][safi
])) {
3034 reason
= "as-path contains our own AS;";
3039 /* Route reflector originator ID check. */
3040 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3041 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3042 reason
= "originator is us;";
3046 /* Route reflector cluster ID check. */
3047 if (bgp_cluster_filter(peer
, attr
)) {
3048 reason
= "reflected from the same cluster;";
3052 /* Apply incoming filter. */
3053 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3058 bgp_attr_dup(&new_attr
, attr
);
3060 /* Apply incoming route-map.
3061 * NB: new_attr may now contain newly allocated values from route-map
3063 * commands, so we need bgp_attr_flush in the error paths, until we
3065 * the attr (which takes over the memory references) */
3066 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3068 reason
= "route-map;";
3069 bgp_attr_flush(&new_attr
);
3073 if (peer
->sort
== BGP_PEER_EBGP
) {
3075 /* If we receive the graceful-shutdown community from an eBGP
3076 * peer we must lower local-preference */
3077 if (new_attr
.community
3078 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3079 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3080 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3082 /* If graceful-shutdown is configured then add the GSHUT
3083 * community to all paths received from eBGP peers */
3084 } else if (bgp_flag_check(peer
->bgp
,
3085 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3086 bgp_attr_add_gshut_community(&new_attr
);
3090 /* next hop check. */
3091 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3092 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3093 reason
= "martian or self next-hop;";
3094 bgp_attr_flush(&new_attr
);
3098 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3099 reason
= "self mac;";
3103 attr_new
= bgp_attr_intern(&new_attr
);
3105 /* If the update is implicit withdraw. */
3107 pi
->uptime
= bgp_clock();
3108 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3110 /* Same attribute comes in. */
3111 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3112 && attrhash_cmp(pi
->attr
, attr_new
)
3113 && (!has_valid_label
3114 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3115 num_labels
* sizeof(mpls_label_t
))
3117 && (overlay_index_equal(
3118 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3119 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3120 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3121 BGP_CONFIG_DAMPENING
)
3122 && peer
->sort
== BGP_PEER_EBGP
3123 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3124 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3125 bgp_debug_rdpfxpath2str(
3126 afi
, safi
, prd
, p
, label
,
3127 num_labels
, addpath_id
? 1 : 0,
3128 addpath_id
, pfx_buf
,
3130 zlog_debug("%s rcvd %s", peer
->host
,
3134 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3135 != BGP_DAMP_SUPPRESSED
) {
3136 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3138 bgp_process(bgp
, rn
, afi
, safi
);
3140 } else /* Duplicate - odd */
3142 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3143 if (!peer
->rcvd_attr_printed
) {
3145 "%s rcvd UPDATE w/ attr: %s",
3147 peer
->rcvd_attr_str
);
3148 peer
->rcvd_attr_printed
= 1;
3151 bgp_debug_rdpfxpath2str(
3152 afi
, safi
, prd
, p
, label
,
3153 num_labels
, addpath_id
? 1 : 0,
3154 addpath_id
, pfx_buf
,
3157 "%s rcvd %s...duplicate ignored",
3158 peer
->host
, pfx_buf
);
3161 /* graceful restart STALE flag unset. */
3162 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3163 bgp_path_info_unset_flag(
3164 rn
, pi
, BGP_PATH_STALE
);
3165 bgp_process(bgp
, rn
, afi
, safi
);
3169 bgp_unlock_node(rn
);
3170 bgp_attr_unintern(&attr_new
);
3175 /* Withdraw/Announce before we fully processed the withdraw */
3176 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3177 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3178 bgp_debug_rdpfxpath2str(
3179 afi
, safi
, prd
, p
, label
, num_labels
,
3180 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3183 "%s rcvd %s, flapped quicker than processing",
3184 peer
->host
, pfx_buf
);
3187 bgp_path_info_restore(rn
, pi
);
3190 /* Received Logging. */
3191 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3192 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3193 num_labels
, addpath_id
? 1 : 0,
3194 addpath_id
, pfx_buf
,
3196 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3199 /* graceful restart STALE flag unset. */
3200 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3201 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3203 /* The attribute is changed. */
3204 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3206 /* implicit withdraw, decrement aggregate and pcount here.
3207 * only if update is accepted, they'll increment below.
3209 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3211 /* Update bgp route dampening information. */
3212 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3213 && peer
->sort
== BGP_PEER_EBGP
) {
3214 /* This is implicit withdraw so we should update
3217 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3218 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3221 if (safi
== SAFI_MPLS_VPN
) {
3222 struct bgp_node
*prn
= NULL
;
3223 struct bgp_table
*table
= NULL
;
3225 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3226 (struct prefix
*)prd
);
3227 if (bgp_node_has_bgp_path_info_data(prn
)) {
3228 table
= bgp_node_get_bgp_table_info(prn
);
3230 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3231 bgp
, prd
, table
, p
, pi
);
3233 bgp_unlock_node(prn
);
3235 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3236 && (safi
== SAFI_UNICAST
)) {
3237 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3239 * Implicit withdraw case.
3241 ++vnc_implicit_withdraw
;
3242 vnc_import_bgp_del_route(bgp
, p
, pi
);
3243 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3248 /* Special handling for EVPN update of an existing route. If the
3249 * extended community attribute has changed, we need to
3251 * the route using its existing extended community. It will be
3252 * subsequently processed for import with the new extended
3255 if (safi
== SAFI_EVPN
&& !same_attr
) {
3257 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3259 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3262 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3263 attr_new
->ecommunity
);
3265 if (bgp_debug_update(peer
, p
, NULL
, 1))
3267 "Change in EXT-COMM, existing %s new %s",
3269 pi
->attr
->ecommunity
),
3271 attr_new
->ecommunity
));
3272 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3278 /* Update to new attribute. */
3279 bgp_attr_unintern(&pi
->attr
);
3280 pi
->attr
= attr_new
;
3282 /* Update MPLS label */
3283 if (has_valid_label
) {
3284 extra
= bgp_path_info_extra_get(pi
);
3285 if (extra
->label
!= label
) {
3286 memcpy(&extra
->label
, label
,
3287 num_labels
* sizeof(mpls_label_t
));
3288 extra
->num_labels
= num_labels
;
3290 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3291 bgp_set_valid_label(&extra
->label
[0]);
3295 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3296 && (safi
== SAFI_UNICAST
)) {
3297 if (vnc_implicit_withdraw
) {
3299 * Add back the route with its new attributes
3301 * The route is still selected, until the route
3303 * queued by bgp_process actually runs. We have
3305 * update to the VNC side immediately to avoid
3307 * configuration changes (e.g., route-map
3309 * trigger re-importation of the entire RIB.
3311 vnc_import_bgp_add_route(bgp
, p
, pi
);
3312 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3316 /* Update Overlay Index */
3317 if (afi
== AFI_L2VPN
) {
3318 overlay_index_update(
3319 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3320 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3323 /* Update bgp route dampening information. */
3324 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3325 && peer
->sort
== BGP_PEER_EBGP
) {
3326 /* Now we do normal update dampening. */
3327 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3328 if (ret
== BGP_DAMP_SUPPRESSED
) {
3329 bgp_unlock_node(rn
);
3334 /* Nexthop reachability check - for unicast and
3335 * labeled-unicast.. */
3336 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3337 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3338 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3339 && !CHECK_FLAG(peer
->flags
,
3340 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3342 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3347 struct bgp
*bgp_nexthop
= bgp
;
3349 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3350 bgp_nexthop
= pi
->extra
->bgp_orig
;
3352 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3354 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3355 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3357 if (BGP_DEBUG(nht
, NHT
)) {
3358 char buf1
[INET6_ADDRSTRLEN
];
3360 (const void *)&attr_new
3362 buf1
, INET6_ADDRSTRLEN
);
3363 zlog_debug("%s(%s): NH unresolved",
3364 __FUNCTION__
, buf1
);
3366 bgp_path_info_unset_flag(rn
, pi
,
3370 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3373 if (safi
== SAFI_MPLS_VPN
) {
3374 struct bgp_node
*prn
= NULL
;
3375 struct bgp_table
*table
= NULL
;
3377 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3378 (struct prefix
*)prd
);
3379 if (bgp_node_has_bgp_path_info_data(prn
)) {
3380 table
= bgp_node_get_bgp_table_info(prn
);
3382 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3383 bgp
, prd
, table
, p
, pi
);
3385 bgp_unlock_node(prn
);
3389 /* If this is an EVPN route and some attribute has changed,
3391 * route for import. If the extended community has changed, we
3393 * have done the un-import earlier and the import would result
3395 * route getting injected into appropriate L2 VNIs. If it is
3397 * some other attribute change, the import will result in
3399 * the attributes for the route in the VNI(s).
3401 if (safi
== SAFI_EVPN
&& !same_attr
)
3402 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3404 /* Process change. */
3405 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3407 bgp_process(bgp
, rn
, afi
, safi
);
3408 bgp_unlock_node(rn
);
3410 if (SAFI_UNICAST
== safi
3411 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3412 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3414 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3416 if ((SAFI_MPLS_VPN
== safi
)
3417 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3419 vpn_leak_to_vrf_update(bgp
, pi
);
3423 if (SAFI_MPLS_VPN
== safi
) {
3424 mpls_label_t label_decoded
= decode_label(label
);
3426 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3427 type
, sub_type
, &label_decoded
);
3429 if (SAFI_ENCAP
== safi
) {
3430 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3431 type
, sub_type
, NULL
);
3436 } // End of implicit withdraw
3438 /* Received Logging. */
3439 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3440 if (!peer
->rcvd_attr_printed
) {
3441 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3442 peer
->rcvd_attr_str
);
3443 peer
->rcvd_attr_printed
= 1;
3446 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3447 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3449 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3452 /* Make new BGP info. */
3453 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3455 /* Update MPLS label */
3456 if (has_valid_label
) {
3457 extra
= bgp_path_info_extra_get(new);
3458 if (extra
->label
!= label
) {
3459 memcpy(&extra
->label
, label
,
3460 num_labels
* sizeof(mpls_label_t
));
3461 extra
->num_labels
= num_labels
;
3463 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3464 bgp_set_valid_label(&extra
->label
[0]);
3467 /* Update Overlay Index */
3468 if (afi
== AFI_L2VPN
) {
3469 overlay_index_update(new->attr
,
3470 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3471 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3473 /* Nexthop reachability check. */
3474 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3475 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3476 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3477 && !CHECK_FLAG(peer
->flags
,
3478 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3479 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3484 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3485 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3486 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3488 if (BGP_DEBUG(nht
, NHT
)) {
3489 char buf1
[INET6_ADDRSTRLEN
];
3491 (const void *)&attr_new
->nexthop
,
3492 buf1
, INET6_ADDRSTRLEN
);
3493 zlog_debug("%s(%s): NH unresolved",
3494 __FUNCTION__
, buf1
);
3496 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3499 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3502 new->addpath_rx_id
= addpath_id
;
3504 /* Increment prefix */
3505 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3507 /* Register new BGP information. */
3508 bgp_path_info_add(rn
, new);
3510 /* route_node_get lock */
3511 bgp_unlock_node(rn
);
3514 if (safi
== SAFI_MPLS_VPN
) {
3515 struct bgp_node
*prn
= NULL
;
3516 struct bgp_table
*table
= NULL
;
3518 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3519 if (bgp_node_has_bgp_path_info_data(prn
)) {
3520 table
= bgp_node_get_bgp_table_info(prn
);
3522 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3523 bgp
, prd
, table
, p
, new);
3525 bgp_unlock_node(prn
);
3529 /* If maximum prefix count is configured and current prefix
3531 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3534 /* If this is an EVPN route, process for import. */
3535 if (safi
== SAFI_EVPN
)
3536 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3538 /* Process change. */
3539 bgp_process(bgp
, rn
, afi
, safi
);
3541 if (SAFI_UNICAST
== safi
3542 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3543 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3544 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3546 if ((SAFI_MPLS_VPN
== safi
)
3547 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3549 vpn_leak_to_vrf_update(bgp
, new);
3552 if (SAFI_MPLS_VPN
== safi
) {
3553 mpls_label_t label_decoded
= decode_label(label
);
3555 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3556 sub_type
, &label_decoded
);
3558 if (SAFI_ENCAP
== safi
) {
3559 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3566 /* This BGP update is filtered. Log the reason then update BGP
3569 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3570 if (!peer
->rcvd_attr_printed
) {
3571 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3572 peer
->rcvd_attr_str
);
3573 peer
->rcvd_attr_printed
= 1;
3576 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3577 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3579 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3580 peer
->host
, pfx_buf
, reason
);
3584 /* If this is an EVPN route, un-import it as it is now filtered.
3586 if (safi
== SAFI_EVPN
)
3587 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3589 if (SAFI_UNICAST
== safi
3590 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3591 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3593 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3595 if ((SAFI_MPLS_VPN
== safi
)
3596 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3598 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3601 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3604 bgp_unlock_node(rn
);
3608 * Filtered update is treated as an implicit withdrawal (see
3610 * a few lines above)
3612 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3613 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3621 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3622 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3623 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3624 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3627 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3628 struct bgp_node
*rn
;
3629 struct bgp_path_info
*pi
;
3632 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3633 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3641 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3643 /* If peer is soft reconfiguration enabled. Record input packet for
3644 * further calculation.
3646 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3647 * routes that are filtered. This tanks out Quagga RS pretty badly due
3649 * the iteration over all RS clients.
3650 * Since we need to remove the entry from adj_in anyway, do that first
3652 * if there was no entry, we don't need to do anything more.
3654 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3655 && peer
!= bgp
->peer_self
)
3656 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3657 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3658 bgp_debug_rdpfxpath2str(
3659 afi
, safi
, prd
, p
, label
, num_labels
,
3660 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3663 "%s withdrawing route %s not in adj-in",
3664 peer
->host
, pfx_buf
);
3666 bgp_unlock_node(rn
);
3670 /* Lookup withdrawn route. */
3671 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3672 if (pi
->peer
== peer
&& pi
->type
== type
3673 && pi
->sub_type
== sub_type
3674 && pi
->addpath_rx_id
== addpath_id
)
3678 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3679 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3680 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3682 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3686 /* Withdraw specified route from routing table. */
3687 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3688 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3689 if (SAFI_UNICAST
== safi
3690 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3691 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3692 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3694 if ((SAFI_MPLS_VPN
== safi
)
3695 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3697 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3699 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3700 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3701 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3703 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3706 /* Unlock bgp_node_get() lock. */
3707 bgp_unlock_node(rn
);
3712 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3715 struct update_subgroup
*subgrp
;
3716 subgrp
= peer_subgroup(peer
, afi
, safi
);
3717 subgroup_default_originate(subgrp
, withdraw
);
3722 * bgp_stop_announce_route_timer
3724 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3726 if (!paf
->t_announce_route
)
3729 THREAD_TIMER_OFF(paf
->t_announce_route
);
3733 * bgp_announce_route_timer_expired
3735 * Callback that is invoked when the route announcement timer for a
3738 static int bgp_announce_route_timer_expired(struct thread
*t
)
3740 struct peer_af
*paf
;
3743 paf
= THREAD_ARG(t
);
3746 if (peer
->status
!= Established
)
3749 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3752 peer_af_announce_route(paf
, 1);
3757 * bgp_announce_route
3759 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3761 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3763 struct peer_af
*paf
;
3764 struct update_subgroup
*subgrp
;
3766 paf
= peer_af_find(peer
, afi
, safi
);
3769 subgrp
= PAF_SUBGRP(paf
);
3772 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3773 * or a refresh has already been triggered.
3775 if (!subgrp
|| paf
->t_announce_route
)
3779 * Start a timer to stagger/delay the announce. This serves
3780 * two purposes - announcement can potentially be combined for
3781 * multiple peers and the announcement doesn't happen in the
3784 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3785 (subgrp
->peer_count
== 1)
3786 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3787 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3788 &paf
->t_announce_route
);
3792 * Announce routes from all AF tables to a peer.
3794 * This should ONLY be called when there is a need to refresh the
3795 * routes to the peer based on a policy change for this peer alone
3796 * or a route refresh request received from the peer.
3797 * The operation will result in splitting the peer from its existing
3798 * subgroups and putting it in new subgroups.
3800 void bgp_announce_route_all(struct peer
*peer
)
3805 FOREACH_AFI_SAFI (afi
, safi
)
3806 bgp_announce_route(peer
, afi
, safi
);
3809 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3810 struct bgp_table
*table
,
3811 struct prefix_rd
*prd
)
3814 struct bgp_node
*rn
;
3815 struct bgp_adj_in
*ain
;
3818 table
= peer
->bgp
->rib
[afi
][safi
];
3820 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3821 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3822 if (ain
->peer
!= peer
)
3825 struct bgp_path_info
*pi
=
3826 bgp_node_get_bgp_path_info(rn
);
3827 uint32_t num_labels
= 0;
3828 mpls_label_t
*label_pnt
= NULL
;
3829 struct bgp_route_evpn evpn
;
3831 if (pi
&& pi
->extra
)
3832 num_labels
= pi
->extra
->num_labels
;
3834 label_pnt
= &pi
->extra
->label
[0];
3836 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3839 memset(&evpn
, 0, sizeof(evpn
));
3841 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3842 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3843 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3844 num_labels
, 1, &evpn
);
3847 bgp_unlock_node(rn
);
3853 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3855 struct bgp_node
*rn
;
3856 struct bgp_table
*table
;
3858 if (peer
->status
!= Established
)
3861 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3862 && (safi
!= SAFI_EVPN
))
3863 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3865 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3866 rn
= bgp_route_next(rn
)) {
3867 table
= bgp_node_get_bgp_table_info(rn
);
3868 if (table
!= NULL
) {
3869 struct prefix_rd prd
;
3871 prd
.family
= AF_UNSPEC
;
3873 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3875 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3882 struct bgp_clear_node_queue
{
3883 struct bgp_node
*rn
;
3886 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3888 struct bgp_clear_node_queue
*cnq
= data
;
3889 struct bgp_node
*rn
= cnq
->rn
;
3890 struct peer
*peer
= wq
->spec
.data
;
3891 struct bgp_path_info
*pi
;
3893 afi_t afi
= bgp_node_table(rn
)->afi
;
3894 safi_t safi
= bgp_node_table(rn
)->safi
;
3899 /* It is possible that we have multiple paths for a prefix from a peer
3900 * if that peer is using AddPath.
3902 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
3903 if (pi
->peer
!= peer
)
3906 /* graceful restart STALE flag set. */
3907 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3908 && peer
->nsf
[afi
][safi
]
3909 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3910 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3911 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3913 /* If this is an EVPN route, process for
3915 if (safi
== SAFI_EVPN
)
3916 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3918 /* Handle withdraw for VRF route-leaking and L3VPN */
3919 if (SAFI_UNICAST
== safi
3920 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3921 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3922 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3925 if (SAFI_MPLS_VPN
== safi
&&
3926 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3927 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3930 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3936 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3938 struct bgp_clear_node_queue
*cnq
= data
;
3939 struct bgp_node
*rn
= cnq
->rn
;
3940 struct bgp_table
*table
= bgp_node_table(rn
);
3942 bgp_unlock_node(rn
);
3943 bgp_table_unlock(table
);
3944 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3947 static void bgp_clear_node_complete(struct work_queue
*wq
)
3949 struct peer
*peer
= wq
->spec
.data
;
3951 /* Tickle FSM to start moving again */
3952 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3954 peer_unlock(peer
); /* bgp_clear_route */
3957 static void bgp_clear_node_queue_init(struct peer
*peer
)
3959 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3961 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3962 #undef CLEAR_QUEUE_NAME_LEN
3964 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3965 peer
->clear_node_queue
->spec
.hold
= 10;
3966 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3967 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3968 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3969 peer
->clear_node_queue
->spec
.max_retries
= 0;
3971 /* we only 'lock' this peer reference when the queue is actually active
3973 peer
->clear_node_queue
->spec
.data
= peer
;
3976 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3977 struct bgp_table
*table
)
3979 struct bgp_node
*rn
;
3980 int force
= bm
->process_main_queue
? 0 : 1;
3983 table
= peer
->bgp
->rib
[afi
][safi
];
3985 /* If still no table => afi/safi isn't configured at all or smth. */
3989 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3990 struct bgp_path_info
*pi
, *next
;
3991 struct bgp_adj_in
*ain
;
3992 struct bgp_adj_in
*ain_next
;
3994 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3995 * queued for every clearing peer, regardless of whether it is
3996 * relevant to the peer at hand.
3998 * Overview: There are 3 different indices which need to be
3999 * scrubbed, potentially, when a peer is removed:
4001 * 1 peer's routes visible via the RIB (ie accepted routes)
4002 * 2 peer's routes visible by the (optional) peer's adj-in index
4003 * 3 other routes visible by the peer's adj-out index
4005 * 3 there is no hurry in scrubbing, once the struct peer is
4006 * removed from bgp->peer, we could just GC such deleted peer's
4007 * adj-outs at our leisure.
4009 * 1 and 2 must be 'scrubbed' in some way, at least made
4010 * invisible via RIB index before peer session is allowed to be
4011 * brought back up. So one needs to know when such a 'search' is
4016 * - there'd be a single global queue or a single RIB walker
4017 * - rather than tracking which route_nodes still need to be
4018 * examined on a peer basis, we'd track which peers still
4021 * Given that our per-peer prefix-counts now should be reliable,
4022 * this may actually be achievable. It doesn't seem to be a huge
4023 * problem at this time,
4025 * It is possible that we have multiple paths for a prefix from
4027 * if that peer is using AddPath.
4031 ain_next
= ain
->next
;
4033 if (ain
->peer
== peer
) {
4034 bgp_adj_in_remove(rn
, ain
);
4035 bgp_unlock_node(rn
);
4041 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4043 if (pi
->peer
!= peer
)
4047 bgp_path_info_reap(rn
, pi
);
4049 struct bgp_clear_node_queue
*cnq
;
4051 /* both unlocked in bgp_clear_node_queue_del */
4052 bgp_table_lock(bgp_node_table(rn
));
4055 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4056 sizeof(struct bgp_clear_node_queue
));
4058 work_queue_add(peer
->clear_node_queue
, cnq
);
4066 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4068 struct bgp_node
*rn
;
4069 struct bgp_table
*table
;
4071 if (peer
->clear_node_queue
== NULL
)
4072 bgp_clear_node_queue_init(peer
);
4074 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4075 * Idle until it receives a Clearing_Completed event. This protects
4076 * against peers which flap faster than we can we clear, which could
4079 * a) race with routes from the new session being installed before
4080 * clear_route_node visits the node (to delete the route of that
4082 * b) resource exhaustion, clear_route_node likely leads to an entry
4083 * on the process_main queue. Fast-flapping could cause that queue
4087 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4088 * the unlock will happen upon work-queue completion; other wise, the
4089 * unlock happens at the end of this function.
4091 if (!peer
->clear_node_queue
->thread
)
4094 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4095 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4097 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4098 rn
= bgp_route_next(rn
)) {
4099 table
= bgp_node_get_bgp_table_info(rn
);
4103 bgp_clear_route_table(peer
, afi
, safi
, table
);
4106 /* unlock if no nodes got added to the clear-node-queue. */
4107 if (!peer
->clear_node_queue
->thread
)
4111 void bgp_clear_route_all(struct peer
*peer
)
4116 FOREACH_AFI_SAFI (afi
, safi
)
4117 bgp_clear_route(peer
, afi
, safi
);
4120 rfapiProcessPeerDown(peer
);
4124 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4126 struct bgp_table
*table
;
4127 struct bgp_node
*rn
;
4128 struct bgp_adj_in
*ain
;
4129 struct bgp_adj_in
*ain_next
;
4131 table
= peer
->bgp
->rib
[afi
][safi
];
4133 /* It is possible that we have multiple paths for a prefix from a peer
4134 * if that peer is using AddPath.
4136 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4140 ain_next
= ain
->next
;
4142 if (ain
->peer
== peer
) {
4143 bgp_adj_in_remove(rn
, ain
);
4144 bgp_unlock_node(rn
);
4152 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4154 struct bgp_node
*rn
;
4155 struct bgp_path_info
*pi
;
4156 struct bgp_table
*table
;
4158 if (safi
== SAFI_MPLS_VPN
) {
4159 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4160 rn
= bgp_route_next(rn
)) {
4161 struct bgp_node
*rm
;
4163 /* look for neighbor in tables */
4164 table
= bgp_node_get_bgp_table_info(rn
);
4168 for (rm
= bgp_table_top(table
); rm
;
4169 rm
= bgp_route_next(rm
))
4170 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4172 if (pi
->peer
!= peer
)
4174 if (!CHECK_FLAG(pi
->flags
,
4178 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4183 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4184 rn
= bgp_route_next(rn
))
4185 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4187 if (pi
->peer
!= peer
)
4189 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4191 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4197 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4199 if (peer
->sort
== BGP_PEER_EBGP
4200 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4201 || FILTER_LIST_OUT_NAME(filter
)
4202 || DISTRIBUTE_OUT_NAME(filter
)))
4207 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4209 if (peer
->sort
== BGP_PEER_EBGP
4210 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4211 || FILTER_LIST_IN_NAME(filter
)
4212 || DISTRIBUTE_IN_NAME(filter
)))
4217 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4220 struct bgp_node
*rn
;
4221 struct bgp_path_info
*pi
;
4222 struct bgp_path_info
*next
;
4224 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4225 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4228 /* Unimport EVPN routes from VRFs */
4229 if (safi
== SAFI_EVPN
)
4230 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4234 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4235 && pi
->type
== ZEBRA_ROUTE_BGP
4236 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4237 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4238 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4240 if (bgp_fibupd_safi(safi
))
4241 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4243 bgp_path_info_reap(rn
, pi
);
4248 /* Delete all kernel routes. */
4249 void bgp_cleanup_routes(struct bgp
*bgp
)
4252 struct bgp_node
*rn
;
4253 struct bgp_table
*table
;
4255 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4256 if (afi
== AFI_L2VPN
)
4258 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4261 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4263 if (afi
!= AFI_L2VPN
) {
4265 safi
= SAFI_MPLS_VPN
;
4266 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4267 rn
= bgp_route_next(rn
)) {
4268 table
= bgp_node_get_bgp_table_info(rn
);
4269 if (table
!= NULL
) {
4270 bgp_cleanup_table(bgp
, table
, safi
);
4271 bgp_table_finish(&table
);
4272 bgp_node_set_bgp_table_info(rn
, NULL
);
4273 bgp_unlock_node(rn
);
4277 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); 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
);
4282 bgp_table_finish(&table
);
4283 bgp_node_set_bgp_table_info(rn
, NULL
);
4284 bgp_unlock_node(rn
);
4289 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4290 rn
= bgp_route_next(rn
)) {
4291 table
= bgp_node_get_bgp_table_info(rn
);
4292 if (table
!= NULL
) {
4293 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4294 bgp_table_finish(&table
);
4295 bgp_node_set_bgp_table_info(rn
, NULL
);
4296 bgp_unlock_node(rn
);
4301 void bgp_reset(void)
4304 bgp_zclient_reset();
4305 access_list_reset();
4306 prefix_list_reset();
4309 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4311 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4312 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4313 PEER_CAP_ADDPATH_AF_TX_RCV
));
4316 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4318 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4319 struct bgp_nlri
*packet
)
4328 int addpath_encoded
;
4329 uint32_t addpath_id
;
4332 lim
= pnt
+ packet
->length
;
4334 safi
= packet
->safi
;
4336 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4338 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4339 syntactic validity. If the field is syntactically incorrect,
4340 then the Error Subcode is set to Invalid Network Field. */
4341 for (; pnt
< lim
; pnt
+= psize
) {
4342 /* Clear prefix structure. */
4343 memset(&p
, 0, sizeof(struct prefix
));
4345 if (addpath_encoded
) {
4347 /* When packet overflow occurs return immediately. */
4348 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4349 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4351 addpath_id
= ntohl(*((uint32_t *)pnt
));
4352 pnt
+= BGP_ADDPATH_ID_LEN
;
4355 /* Fetch prefix length. */
4356 p
.prefixlen
= *pnt
++;
4357 /* afi/safi validity already verified by caller,
4358 * bgp_update_receive */
4359 p
.family
= afi2family(afi
);
4361 /* Prefix length check. */
4362 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4365 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4366 peer
->host
, p
.prefixlen
, packet
->afi
);
4367 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4370 /* Packet size overflow check. */
4371 psize
= PSIZE(p
.prefixlen
);
4373 /* When packet overflow occur return immediately. */
4374 if (pnt
+ psize
> lim
) {
4377 "%s [Error] Update packet error (prefix length %d overflows packet)",
4378 peer
->host
, p
.prefixlen
);
4379 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4382 /* Defensive coding, double-check the psize fits in a struct
4384 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4387 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4388 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4389 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4392 /* Fetch prefix from NLRI packet. */
4393 memcpy(p
.u
.val
, pnt
, psize
);
4395 /* Check address. */
4396 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4397 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4398 /* From RFC4271 Section 6.3:
4400 * If a prefix in the NLRI field is semantically
4402 * (e.g., an unexpected multicast IP address),
4404 * be logged locally, and the prefix SHOULD be
4409 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4410 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4415 /* Check address. */
4416 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4417 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4422 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4424 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4429 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4434 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4436 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4443 /* Normal process. */
4445 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4446 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4447 NULL
, NULL
, 0, 0, NULL
);
4449 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4450 safi
, ZEBRA_ROUTE_BGP
,
4451 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4454 /* Do not send BGP notification twice when maximum-prefix count
4456 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4457 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4459 /* Address family configuration mismatch. */
4461 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4464 /* Packet length consistency check. */
4468 "%s [Error] Update packet error (prefix length mismatch with total length)",
4470 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4473 return BGP_NLRI_PARSE_OK
;
4476 static struct bgp_static
*bgp_static_new(void)
4478 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4481 static void bgp_static_free(struct bgp_static
*bgp_static
)
4483 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4484 route_map_counter_decrement(bgp_static
->rmap
.map
);
4486 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4487 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4490 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4491 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4493 struct bgp_node
*rn
;
4494 struct bgp_path_info
*pi
;
4495 struct bgp_path_info
*new;
4496 struct bgp_path_info rmap_path
;
4498 struct attr
*attr_new
;
4501 int vnc_implicit_withdraw
= 0;
4508 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4510 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4512 attr
.nexthop
= bgp_static
->igpnexthop
;
4513 attr
.med
= bgp_static
->igpmetric
;
4514 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4516 if (bgp_static
->atomic
)
4517 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4519 /* Store label index, if required. */
4520 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4521 attr
.label_index
= bgp_static
->label_index
;
4522 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4525 /* Apply route-map. */
4526 if (bgp_static
->rmap
.name
) {
4527 struct attr attr_tmp
= attr
;
4529 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4530 rmap_path
.peer
= bgp
->peer_self
;
4531 rmap_path
.attr
= &attr_tmp
;
4533 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4535 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4538 bgp
->peer_self
->rmap_type
= 0;
4540 if (ret
== RMAP_DENYMATCH
) {
4541 /* Free uninterned attribute. */
4542 bgp_attr_flush(&attr_tmp
);
4544 /* Unintern original. */
4545 aspath_unintern(&attr
.aspath
);
4546 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4550 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4551 bgp_attr_add_gshut_community(&attr_tmp
);
4553 attr_new
= bgp_attr_intern(&attr_tmp
);
4556 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4557 bgp_attr_add_gshut_community(&attr
);
4559 attr_new
= bgp_attr_intern(&attr
);
4562 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4563 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4564 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4568 if (attrhash_cmp(pi
->attr
, attr_new
)
4569 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4570 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4571 bgp_unlock_node(rn
);
4572 bgp_attr_unintern(&attr_new
);
4573 aspath_unintern(&attr
.aspath
);
4576 /* The attribute is changed. */
4577 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4579 /* Rewrite BGP route information. */
4580 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4581 bgp_path_info_restore(rn
, pi
);
4583 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4585 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4586 && (safi
== SAFI_UNICAST
)) {
4587 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4589 * Implicit withdraw case.
4590 * We have to do this before pi is
4593 ++vnc_implicit_withdraw
;
4594 vnc_import_bgp_del_route(bgp
, p
, pi
);
4595 vnc_import_bgp_exterior_del_route(
4600 bgp_attr_unintern(&pi
->attr
);
4601 pi
->attr
= attr_new
;
4602 pi
->uptime
= bgp_clock();
4604 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4605 && (safi
== SAFI_UNICAST
)) {
4606 if (vnc_implicit_withdraw
) {
4607 vnc_import_bgp_add_route(bgp
, p
, pi
);
4608 vnc_import_bgp_exterior_add_route(
4614 /* Nexthop reachability check. */
4615 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4616 && (safi
== SAFI_UNICAST
4617 || safi
== SAFI_LABELED_UNICAST
)) {
4619 struct bgp
*bgp_nexthop
= bgp
;
4621 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4622 bgp_nexthop
= pi
->extra
->bgp_orig
;
4624 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4626 bgp_path_info_set_flag(rn
, pi
,
4629 if (BGP_DEBUG(nht
, NHT
)) {
4630 char buf1
[INET6_ADDRSTRLEN
];
4631 inet_ntop(p
->family
,
4635 "%s(%s): Route not in table, not advertising",
4636 __FUNCTION__
, buf1
);
4638 bgp_path_info_unset_flag(
4639 rn
, pi
, BGP_PATH_VALID
);
4642 /* Delete the NHT structure if any, if we're
4644 * enabling/disabling import check. We
4645 * deregister the route
4646 * from NHT to avoid overloading NHT and the
4647 * process interaction
4649 bgp_unlink_nexthop(pi
);
4650 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4652 /* Process change. */
4653 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4654 bgp_process(bgp
, rn
, afi
, safi
);
4656 if (SAFI_UNICAST
== safi
4657 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4659 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4660 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4664 bgp_unlock_node(rn
);
4665 aspath_unintern(&attr
.aspath
);
4670 /* Make new BGP info. */
4671 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4673 /* Nexthop reachability check. */
4674 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4675 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4676 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4677 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4679 if (BGP_DEBUG(nht
, NHT
)) {
4680 char buf1
[INET6_ADDRSTRLEN
];
4681 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4684 "%s(%s): Route not in table, not advertising",
4685 __FUNCTION__
, buf1
);
4687 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4690 /* Delete the NHT structure if any, if we're toggling between
4691 * enabling/disabling import check. We deregister the route
4692 * from NHT to avoid overloading NHT and the process interaction
4694 bgp_unlink_nexthop(new);
4696 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4699 /* Aggregate address increment. */
4700 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4702 /* Register new BGP information. */
4703 bgp_path_info_add(rn
, new);
4705 /* route_node_get lock */
4706 bgp_unlock_node(rn
);
4708 /* Process change. */
4709 bgp_process(bgp
, rn
, afi
, safi
);
4711 if (SAFI_UNICAST
== safi
4712 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4713 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4714 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4717 /* Unintern original. */
4718 aspath_unintern(&attr
.aspath
);
4721 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4724 struct bgp_node
*rn
;
4725 struct bgp_path_info
*pi
;
4727 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4729 /* Check selected route and self inserted route. */
4730 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4731 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4732 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4735 /* Withdraw static BGP route from routing table. */
4737 if (SAFI_UNICAST
== safi
4738 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4739 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4740 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4742 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4743 bgp_unlink_nexthop(pi
);
4744 bgp_path_info_delete(rn
, pi
);
4745 bgp_process(bgp
, rn
, afi
, safi
);
4748 /* Unlock bgp_node_lookup. */
4749 bgp_unlock_node(rn
);
4753 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4755 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4756 afi_t afi
, safi_t safi
,
4757 struct prefix_rd
*prd
)
4759 struct bgp_node
*rn
;
4760 struct bgp_path_info
*pi
;
4762 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4764 /* Check selected route and self inserted route. */
4765 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4766 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4767 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4770 /* Withdraw static BGP route from routing table. */
4773 rfapiProcessWithdraw(
4774 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4775 1); /* Kill, since it is an administrative change */
4777 if (SAFI_MPLS_VPN
== safi
4778 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4779 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4781 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4782 bgp_path_info_delete(rn
, pi
);
4783 bgp_process(bgp
, rn
, afi
, safi
);
4786 /* Unlock bgp_node_lookup. */
4787 bgp_unlock_node(rn
);
4790 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4791 struct bgp_static
*bgp_static
, afi_t afi
,
4794 struct bgp_node
*rn
;
4795 struct bgp_path_info
*new;
4796 struct attr
*attr_new
;
4797 struct attr attr
= {0};
4798 struct bgp_path_info
*pi
;
4800 mpls_label_t label
= 0;
4802 uint32_t num_labels
= 0;
4807 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4809 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4812 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4814 attr
.nexthop
= bgp_static
->igpnexthop
;
4815 attr
.med
= bgp_static
->igpmetric
;
4816 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4818 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4819 || (safi
== SAFI_ENCAP
)) {
4820 if (afi
== AFI_IP
) {
4821 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4822 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4825 if (afi
== AFI_L2VPN
) {
4826 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4828 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4829 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4830 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4831 sizeof(struct in6_addr
));
4832 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4833 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4834 struct bgp_encap_type_vxlan bet
;
4835 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4836 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4837 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4839 if (bgp_static
->router_mac
) {
4840 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4843 /* Apply route-map. */
4844 if (bgp_static
->rmap
.name
) {
4845 struct attr attr_tmp
= attr
;
4846 struct bgp_path_info rmap_path
;
4849 rmap_path
.peer
= bgp
->peer_self
;
4850 rmap_path
.attr
= &attr_tmp
;
4852 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4854 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4857 bgp
->peer_self
->rmap_type
= 0;
4859 if (ret
== RMAP_DENYMATCH
) {
4860 /* Free uninterned attribute. */
4861 bgp_attr_flush(&attr_tmp
);
4863 /* Unintern original. */
4864 aspath_unintern(&attr
.aspath
);
4865 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4870 attr_new
= bgp_attr_intern(&attr_tmp
);
4872 attr_new
= bgp_attr_intern(&attr
);
4875 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4876 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4877 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4881 memset(&add
, 0, sizeof(union gw_addr
));
4882 if (attrhash_cmp(pi
->attr
, attr_new
)
4883 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4884 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4885 bgp_unlock_node(rn
);
4886 bgp_attr_unintern(&attr_new
);
4887 aspath_unintern(&attr
.aspath
);
4890 /* The attribute is changed. */
4891 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4893 /* Rewrite BGP route information. */
4894 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4895 bgp_path_info_restore(rn
, pi
);
4897 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4898 bgp_attr_unintern(&pi
->attr
);
4899 pi
->attr
= attr_new
;
4900 pi
->uptime
= bgp_clock();
4903 label
= decode_label(&pi
->extra
->label
[0]);
4906 /* Process change. */
4907 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4908 bgp_process(bgp
, rn
, afi
, safi
);
4910 if (SAFI_MPLS_VPN
== safi
4911 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4912 vpn_leak_to_vrf_update(bgp
, pi
);
4915 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4916 pi
->attr
, afi
, safi
, pi
->type
,
4917 pi
->sub_type
, &label
);
4919 bgp_unlock_node(rn
);
4920 aspath_unintern(&attr
.aspath
);
4926 /* Make new BGP info. */
4927 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4929 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4930 new->extra
= bgp_path_info_extra_new();
4932 new->extra
->label
[0] = bgp_static
->label
;
4933 new->extra
->num_labels
= num_labels
;
4936 label
= decode_label(&bgp_static
->label
);
4939 /* Aggregate address increment. */
4940 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4942 /* Register new BGP information. */
4943 bgp_path_info_add(rn
, new);
4944 /* route_node_get lock */
4945 bgp_unlock_node(rn
);
4947 /* Process change. */
4948 bgp_process(bgp
, rn
, afi
, safi
);
4950 if (SAFI_MPLS_VPN
== safi
4951 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4952 vpn_leak_to_vrf_update(bgp
, new);
4955 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4956 safi
, new->type
, new->sub_type
, &label
);
4959 /* Unintern original. */
4960 aspath_unintern(&attr
.aspath
);
4963 /* Configure static BGP network. When user don't run zebra, static
4964 route should be installed as valid. */
4965 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4966 const char *ip_str
, afi_t afi
, safi_t safi
,
4967 const char *rmap
, int backdoor
, uint32_t label_index
)
4969 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4972 struct bgp_static
*bgp_static
;
4973 struct bgp_node
*rn
;
4974 uint8_t need_update
= 0;
4976 /* Convert IP prefix string to struct prefix. */
4977 ret
= str2prefix(ip_str
, &p
);
4979 vty_out(vty
, "%% Malformed prefix\n");
4980 return CMD_WARNING_CONFIG_FAILED
;
4982 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4983 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4984 return CMD_WARNING_CONFIG_FAILED
;
4991 /* Set BGP static route configuration. */
4992 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4995 vty_out(vty
, "%% Can't find static route specified\n");
4996 return CMD_WARNING_CONFIG_FAILED
;
4999 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5001 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5002 && (label_index
!= bgp_static
->label_index
)) {
5004 "%% label-index doesn't match static route\n");
5005 return CMD_WARNING_CONFIG_FAILED
;
5008 if ((rmap
&& bgp_static
->rmap
.name
)
5009 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5011 "%% route-map name doesn't match static route\n");
5012 return CMD_WARNING_CONFIG_FAILED
;
5015 /* Update BGP RIB. */
5016 if (!bgp_static
->backdoor
)
5017 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5019 /* Clear configuration. */
5020 bgp_static_free(bgp_static
);
5021 bgp_node_set_bgp_static_info(rn
, NULL
);
5022 bgp_unlock_node(rn
);
5023 bgp_unlock_node(rn
);
5026 /* Set BGP static route configuration. */
5027 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5029 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5031 /* Configuration change. */
5032 /* Label index cannot be changed. */
5033 if (bgp_static
->label_index
!= label_index
) {
5034 vty_out(vty
, "%% cannot change label-index\n");
5035 return CMD_WARNING_CONFIG_FAILED
;
5038 /* Check previous routes are installed into BGP. */
5039 if (bgp_static
->valid
5040 && bgp_static
->backdoor
!= backdoor
)
5043 bgp_static
->backdoor
= backdoor
;
5046 XFREE(MTYPE_ROUTE_MAP_NAME
,
5047 bgp_static
->rmap
.name
);
5048 route_map_counter_decrement(
5049 bgp_static
->rmap
.map
);
5050 bgp_static
->rmap
.name
=
5051 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5052 bgp_static
->rmap
.map
=
5053 route_map_lookup_by_name(rmap
);
5054 route_map_counter_increment(
5055 bgp_static
->rmap
.map
);
5057 XFREE(MTYPE_ROUTE_MAP_NAME
,
5058 bgp_static
->rmap
.name
);
5059 route_map_counter_decrement(
5060 bgp_static
->rmap
.map
);
5061 bgp_static
->rmap
.name
= NULL
;
5062 bgp_static
->rmap
.map
= NULL
;
5063 bgp_static
->valid
= 0;
5065 bgp_unlock_node(rn
);
5067 /* New configuration. */
5068 bgp_static
= bgp_static_new();
5069 bgp_static
->backdoor
= backdoor
;
5070 bgp_static
->valid
= 0;
5071 bgp_static
->igpmetric
= 0;
5072 bgp_static
->igpnexthop
.s_addr
= 0;
5073 bgp_static
->label_index
= label_index
;
5076 XFREE(MTYPE_ROUTE_MAP_NAME
,
5077 bgp_static
->rmap
.name
);
5078 route_map_counter_decrement(
5079 bgp_static
->rmap
.map
);
5080 bgp_static
->rmap
.name
=
5081 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5082 bgp_static
->rmap
.map
=
5083 route_map_lookup_by_name(rmap
);
5084 route_map_counter_increment(
5085 bgp_static
->rmap
.map
);
5087 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5090 bgp_static
->valid
= 1;
5092 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5094 if (!bgp_static
->backdoor
)
5095 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5101 void bgp_static_add(struct bgp
*bgp
)
5105 struct bgp_node
*rn
;
5106 struct bgp_node
*rm
;
5107 struct bgp_table
*table
;
5108 struct bgp_static
*bgp_static
;
5110 FOREACH_AFI_SAFI (afi
, safi
)
5111 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5112 rn
= bgp_route_next(rn
)) {
5113 if (!bgp_node_has_bgp_path_info_data(rn
))
5116 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5117 || (safi
== SAFI_EVPN
)) {
5118 table
= bgp_node_get_bgp_table_info(rn
);
5120 for (rm
= bgp_table_top(table
); rm
;
5121 rm
= bgp_route_next(rm
)) {
5123 bgp_node_get_bgp_static_info(
5125 bgp_static_update_safi(bgp
, &rm
->p
,
5132 bgp_node_get_bgp_static_info(rn
), afi
,
5138 /* Called from bgp_delete(). Delete all static routes from the BGP
5140 void bgp_static_delete(struct bgp
*bgp
)
5144 struct bgp_node
*rn
;
5145 struct bgp_node
*rm
;
5146 struct bgp_table
*table
;
5147 struct bgp_static
*bgp_static
;
5149 FOREACH_AFI_SAFI (afi
, safi
)
5150 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5151 rn
= bgp_route_next(rn
)) {
5152 if (!bgp_node_has_bgp_path_info_data(rn
))
5155 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5156 || (safi
== SAFI_EVPN
)) {
5157 table
= bgp_node_get_bgp_table_info(rn
);
5159 for (rm
= bgp_table_top(table
); rm
;
5160 rm
= bgp_route_next(rm
)) {
5162 bgp_node_get_bgp_static_info(
5167 bgp_static_withdraw_safi(
5168 bgp
, &rm
->p
, AFI_IP
, safi
,
5169 (struct prefix_rd
*)&rn
->p
);
5170 bgp_static_free(bgp_static
);
5171 bgp_node_set_bgp_static_info(rn
, NULL
);
5172 bgp_unlock_node(rn
);
5175 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5176 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5177 bgp_static_free(bgp_static
);
5178 bgp_node_set_bgp_static_info(rn
, NULL
);
5179 bgp_unlock_node(rn
);
5184 void bgp_static_redo_import_check(struct bgp
*bgp
)
5188 struct bgp_node
*rn
;
5189 struct bgp_node
*rm
;
5190 struct bgp_table
*table
;
5191 struct bgp_static
*bgp_static
;
5193 /* Use this flag to force reprocessing of the route */
5194 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5195 FOREACH_AFI_SAFI (afi
, safi
) {
5196 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5197 rn
= bgp_route_next(rn
)) {
5198 if (!bgp_node_has_bgp_path_info_data(rn
))
5201 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5202 || (safi
== SAFI_EVPN
)) {
5203 table
= bgp_node_get_bgp_table_info(rn
);
5205 for (rm
= bgp_table_top(table
); rm
;
5206 rm
= bgp_route_next(rm
)) {
5208 bgp_node_get_bgp_static_info(
5210 bgp_static_update_safi(bgp
, &rm
->p
,
5215 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5216 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5221 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5224 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5227 struct bgp_table
*table
;
5228 struct bgp_node
*rn
;
5229 struct bgp_path_info
*pi
;
5231 table
= bgp
->rib
[afi
][safi
];
5232 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5233 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5234 if (pi
->peer
== bgp
->peer_self
5235 && ((pi
->type
== ZEBRA_ROUTE_BGP
5236 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5237 || (pi
->type
!= ZEBRA_ROUTE_BGP
5239 == BGP_ROUTE_REDISTRIBUTE
))) {
5240 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5242 bgp_unlink_nexthop(pi
);
5243 bgp_path_info_delete(rn
, pi
);
5244 bgp_process(bgp
, rn
, afi
, safi
);
5251 * Purge all networks and redistributed routes from routing table.
5252 * Invoked upon the instance going down.
5254 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5259 FOREACH_AFI_SAFI (afi
, safi
)
5260 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5265 * Currently this is used to set static routes for VPN and ENCAP.
5266 * I think it can probably be factored with bgp_static_set.
5268 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5269 const char *ip_str
, const char *rd_str
,
5270 const char *label_str
, const char *rmap_str
,
5271 int evpn_type
, const char *esi
, const char *gwip
,
5272 const char *ethtag
, const char *routermac
)
5274 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5277 struct prefix_rd prd
;
5278 struct bgp_node
*prn
;
5279 struct bgp_node
*rn
;
5280 struct bgp_table
*table
;
5281 struct bgp_static
*bgp_static
;
5282 mpls_label_t label
= MPLS_INVALID_LABEL
;
5283 struct prefix gw_ip
;
5285 /* validate ip prefix */
5286 ret
= str2prefix(ip_str
, &p
);
5288 vty_out(vty
, "%% Malformed prefix\n");
5289 return CMD_WARNING_CONFIG_FAILED
;
5292 if ((afi
== AFI_L2VPN
)
5293 && (bgp_build_evpn_prefix(evpn_type
,
5294 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5295 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5296 return CMD_WARNING_CONFIG_FAILED
;
5299 ret
= str2prefix_rd(rd_str
, &prd
);
5301 vty_out(vty
, "%% Malformed rd\n");
5302 return CMD_WARNING_CONFIG_FAILED
;
5306 unsigned long label_val
;
5307 label_val
= strtoul(label_str
, NULL
, 10);
5308 encode_label(label_val
, &label
);
5311 if (safi
== SAFI_EVPN
) {
5312 if (esi
&& str2esi(esi
, NULL
) == 0) {
5313 vty_out(vty
, "%% Malformed ESI\n");
5314 return CMD_WARNING_CONFIG_FAILED
;
5316 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5317 vty_out(vty
, "%% Malformed Router MAC\n");
5318 return CMD_WARNING_CONFIG_FAILED
;
5321 memset(&gw_ip
, 0, sizeof(struct prefix
));
5322 ret
= str2prefix(gwip
, &gw_ip
);
5324 vty_out(vty
, "%% Malformed GatewayIp\n");
5325 return CMD_WARNING_CONFIG_FAILED
;
5327 if ((gw_ip
.family
== AF_INET
5328 && is_evpn_prefix_ipaddr_v6(
5329 (struct prefix_evpn
*)&p
))
5330 || (gw_ip
.family
== AF_INET6
5331 && is_evpn_prefix_ipaddr_v4(
5332 (struct prefix_evpn
*)&p
))) {
5334 "%% GatewayIp family differs with IP prefix\n");
5335 return CMD_WARNING_CONFIG_FAILED
;
5339 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5340 if (!bgp_node_has_bgp_path_info_data(prn
))
5341 bgp_node_set_bgp_table_info(prn
,
5342 bgp_table_init(bgp
, afi
, safi
));
5343 table
= bgp_node_get_bgp_table_info(prn
);
5345 rn
= bgp_node_get(table
, &p
);
5347 if (bgp_node_has_bgp_path_info_data(rn
)) {
5348 vty_out(vty
, "%% Same network configuration exists\n");
5349 bgp_unlock_node(rn
);
5351 /* New configuration. */
5352 bgp_static
= bgp_static_new();
5353 bgp_static
->backdoor
= 0;
5354 bgp_static
->valid
= 0;
5355 bgp_static
->igpmetric
= 0;
5356 bgp_static
->igpnexthop
.s_addr
= 0;
5357 bgp_static
->label
= label
;
5358 bgp_static
->prd
= prd
;
5361 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5362 route_map_counter_decrement(bgp_static
->rmap
.map
);
5363 bgp_static
->rmap
.name
=
5364 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5365 bgp_static
->rmap
.map
=
5366 route_map_lookup_by_name(rmap_str
);
5367 route_map_counter_increment(bgp_static
->rmap
.map
);
5370 if (safi
== SAFI_EVPN
) {
5372 bgp_static
->eth_s_id
=
5374 sizeof(struct eth_segment_id
));
5375 str2esi(esi
, bgp_static
->eth_s_id
);
5378 bgp_static
->router_mac
=
5379 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5380 (void)prefix_str2mac(routermac
,
5381 bgp_static
->router_mac
);
5384 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5386 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5388 bgp_static
->valid
= 1;
5389 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5395 /* Configure static BGP network. */
5396 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5397 const char *ip_str
, const char *rd_str
,
5398 const char *label_str
, int evpn_type
, const char *esi
,
5399 const char *gwip
, const char *ethtag
)
5401 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5404 struct prefix_rd prd
;
5405 struct bgp_node
*prn
;
5406 struct bgp_node
*rn
;
5407 struct bgp_table
*table
;
5408 struct bgp_static
*bgp_static
;
5409 mpls_label_t label
= MPLS_INVALID_LABEL
;
5411 /* Convert IP prefix string to struct prefix. */
5412 ret
= str2prefix(ip_str
, &p
);
5414 vty_out(vty
, "%% Malformed prefix\n");
5415 return CMD_WARNING_CONFIG_FAILED
;
5418 if ((afi
== AFI_L2VPN
)
5419 && (bgp_build_evpn_prefix(evpn_type
,
5420 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5421 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5422 return CMD_WARNING_CONFIG_FAILED
;
5424 ret
= str2prefix_rd(rd_str
, &prd
);
5426 vty_out(vty
, "%% Malformed rd\n");
5427 return CMD_WARNING_CONFIG_FAILED
;
5431 unsigned long label_val
;
5432 label_val
= strtoul(label_str
, NULL
, 10);
5433 encode_label(label_val
, &label
);
5436 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5437 if (!bgp_node_has_bgp_path_info_data(prn
))
5438 bgp_node_set_bgp_table_info(prn
,
5439 bgp_table_init(bgp
, afi
, safi
));
5441 bgp_unlock_node(prn
);
5442 table
= bgp_node_get_bgp_table_info(prn
);
5444 rn
= bgp_node_lookup(table
, &p
);
5447 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5449 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5450 bgp_static_free(bgp_static
);
5451 bgp_node_set_bgp_static_info(rn
, NULL
);
5452 bgp_unlock_node(rn
);
5453 bgp_unlock_node(rn
);
5455 vty_out(vty
, "%% Can't find the route\n");
5460 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5461 const char *rmap_name
)
5463 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5464 struct bgp_rmap
*rmap
;
5466 rmap
= &bgp
->table_map
[afi
][safi
];
5468 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5469 route_map_counter_decrement(rmap
->map
);
5470 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5471 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5472 route_map_counter_increment(rmap
->map
);
5474 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5475 route_map_counter_decrement(rmap
->map
);
5480 if (bgp_fibupd_safi(safi
))
5481 bgp_zebra_announce_table(bgp
, afi
, safi
);
5486 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5487 const char *rmap_name
)
5489 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5490 struct bgp_rmap
*rmap
;
5492 rmap
= &bgp
->table_map
[afi
][safi
];
5493 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5494 route_map_counter_decrement(rmap
->map
);
5498 if (bgp_fibupd_safi(safi
))
5499 bgp_zebra_announce_table(bgp
, afi
, safi
);
5504 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5507 if (bgp
->table_map
[afi
][safi
].name
) {
5508 vty_out(vty
, " table-map %s\n",
5509 bgp
->table_map
[afi
][safi
].name
);
5513 DEFUN (bgp_table_map
,
5516 "BGP table to RIB route download filter\n"
5517 "Name of the route map\n")
5520 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5521 argv
[idx_word
]->arg
);
5523 DEFUN (no_bgp_table_map
,
5524 no_bgp_table_map_cmd
,
5525 "no table-map WORD",
5527 "BGP table to RIB route download filter\n"
5528 "Name of the route map\n")
5531 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5532 argv
[idx_word
]->arg
);
5538 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5539 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5540 backdoor$backdoor}]",
5542 "Specify a network to announce via BGP\n"
5547 "Route-map to modify the attributes\n"
5548 "Name of the route map\n"
5549 "Label index to associate with the prefix\n"
5550 "Label index value\n"
5551 "Specify a BGP backdoor route\n")
5553 char addr_prefix_str
[BUFSIZ
];
5558 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5561 vty_out(vty
, "%% Inconsistent address and mask\n");
5562 return CMD_WARNING_CONFIG_FAILED
;
5566 return bgp_static_set(
5567 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5568 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5569 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5572 DEFPY(ipv6_bgp_network
,
5573 ipv6_bgp_network_cmd
,
5574 "[no] network X:X::X:X/M$prefix \
5575 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5577 "Specify a network to announce via BGP\n"
5579 "Route-map to modify the attributes\n"
5580 "Name of the route map\n"
5581 "Label index to associate with the prefix\n"
5582 "Label index value\n")
5584 return bgp_static_set(
5585 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5586 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5589 static struct bgp_aggregate
*bgp_aggregate_new(void)
5591 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5594 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5596 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5599 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5600 struct aspath
*aspath
,
5601 struct community
*comm
,
5602 struct ecommunity
*ecomm
,
5603 struct lcommunity
*lcomm
)
5605 static struct aspath
*ae
= NULL
;
5608 ae
= aspath_empty();
5613 if (origin
!= pi
->attr
->origin
)
5616 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5619 if (!community_cmp(pi
->attr
->community
, comm
))
5622 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5625 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5628 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5634 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5635 struct prefix
*p
, uint8_t origin
,
5636 struct aspath
*aspath
,
5637 struct community
*community
,
5638 struct ecommunity
*ecommunity
,
5639 struct lcommunity
*lcommunity
,
5640 uint8_t atomic_aggregate
,
5641 struct bgp_aggregate
*aggregate
)
5643 struct bgp_node
*rn
;
5644 struct bgp_table
*table
;
5645 struct bgp_path_info
*pi
, *orig
, *new;
5647 table
= bgp
->rib
[afi
][safi
];
5649 rn
= bgp_node_get(table
, p
);
5651 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5652 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5653 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5656 if (aggregate
->count
> 0) {
5658 * If the aggregate information has not changed
5659 * no need to re-install it again.
5661 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5662 ecommunity
, lcommunity
)) {
5663 bgp_unlock_node(rn
);
5666 aspath_free(aspath
);
5668 community_free(&community
);
5670 ecommunity_free(&ecommunity
);
5672 lcommunity_free(&lcommunity
);
5678 * Mark the old as unusable
5681 bgp_path_info_delete(rn
, pi
);
5683 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5685 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5686 community
, ecommunity
,
5691 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5693 bgp_path_info_add(rn
, new);
5694 bgp_process(bgp
, rn
, afi
, safi
);
5696 for (pi
= orig
; pi
; pi
= pi
->next
)
5697 if (pi
->peer
== bgp
->peer_self
5698 && pi
->type
== ZEBRA_ROUTE_BGP
5699 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5702 /* Withdraw static BGP route from routing table. */
5704 bgp_path_info_delete(rn
, pi
);
5705 bgp_process(bgp
, rn
, afi
, safi
);
5709 bgp_unlock_node(rn
);
5712 /* Update an aggregate as routes are added/removed from the BGP table */
5713 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5714 afi_t afi
, safi_t safi
,
5715 struct bgp_aggregate
*aggregate
)
5717 struct bgp_table
*table
;
5718 struct bgp_node
*top
;
5719 struct bgp_node
*rn
;
5721 struct aspath
*aspath
= NULL
;
5722 struct community
*community
= NULL
;
5723 struct ecommunity
*ecommunity
= NULL
;
5724 struct lcommunity
*lcommunity
= NULL
;
5725 struct bgp_path_info
*pi
;
5726 unsigned long match
= 0;
5727 uint8_t atomic_aggregate
= 0;
5729 /* ORIGIN attribute: If at least one route among routes that are
5730 aggregated has ORIGIN with the value INCOMPLETE, then the
5731 aggregated route must have the ORIGIN attribute with the value
5732 INCOMPLETE. Otherwise, if at least one route among routes that
5733 are aggregated has ORIGIN with the value EGP, then the aggregated
5734 route must have the origin attribute with the value EGP. In all
5735 other case the value of the ORIGIN attribute of the aggregated
5736 route is INTERNAL. */
5737 origin
= BGP_ORIGIN_IGP
;
5739 table
= bgp
->rib
[afi
][safi
];
5741 top
= bgp_node_get(table
, p
);
5742 for (rn
= bgp_node_get(table
, p
); rn
;
5743 rn
= bgp_route_next_until(rn
, top
)) {
5744 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5749 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5750 if (BGP_PATH_HOLDDOWN(pi
))
5754 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5755 atomic_aggregate
= 1;
5757 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5761 * summary-only aggregate route suppress
5762 * aggregated route announcements.
5764 if (aggregate
->summary_only
) {
5765 (bgp_path_info_extra_get(pi
))->suppress
++;
5766 bgp_path_info_set_flag(rn
, pi
,
5767 BGP_PATH_ATTR_CHANGED
);
5774 * If at least one route among routes that are
5775 * aggregated has ORIGIN with the value INCOMPLETE,
5776 * then the aggregated route MUST have the ORIGIN
5777 * attribute with the value INCOMPLETE. Otherwise, if
5778 * at least one route among routes that are aggregated
5779 * has ORIGIN with the value EGP, then the aggregated
5780 * route MUST have the ORIGIN attribute with the value
5783 switch (pi
->attr
->origin
) {
5784 case BGP_ORIGIN_INCOMPLETE
:
5785 aggregate
->incomplete_origin_count
++;
5787 case BGP_ORIGIN_EGP
:
5788 aggregate
->egp_origin_count
++;
5796 if (!aggregate
->as_set
)
5800 * as-set aggregate route generate origin, as path,
5801 * and community aggregation.
5803 /* Compute aggregate route's as-path.
5805 bgp_compute_aggregate_aspath(aggregate
,
5808 /* Compute aggregate route's community.
5810 if (pi
->attr
->community
)
5811 bgp_compute_aggregate_community(
5813 pi
->attr
->community
);
5815 /* Compute aggregate route's extended community.
5817 if (pi
->attr
->ecommunity
)
5818 bgp_compute_aggregate_ecommunity(
5820 pi
->attr
->ecommunity
);
5822 /* Compute aggregate route's large community.
5824 if (pi
->attr
->lcommunity
)
5825 bgp_compute_aggregate_lcommunity(
5827 pi
->attr
->lcommunity
);
5830 bgp_process(bgp
, rn
, afi
, safi
);
5832 bgp_unlock_node(top
);
5835 if (aggregate
->incomplete_origin_count
> 0)
5836 origin
= BGP_ORIGIN_INCOMPLETE
;
5837 else if (aggregate
->egp_origin_count
> 0)
5838 origin
= BGP_ORIGIN_EGP
;
5840 if (aggregate
->as_set
) {
5841 if (aggregate
->aspath
)
5842 /* Retrieve aggregate route's as-path.
5844 aspath
= aspath_dup(aggregate
->aspath
);
5846 if (aggregate
->community
)
5847 /* Retrieve aggregate route's community.
5849 community
= community_dup(aggregate
->community
);
5851 if (aggregate
->ecommunity
)
5852 /* Retrieve aggregate route's ecommunity.
5854 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
5856 if (aggregate
->lcommunity
)
5857 /* Retrieve aggregate route's lcommunity.
5859 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
5862 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5863 ecommunity
, lcommunity
, atomic_aggregate
,
5867 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5868 safi_t safi
, struct bgp_aggregate
*aggregate
)
5870 struct bgp_table
*table
;
5871 struct bgp_node
*top
;
5872 struct bgp_node
*rn
;
5873 struct bgp_path_info
*pi
;
5874 unsigned long match
;
5876 table
= bgp
->rib
[afi
][safi
];
5878 /* If routes exists below this node, generate aggregate routes. */
5879 top
= bgp_node_get(table
, p
);
5880 for (rn
= bgp_node_get(table
, p
); rn
;
5881 rn
= bgp_route_next_until(rn
, top
)) {
5882 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5886 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5887 if (BGP_PATH_HOLDDOWN(pi
))
5890 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5893 if (aggregate
->summary_only
&& pi
->extra
) {
5894 pi
->extra
->suppress
--;
5896 if (pi
->extra
->suppress
== 0) {
5897 bgp_path_info_set_flag(
5898 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5904 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
5905 aggregate
->incomplete_origin_count
--;
5906 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
5907 aggregate
->egp_origin_count
--;
5909 if (aggregate
->as_set
) {
5910 /* Remove as-path from aggregate.
5912 bgp_remove_aspath_from_aggregate(
5916 if (pi
->attr
->community
)
5917 /* Remove community from aggregate.
5919 bgp_remove_community_from_aggregate(
5921 pi
->attr
->community
);
5923 if (pi
->attr
->ecommunity
)
5924 /* Remove ecommunity from aggregate.
5926 bgp_remove_ecommunity_from_aggregate(
5928 pi
->attr
->ecommunity
);
5930 if (pi
->attr
->lcommunity
)
5931 /* Remove lcommunity from aggregate.
5933 bgp_remove_lcommunity_from_aggregate(
5935 pi
->attr
->lcommunity
);
5940 /* If this node was suppressed, process the change. */
5942 bgp_process(bgp
, rn
, afi
, safi
);
5944 bgp_unlock_node(top
);
5947 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
5948 struct bgp_path_info
*pinew
, afi_t afi
,
5950 struct bgp_aggregate
*aggregate
)
5953 struct aspath
*aspath
= NULL
;
5954 uint8_t atomic_aggregate
= 0;
5955 struct community
*community
= NULL
;
5956 struct ecommunity
*ecommunity
= NULL
;
5957 struct lcommunity
*lcommunity
= NULL
;
5959 /* ORIGIN attribute: If at least one route among routes that are
5960 * aggregated has ORIGIN with the value INCOMPLETE, then the
5961 * aggregated route must have the ORIGIN attribute with the value
5962 * INCOMPLETE. Otherwise, if at least one route among routes that
5963 * are aggregated has ORIGIN with the value EGP, then the aggregated
5964 * route must have the origin attribute with the value EGP. In all
5965 * other case the value of the ORIGIN attribute of the aggregated
5966 * route is INTERNAL.
5968 origin
= BGP_ORIGIN_IGP
;
5972 if (aggregate
->summary_only
)
5973 (bgp_path_info_extra_get(pinew
))->suppress
++;
5975 switch (pinew
->attr
->origin
) {
5976 case BGP_ORIGIN_INCOMPLETE
:
5977 aggregate
->incomplete_origin_count
++;
5979 case BGP_ORIGIN_EGP
:
5980 aggregate
->egp_origin_count
++;
5988 if (aggregate
->incomplete_origin_count
> 0)
5989 origin
= BGP_ORIGIN_INCOMPLETE
;
5990 else if (aggregate
->egp_origin_count
> 0)
5991 origin
= BGP_ORIGIN_EGP
;
5993 if (aggregate
->as_set
) {
5994 /* Compute aggregate route's as-path.
5996 bgp_compute_aggregate_aspath(aggregate
,
5997 pinew
->attr
->aspath
);
5999 /* Compute aggregate route's community.
6001 if (pinew
->attr
->community
)
6002 bgp_compute_aggregate_community(
6004 pinew
->attr
->community
);
6006 /* Compute aggregate route's extended community.
6008 if (pinew
->attr
->ecommunity
)
6009 bgp_compute_aggregate_ecommunity(
6011 pinew
->attr
->ecommunity
);
6013 /* Compute aggregate route's large community.
6015 if (pinew
->attr
->lcommunity
)
6016 bgp_compute_aggregate_lcommunity(
6018 pinew
->attr
->lcommunity
);
6020 /* Retrieve aggregate route's as-path.
6022 if (aggregate
->aspath
)
6023 aspath
= aspath_dup(aggregate
->aspath
);
6025 /* Retrieve aggregate route's community.
6027 if (aggregate
->community
)
6028 community
= community_dup(aggregate
->community
);
6030 /* Retrieve aggregate route's ecommunity.
6032 if (aggregate
->ecommunity
)
6033 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6035 /* Retrieve aggregate route's lcommunity.
6037 if (aggregate
->lcommunity
)
6038 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6041 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6042 aspath
, community
, ecommunity
,
6043 lcommunity
, atomic_aggregate
, aggregate
);
6046 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6048 struct bgp_path_info
*pi
,
6049 struct bgp_aggregate
*aggregate
,
6050 struct prefix
*aggr_p
)
6053 struct aspath
*aspath
= NULL
;
6054 uint8_t atomic_aggregate
= 0;
6055 struct community
*community
= NULL
;
6056 struct ecommunity
*ecommunity
= NULL
;
6057 struct lcommunity
*lcommunity
= NULL
;
6058 unsigned long match
= 0;
6060 if (BGP_PATH_HOLDDOWN(pi
))
6063 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6066 if (aggregate
->summary_only
6068 && pi
->extra
->suppress
> 0) {
6069 pi
->extra
->suppress
--;
6071 if (pi
->extra
->suppress
== 0) {
6072 bgp_path_info_set_flag(pi
->net
, pi
,
6073 BGP_PATH_ATTR_CHANGED
);
6078 if (aggregate
->count
> 0)
6081 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6082 aggregate
->incomplete_origin_count
--;
6083 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6084 aggregate
->egp_origin_count
--;
6086 if (aggregate
->as_set
) {
6087 /* Remove as-path from aggregate.
6089 bgp_remove_aspath_from_aggregate(aggregate
,
6092 if (pi
->attr
->community
)
6093 /* Remove community from aggregate.
6095 bgp_remove_community_from_aggregate(
6097 pi
->attr
->community
);
6099 if (pi
->attr
->ecommunity
)
6100 /* Remove ecommunity from aggregate.
6102 bgp_remove_ecommunity_from_aggregate(
6104 pi
->attr
->ecommunity
);
6106 if (pi
->attr
->lcommunity
)
6107 /* Remove lcommunity from aggregate.
6109 bgp_remove_lcommunity_from_aggregate(
6111 pi
->attr
->lcommunity
);
6114 /* If this node was suppressed, process the change. */
6116 bgp_process(bgp
, pi
->net
, afi
, safi
);
6118 origin
= BGP_ORIGIN_IGP
;
6119 if (aggregate
->incomplete_origin_count
> 0)
6120 origin
= BGP_ORIGIN_INCOMPLETE
;
6121 else if (aggregate
->egp_origin_count
> 0)
6122 origin
= BGP_ORIGIN_EGP
;
6124 if (aggregate
->as_set
) {
6125 /* Retrieve aggregate route's as-path.
6127 if (aggregate
->aspath
)
6128 aspath
= aspath_dup(aggregate
->aspath
);
6130 /* Retrieve aggregate route's community.
6132 if (aggregate
->community
)
6133 community
= community_dup(aggregate
->community
);
6135 /* Retrieve aggregate route's ecommunity.
6137 if (aggregate
->ecommunity
)
6138 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6140 /* Retrieve aggregate route's lcommunity.
6142 if (aggregate
->lcommunity
)
6143 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6146 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6147 aspath
, community
, ecommunity
,
6148 lcommunity
, atomic_aggregate
, aggregate
);
6151 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6152 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6154 struct bgp_node
*child
;
6155 struct bgp_node
*rn
;
6156 struct bgp_aggregate
*aggregate
;
6157 struct bgp_table
*table
;
6159 table
= bgp
->aggregate
[afi
][safi
];
6161 /* No aggregates configured. */
6162 if (bgp_table_top_nolock(table
) == NULL
)
6165 if (p
->prefixlen
== 0)
6168 if (BGP_PATH_HOLDDOWN(pi
))
6171 child
= bgp_node_get(table
, p
);
6173 /* Aggregate address configuration check. */
6174 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6175 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6176 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6177 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6181 bgp_unlock_node(child
);
6184 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6185 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6187 struct bgp_node
*child
;
6188 struct bgp_node
*rn
;
6189 struct bgp_aggregate
*aggregate
;
6190 struct bgp_table
*table
;
6192 table
= bgp
->aggregate
[afi
][safi
];
6194 /* No aggregates configured. */
6195 if (bgp_table_top_nolock(table
) == NULL
)
6198 if (p
->prefixlen
== 0)
6201 child
= bgp_node_get(table
, p
);
6203 /* Aggregate address configuration check. */
6204 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6205 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6206 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6207 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6208 del
, aggregate
, &rn
->p
);
6211 bgp_unlock_node(child
);
6214 /* Aggregate route attribute. */
6215 #define AGGREGATE_SUMMARY_ONLY 1
6216 #define AGGREGATE_AS_SET 1
6218 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6219 afi_t afi
, safi_t safi
)
6221 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6224 struct bgp_node
*rn
;
6225 struct bgp_aggregate
*aggregate
;
6227 /* Convert string to prefix structure. */
6228 ret
= str2prefix(prefix_str
, &p
);
6230 vty_out(vty
, "Malformed prefix\n");
6231 return CMD_WARNING_CONFIG_FAILED
;
6235 /* Old configuration check. */
6236 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6239 "%% There is no aggregate-address configuration.\n");
6240 return CMD_WARNING_CONFIG_FAILED
;
6243 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6244 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6245 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6246 NULL
, NULL
, 0, aggregate
);
6248 /* Unlock aggregate address configuration. */
6249 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6251 if (aggregate
->community
)
6252 community_free(&aggregate
->community
);
6254 if (aggregate
->community_hash
) {
6255 /* Delete all communities in the hash.
6257 hash_clean(aggregate
->community_hash
,
6258 bgp_aggr_community_remove
);
6259 /* Free up the community_hash.
6261 hash_free(aggregate
->community_hash
);
6264 if (aggregate
->ecommunity
)
6265 ecommunity_free(&aggregate
->ecommunity
);
6267 if (aggregate
->ecommunity_hash
) {
6268 /* Delete all ecommunities in the hash.
6270 hash_clean(aggregate
->ecommunity_hash
,
6271 bgp_aggr_ecommunity_remove
);
6272 /* Free up the ecommunity_hash.
6274 hash_free(aggregate
->ecommunity_hash
);
6277 if (aggregate
->lcommunity
)
6278 lcommunity_free(&aggregate
->lcommunity
);
6280 if (aggregate
->lcommunity_hash
) {
6281 /* Delete all lcommunities in the hash.
6283 hash_clean(aggregate
->lcommunity_hash
,
6284 bgp_aggr_lcommunity_remove
);
6285 /* Free up the lcommunity_hash.
6287 hash_free(aggregate
->lcommunity_hash
);
6290 if (aggregate
->aspath
)
6291 aspath_free(aggregate
->aspath
);
6293 if (aggregate
->aspath_hash
) {
6294 /* Delete all as-paths in the hash.
6296 hash_clean(aggregate
->aspath_hash
,
6297 bgp_aggr_aspath_remove
);
6298 /* Free up the aspath_hash.
6300 hash_free(aggregate
->aspath_hash
);
6303 bgp_aggregate_free(aggregate
);
6304 bgp_unlock_node(rn
);
6305 bgp_unlock_node(rn
);
6310 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6311 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
6313 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6316 struct bgp_node
*rn
;
6317 struct bgp_aggregate
*aggregate
;
6319 /* Convert string to prefix structure. */
6320 ret
= str2prefix(prefix_str
, &p
);
6322 vty_out(vty
, "Malformed prefix\n");
6323 return CMD_WARNING_CONFIG_FAILED
;
6327 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6328 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6329 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6331 return CMD_WARNING_CONFIG_FAILED
;
6334 /* Old configuration check. */
6335 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6337 if (bgp_node_has_bgp_path_info_data(rn
)) {
6338 vty_out(vty
, "There is already same aggregate network.\n");
6339 /* try to remove the old entry */
6340 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6342 vty_out(vty
, "Error deleting aggregate.\n");
6343 bgp_unlock_node(rn
);
6344 return CMD_WARNING_CONFIG_FAILED
;
6348 /* Make aggregate address structure. */
6349 aggregate
= bgp_aggregate_new();
6350 aggregate
->summary_only
= summary_only
;
6351 aggregate
->as_set
= as_set
;
6352 aggregate
->safi
= safi
;
6353 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6355 /* Aggregate address insert into BGP routing table. */
6356 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6361 DEFUN (aggregate_address
,
6362 aggregate_address_cmd
,
6363 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6364 "Configure BGP aggregate entries\n"
6365 "Aggregate prefix\n"
6366 "Generate AS set path information\n"
6367 "Filter more specific routes from updates\n"
6368 "Filter more specific routes from updates\n"
6369 "Generate AS set path information\n")
6372 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6373 char *prefix
= argv
[idx
]->arg
;
6375 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6377 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6378 ? AGGREGATE_SUMMARY_ONLY
6381 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6382 summary_only
, as_set
);
6385 DEFUN (aggregate_address_mask
,
6386 aggregate_address_mask_cmd
,
6387 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6388 "Configure BGP aggregate entries\n"
6389 "Aggregate address\n"
6391 "Generate AS set path information\n"
6392 "Filter more specific routes from updates\n"
6393 "Filter more specific routes from updates\n"
6394 "Generate AS set path information\n")
6397 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6398 char *prefix
= argv
[idx
]->arg
;
6399 char *mask
= argv
[idx
+ 1]->arg
;
6401 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6403 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6404 ? AGGREGATE_SUMMARY_ONLY
6407 char prefix_str
[BUFSIZ
];
6408 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6411 vty_out(vty
, "%% Inconsistent address and mask\n");
6412 return CMD_WARNING_CONFIG_FAILED
;
6415 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6416 summary_only
, as_set
);
6419 DEFUN (no_aggregate_address
,
6420 no_aggregate_address_cmd
,
6421 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6423 "Configure BGP aggregate entries\n"
6424 "Aggregate prefix\n"
6425 "Generate AS set path information\n"
6426 "Filter more specific routes from updates\n"
6427 "Filter more specific routes from updates\n"
6428 "Generate AS set path information\n")
6431 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6432 char *prefix
= argv
[idx
]->arg
;
6433 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6436 DEFUN (no_aggregate_address_mask
,
6437 no_aggregate_address_mask_cmd
,
6438 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6440 "Configure BGP aggregate entries\n"
6441 "Aggregate address\n"
6443 "Generate AS set path information\n"
6444 "Filter more specific routes from updates\n"
6445 "Filter more specific routes from updates\n"
6446 "Generate AS set path information\n")
6449 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6450 char *prefix
= argv
[idx
]->arg
;
6451 char *mask
= argv
[idx
+ 1]->arg
;
6453 char prefix_str
[BUFSIZ
];
6454 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6457 vty_out(vty
, "%% Inconsistent address and mask\n");
6458 return CMD_WARNING_CONFIG_FAILED
;
6461 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6464 DEFUN (ipv6_aggregate_address
,
6465 ipv6_aggregate_address_cmd
,
6466 "aggregate-address X:X::X:X/M [summary-only]",
6467 "Configure BGP aggregate entries\n"
6468 "Aggregate prefix\n"
6469 "Filter more specific routes from updates\n")
6472 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6473 char *prefix
= argv
[idx
]->arg
;
6474 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6475 ? AGGREGATE_SUMMARY_ONLY
6477 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6481 DEFUN (no_ipv6_aggregate_address
,
6482 no_ipv6_aggregate_address_cmd
,
6483 "no aggregate-address X:X::X:X/M [summary-only]",
6485 "Configure BGP aggregate entries\n"
6486 "Aggregate prefix\n"
6487 "Filter more specific routes from updates\n")
6490 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6491 char *prefix
= argv
[idx
]->arg
;
6492 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6495 /* Redistribute route treatment. */
6496 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6497 const union g_addr
*nexthop
, ifindex_t ifindex
,
6498 enum nexthop_types_t nhtype
, uint32_t metric
,
6499 uint8_t type
, unsigned short instance
,
6502 struct bgp_path_info
*new;
6503 struct bgp_path_info
*bpi
;
6504 struct bgp_path_info rmap_path
;
6505 struct bgp_node
*bn
;
6507 struct attr
*new_attr
;
6510 struct bgp_redist
*red
;
6512 /* Make default attribute. */
6513 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6516 case NEXTHOP_TYPE_IFINDEX
:
6518 case NEXTHOP_TYPE_IPV4
:
6519 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6520 attr
.nexthop
= nexthop
->ipv4
;
6522 case NEXTHOP_TYPE_IPV6
:
6523 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6524 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6525 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6527 case NEXTHOP_TYPE_BLACKHOLE
:
6528 switch (p
->family
) {
6530 attr
.nexthop
.s_addr
= INADDR_ANY
;
6533 memset(&attr
.mp_nexthop_global
, 0,
6534 sizeof(attr
.mp_nexthop_global
));
6535 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6540 attr
.nh_ifindex
= ifindex
;
6543 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6546 afi
= family2afi(p
->family
);
6548 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6550 struct attr attr_new
;
6552 /* Copy attribute for modification. */
6553 bgp_attr_dup(&attr_new
, &attr
);
6555 if (red
->redist_metric_flag
)
6556 attr_new
.med
= red
->redist_metric
;
6558 /* Apply route-map. */
6559 if (red
->rmap
.name
) {
6560 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6561 rmap_path
.peer
= bgp
->peer_self
;
6562 rmap_path
.attr
= &attr_new
;
6564 SET_FLAG(bgp
->peer_self
->rmap_type
,
6565 PEER_RMAP_TYPE_REDISTRIBUTE
);
6567 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6570 bgp
->peer_self
->rmap_type
= 0;
6572 if (ret
== RMAP_DENYMATCH
) {
6573 /* Free uninterned attribute. */
6574 bgp_attr_flush(&attr_new
);
6576 /* Unintern original. */
6577 aspath_unintern(&attr
.aspath
);
6578 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6583 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6584 bgp_attr_add_gshut_community(&attr_new
);
6586 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6587 SAFI_UNICAST
, p
, NULL
);
6589 new_attr
= bgp_attr_intern(&attr_new
);
6591 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6593 if (bpi
->peer
== bgp
->peer_self
6594 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6598 /* Ensure the (source route) type is updated. */
6600 if (attrhash_cmp(bpi
->attr
, new_attr
)
6601 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6602 bgp_attr_unintern(&new_attr
);
6603 aspath_unintern(&attr
.aspath
);
6604 bgp_unlock_node(bn
);
6607 /* The attribute is changed. */
6608 bgp_path_info_set_flag(bn
, bpi
,
6609 BGP_PATH_ATTR_CHANGED
);
6611 /* Rewrite BGP route information. */
6612 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6613 bgp_path_info_restore(bn
, bpi
);
6615 bgp_aggregate_decrement(
6616 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6617 bgp_attr_unintern(&bpi
->attr
);
6618 bpi
->attr
= new_attr
;
6619 bpi
->uptime
= bgp_clock();
6621 /* Process change. */
6622 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6624 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6625 bgp_unlock_node(bn
);
6626 aspath_unintern(&attr
.aspath
);
6628 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6630 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6632 vpn_leak_from_vrf_update(
6633 bgp_get_default(), bgp
, bpi
);
6639 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6640 bgp
->peer_self
, new_attr
, bn
);
6641 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6643 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6644 bgp_path_info_add(bn
, new);
6645 bgp_unlock_node(bn
);
6646 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6648 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6649 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6651 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6655 /* Unintern original. */
6656 aspath_unintern(&attr
.aspath
);
6659 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6660 unsigned short instance
)
6663 struct bgp_node
*rn
;
6664 struct bgp_path_info
*pi
;
6665 struct bgp_redist
*red
;
6667 afi
= family2afi(p
->family
);
6669 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6671 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6672 SAFI_UNICAST
, p
, NULL
);
6674 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6675 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6679 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6680 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6682 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6685 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6686 bgp_path_info_delete(rn
, pi
);
6687 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6689 bgp_unlock_node(rn
);
6693 /* Withdraw specified route type's route. */
6694 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6695 unsigned short instance
)
6697 struct bgp_node
*rn
;
6698 struct bgp_path_info
*pi
;
6699 struct bgp_table
*table
;
6701 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6703 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6704 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6705 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6706 && pi
->instance
== instance
)
6710 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6711 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6713 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6716 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6718 bgp_path_info_delete(rn
, pi
);
6719 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6724 /* Static function to display route. */
6725 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6732 if (p
->family
== AF_INET
) {
6736 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6739 json_object_string_add(json
, "prefix",
6740 inet_ntop(p
->family
,
6743 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6744 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6745 json_object_string_add(json
, "network", buf2
);
6747 } else if (p
->family
== AF_ETHERNET
) {
6748 prefix2str(p
, buf
, PREFIX_STRLEN
);
6749 len
= vty_out(vty
, "%s", buf
);
6750 } else if (p
->family
== AF_EVPN
) {
6754 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6757 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6758 } else if (p
->family
== AF_FLOWSPEC
) {
6759 route_vty_out_flowspec(vty
, p
, NULL
,
6761 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6762 NLRI_STRING_FORMAT_MIN
, json
);
6767 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6770 json_object_string_add(json
, "prefix",
6771 inet_ntop(p
->family
,
6774 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6775 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6776 json_object_string_add(json
, "network", buf2
);
6783 vty_out(vty
, "\n%*s", 20, " ");
6785 vty_out(vty
, "%*s", len
, " ");
6789 enum bgp_display_type
{
6793 /* Print the short form route status for a bgp_path_info */
6794 static void route_vty_short_status_out(struct vty
*vty
,
6795 struct bgp_path_info
*path
,
6796 json_object
*json_path
)
6800 /* Route status display. */
6801 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6802 json_object_boolean_true_add(json_path
, "removed");
6804 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6805 json_object_boolean_true_add(json_path
, "stale");
6807 if (path
->extra
&& path
->extra
->suppress
)
6808 json_object_boolean_true_add(json_path
, "suppressed");
6810 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6811 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6812 json_object_boolean_true_add(json_path
, "valid");
6815 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6816 json_object_boolean_true_add(json_path
, "history");
6818 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6819 json_object_boolean_true_add(json_path
, "damped");
6821 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6822 json_object_boolean_true_add(json_path
, "bestpath");
6824 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6825 json_object_boolean_true_add(json_path
, "multipath");
6827 /* Internal route. */
6828 if ((path
->peer
->as
)
6829 && (path
->peer
->as
== path
->peer
->local_as
))
6830 json_object_string_add(json_path
, "pathFrom",
6833 json_object_string_add(json_path
, "pathFrom",
6839 /* Route status display. */
6840 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6842 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6844 else if (path
->extra
&& path
->extra
->suppress
)
6846 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6847 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6853 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6855 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6857 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6859 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6864 /* Internal route. */
6865 if (path
->peer
&& (path
->peer
->as
)
6866 && (path
->peer
->as
== path
->peer
->local_as
))
6872 static char *bgp_nexthop_fqdn(struct peer
*peer
)
6874 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
))
6875 return peer
->hostname
;
6879 /* called from terminal list command */
6880 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6881 struct bgp_path_info
*path
, int display
, safi_t safi
,
6882 json_object
*json_paths
)
6885 json_object
*json_path
= NULL
;
6886 json_object
*json_nexthops
= NULL
;
6887 json_object
*json_nexthop_global
= NULL
;
6888 json_object
*json_nexthop_ll
= NULL
;
6889 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6891 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6892 bool nexthop_othervrf
= false;
6893 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6894 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
6895 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
6898 json_path
= json_object_new_object();
6900 /* short status lead text */
6901 route_vty_short_status_out(vty
, path
, json_path
);
6904 /* print prefix and mask */
6906 route_vty_out_route(p
, vty
, json_path
);
6908 vty_out(vty
, "%*s", 17, " ");
6910 route_vty_out_route(p
, vty
, json_path
);
6913 /* Print attribute */
6917 json_object_array_add(json_paths
, json_path
);
6925 * If vrf id of nexthop is different from that of prefix,
6926 * set up printable string to append
6928 if (path
->extra
&& path
->extra
->bgp_orig
) {
6929 const char *self
= "";
6934 nexthop_othervrf
= true;
6935 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6937 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6938 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6939 "@%s%s", VRFID_NONE_STR
, self
);
6941 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6942 path
->extra
->bgp_orig
->vrf_id
, self
);
6944 if (path
->extra
->bgp_orig
->inst_type
6945 != BGP_INSTANCE_TYPE_DEFAULT
)
6947 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6949 const char *self
= "";
6954 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6958 * For ENCAP and EVPN routes, nexthop address family is not
6959 * neccessarily the same as the prefix address family.
6960 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6961 * EVPN routes are also exchanged with a MP nexthop. Currently,
6963 * is only IPv4, the value will be present in either
6965 * attr->mp_nexthop_global_in
6967 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6970 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6974 sprintf(nexthop
, "%s",
6975 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6979 sprintf(nexthop
, "%s",
6980 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6984 sprintf(nexthop
, "?");
6989 json_nexthop_global
= json_object_new_object();
6991 json_object_string_add(
6992 json_nexthop_global
, "afi",
6993 nexthop_fqdn
? "fqdn"
6994 : (af
== AF_INET
) ? "ip" : "ipv6");
6995 json_object_string_add(
6996 json_nexthop_global
,
6997 nexthop_fqdn
? "fqdn"
6998 : (af
== AF_INET
) ? "ip" : "ipv6",
6999 nexthop_fqdn
? nexthop_fqdn
: nexthop
);
7000 json_object_boolean_true_add(json_nexthop_global
,
7003 vty_out(vty
, "%s%s",
7004 nexthop_fqdn
? nexthop_fqdn
: nexthop
,
7006 } else if (safi
== SAFI_EVPN
) {
7008 json_nexthop_global
= json_object_new_object();
7010 json_object_string_add(
7011 json_nexthop_global
,
7012 nexthop_fqdn
? "fqdn" : "ip",
7013 nexthop_fqdn
? nexthop_fqdn
7014 : inet_ntoa(attr
->nexthop
));
7015 json_object_string_add(json_nexthop_global
, "afi",
7017 json_object_boolean_true_add(json_nexthop_global
,
7020 vty_out(vty
, "%-16s%s",
7021 nexthop_fqdn
?: inet_ntoa(attr
->nexthop
),
7023 } else if (safi
== SAFI_FLOWSPEC
) {
7024 if (attr
->nexthop
.s_addr
!= 0) {
7026 json_nexthop_global
= json_object_new_object();
7027 json_object_string_add(
7028 json_nexthop_global
,
7029 nexthop_fqdn
? "fqdn" : "ip",
7032 : inet_ntoa(attr
->nexthop
));
7033 json_object_string_add(json_nexthop_global
,
7035 json_object_boolean_true_add(
7036 json_nexthop_global
,
7039 vty_out(vty
, "%-16s",
7042 : inet_ntoa(attr
->nexthop
));
7045 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7047 json_nexthop_global
= json_object_new_object();
7049 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
7050 json_object_string_add(
7051 json_nexthop_global
,
7052 nexthop_fqdn
? "fqdn" : "ip",
7056 attr
->mp_nexthop_global_in
));
7058 json_object_string_add(
7059 json_nexthop_global
,
7060 nexthop_fqdn
? "fqdn" : "ip",
7063 : inet_ntoa(attr
->nexthop
));
7065 json_object_string_add(json_nexthop_global
, "afi",
7067 json_object_boolean_true_add(json_nexthop_global
,
7072 snprintf(buf
, sizeof(buf
), "%s%s",
7073 nexthop_fqdn
? nexthop_fqdn
7074 : inet_ntoa(attr
->nexthop
),
7076 vty_out(vty
, "%-16s", buf
);
7081 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7086 json_nexthop_global
= json_object_new_object();
7087 json_object_string_add(
7088 json_nexthop_global
,
7089 nexthop_fqdn
? "fqdn" : "ip",
7092 : inet_ntop(AF_INET6
,
7093 &attr
->mp_nexthop_global
,
7095 json_object_string_add(json_nexthop_global
, "afi",
7097 json_object_string_add(json_nexthop_global
, "scope",
7100 /* We display both LL & GL if both have been
7102 if ((attr
->mp_nexthop_len
== 32)
7103 || (path
->peer
->conf_if
)) {
7104 json_nexthop_ll
= json_object_new_object();
7105 json_object_string_add(
7107 nexthop_fqdn
? "fqdn" : "ip",
7112 &attr
->mp_nexthop_local
,
7114 json_object_string_add(json_nexthop_ll
, "afi",
7116 json_object_string_add(json_nexthop_ll
, "scope",
7119 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7120 &attr
->mp_nexthop_local
)
7122 && !attr
->mp_nexthop_prefer_global
)
7123 json_object_boolean_true_add(
7124 json_nexthop_ll
, "used");
7126 json_object_boolean_true_add(
7127 json_nexthop_global
, "used");
7129 json_object_boolean_true_add(
7130 json_nexthop_global
, "used");
7132 /* Display LL if LL/Global both in table unless
7133 * prefer-global is set */
7134 if (((attr
->mp_nexthop_len
== 32)
7135 && !attr
->mp_nexthop_prefer_global
)
7136 || (path
->peer
->conf_if
)) {
7137 if (path
->peer
->conf_if
) {
7138 len
= vty_out(vty
, "%s",
7139 path
->peer
->conf_if
);
7140 len
= 16 - len
; /* len of IPv6
7146 vty_out(vty
, "\n%*s", 36, " ");
7148 vty_out(vty
, "%*s", len
, " ");
7156 &attr
->mp_nexthop_local
,
7162 vty_out(vty
, "\n%*s", 36, " ");
7164 vty_out(vty
, "%*s", len
, " ");
7173 &attr
->mp_nexthop_global
,
7179 vty_out(vty
, "\n%*s", 36, " ");
7181 vty_out(vty
, "%*s", len
, " ");
7187 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7191 * Adding "metric" field to match with corresponding
7192 * CLI. "med" will be deprecated in future.
7194 json_object_int_add(json_path
, "med", attr
->med
);
7195 json_object_int_add(json_path
, "metric", attr
->med
);
7197 vty_out(vty
, "%10u", attr
->med
);
7198 else if (!json_paths
)
7202 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7206 * Adding "locPrf" field to match with corresponding
7207 * CLI. "localPref" will be deprecated in future.
7209 json_object_int_add(json_path
, "localpref",
7211 json_object_int_add(json_path
, "locPrf",
7214 vty_out(vty
, "%7u", attr
->local_pref
);
7215 else if (!json_paths
)
7219 json_object_int_add(json_path
, "weight", attr
->weight
);
7221 vty_out(vty
, "%7u ", attr
->weight
);
7225 json_object_string_add(
7226 json_path
, "peerId",
7227 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7235 * Adding "path" field to match with corresponding
7236 * CLI. "aspath" will be deprecated in future.
7238 json_object_string_add(json_path
, "aspath",
7240 json_object_string_add(json_path
, "path",
7243 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7248 json_object_string_add(json_path
, "origin",
7249 bgp_origin_long_str
[attr
->origin
]);
7251 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7255 json_object_boolean_true_add(json_path
,
7256 "announceNexthopSelf");
7257 if (nexthop_othervrf
) {
7258 json_object_string_add(json_path
, "nhVrfName",
7261 json_object_int_add(json_path
, "nhVrfId",
7262 ((nexthop_vrfid
== VRF_UNKNOWN
)
7264 : (int)nexthop_vrfid
));
7269 if (json_nexthop_global
|| json_nexthop_ll
) {
7270 json_nexthops
= json_object_new_array();
7272 if (json_nexthop_global
)
7273 json_object_array_add(json_nexthops
,
7274 json_nexthop_global
);
7276 if (json_nexthop_ll
)
7277 json_object_array_add(json_nexthops
,
7280 json_object_object_add(json_path
, "nexthops",
7284 json_object_array_add(json_paths
, json_path
);
7288 /* prints an additional line, indented, with VNC info, if
7290 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7291 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7296 /* called from terminal list command */
7297 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7298 safi_t safi
, bool use_json
, json_object
*json_ar
)
7300 json_object
*json_status
= NULL
;
7301 json_object
*json_net
= NULL
;
7304 /* Route status display. */
7306 json_status
= json_object_new_object();
7307 json_net
= json_object_new_object();
7314 /* print prefix and mask */
7316 json_object_string_add(
7317 json_net
, "addrPrefix",
7318 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
7319 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
7320 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7321 json_object_string_add(json_net
, "network", buf2
);
7323 route_vty_out_route(p
, vty
, NULL
);
7325 /* Print attribute */
7328 if (p
->family
== AF_INET
7329 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7330 || safi
== SAFI_EVPN
7331 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7332 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7333 || safi
== SAFI_EVPN
)
7334 json_object_string_add(
7335 json_net
, "nextHop",
7337 attr
->mp_nexthop_global_in
));
7339 json_object_string_add(
7340 json_net
, "nextHop",
7341 inet_ntoa(attr
->nexthop
));
7342 } else if (p
->family
== AF_INET6
7343 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7346 json_object_string_add(
7347 json_net
, "nextHopGlobal",
7349 &attr
->mp_nexthop_global
, buf
,
7354 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7355 json_object_int_add(json_net
, "metric",
7358 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7361 * Adding "locPrf" field to match with
7362 * corresponding CLI. "localPref" will be
7363 * deprecated in future.
7365 json_object_int_add(json_net
, "localPref",
7367 json_object_int_add(json_net
, "locPrf",
7371 json_object_int_add(json_net
, "weight", attr
->weight
);
7377 * Adding "path" field to match with
7378 * corresponding CLI. "localPref" will be
7379 * deprecated in future.
7381 json_object_string_add(json_net
, "asPath",
7383 json_object_string_add(json_net
, "path",
7388 json_object_string_add(json_net
, "bgpOriginCode",
7389 bgp_origin_str
[attr
->origin
]);
7391 if (p
->family
== AF_INET
7392 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7393 || safi
== SAFI_EVPN
7394 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7395 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7396 || safi
== SAFI_EVPN
)
7397 vty_out(vty
, "%-16s",
7399 attr
->mp_nexthop_global_in
));
7401 vty_out(vty
, "%-16s",
7402 inet_ntoa(attr
->nexthop
));
7403 } else if (p
->family
== AF_INET6
7404 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7411 &attr
->mp_nexthop_global
, buf
,
7415 vty_out(vty
, "\n%*s", 36, " ");
7417 vty_out(vty
, "%*s", len
, " ");
7420 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7421 vty_out(vty
, "%10u", attr
->med
);
7425 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7426 vty_out(vty
, "%7u", attr
->local_pref
);
7430 vty_out(vty
, "%7u ", attr
->weight
);
7434 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7437 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7441 json_object_boolean_true_add(json_status
, "*");
7442 json_object_boolean_true_add(json_status
, ">");
7443 json_object_object_add(json_net
, "appliedStatusSymbols",
7445 char buf_cut
[BUFSIZ
];
7446 json_object_object_add(
7448 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7454 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7455 struct bgp_path_info
*path
, int display
, safi_t safi
,
7458 json_object
*json_out
= NULL
;
7460 mpls_label_t label
= MPLS_INVALID_LABEL
;
7466 json_out
= json_object_new_object();
7468 /* short status lead text */
7469 route_vty_short_status_out(vty
, path
, json_out
);
7471 /* print prefix and mask */
7474 route_vty_out_route(p
, vty
, NULL
);
7476 vty_out(vty
, "%*s", 17, " ");
7479 /* Print attribute */
7482 if (((p
->family
== AF_INET
)
7483 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7484 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7485 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7486 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7487 || safi
== SAFI_EVPN
) {
7489 json_object_string_add(
7490 json_out
, "mpNexthopGlobalIn",
7492 attr
->mp_nexthop_global_in
));
7494 vty_out(vty
, "%-16s",
7496 attr
->mp_nexthop_global_in
));
7499 json_object_string_add(
7500 json_out
, "nexthop",
7501 inet_ntoa(attr
->nexthop
));
7503 vty_out(vty
, "%-16s",
7504 inet_ntoa(attr
->nexthop
));
7506 } else if (((p
->family
== AF_INET6
)
7507 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7508 || (safi
== SAFI_EVPN
7509 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7510 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7514 if (attr
->mp_nexthop_len
7515 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7517 json_object_string_add(
7518 json_out
, "mpNexthopGlobalIn",
7521 &attr
->mp_nexthop_global
,
7522 buf_a
, sizeof(buf_a
)));
7527 &attr
->mp_nexthop_global
,
7528 buf_a
, sizeof(buf_a
)));
7529 } else if (attr
->mp_nexthop_len
7530 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7533 &attr
->mp_nexthop_global
,
7534 buf_a
, sizeof(buf_a
));
7536 &attr
->mp_nexthop_local
,
7537 buf_b
, sizeof(buf_b
));
7538 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7539 json_object_string_add(
7541 "mpNexthopGlobalLocal", buf_c
);
7543 vty_out(vty
, "%s(%s)",
7546 &attr
->mp_nexthop_global
,
7547 buf_a
, sizeof(buf_a
)),
7550 &attr
->mp_nexthop_local
,
7551 buf_b
, sizeof(buf_b
)));
7556 label
= decode_label(&path
->extra
->label
[0]);
7558 if (bgp_is_valid_label(&label
)) {
7560 json_object_int_add(json_out
, "notag", label
);
7561 json_object_array_add(json
, json_out
);
7563 vty_out(vty
, "notag/%d", label
);
7569 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7570 struct bgp_path_info
*path
, int display
,
7571 json_object
*json_paths
)
7575 json_object
*json_path
= NULL
;
7578 json_path
= json_object_new_object();
7583 /* short status lead text */
7584 route_vty_short_status_out(vty
, path
, json_path
);
7586 /* print prefix and mask */
7588 route_vty_out_route(p
, vty
, NULL
);
7590 vty_out(vty
, "%*s", 17, " ");
7592 /* Print attribute */
7596 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7600 vty_out(vty
, "%-16s",
7601 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7605 vty_out(vty
, "%s(%s)",
7606 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7608 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7615 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7617 vty_out(vty
, "%s", str
);
7618 XFREE(MTYPE_TMP
, str
);
7620 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7622 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7623 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7626 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7629 if (attr
->ecommunity
) {
7631 struct ecommunity_val
*routermac
= ecommunity_lookup(
7632 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7633 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7635 mac
= ecom_mac2str((char *)routermac
->val
);
7637 vty_out(vty
, "/%s", (char *)mac
);
7638 XFREE(MTYPE_TMP
, mac
);
7646 /* dampening route */
7647 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7648 struct bgp_path_info
*path
, int display
, afi_t afi
,
7649 safi_t safi
, bool use_json
, json_object
*json
)
7653 char timebuf
[BGP_UPTIME_LEN
];
7655 /* short status lead text */
7656 route_vty_short_status_out(vty
, path
, json
);
7658 /* print prefix and mask */
7661 route_vty_out_route(p
, vty
, NULL
);
7663 vty_out(vty
, "%*s", 17, " ");
7666 len
= vty_out(vty
, "%s", path
->peer
->host
);
7670 vty_out(vty
, "\n%*s", 34, " ");
7673 json_object_int_add(json
, "peerHost", len
);
7675 vty_out(vty
, "%*s", len
, " ");
7679 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
7680 safi
, use_json
, json
);
7683 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7684 BGP_UPTIME_LEN
, afi
, safi
,
7687 /* Print attribute */
7693 json_object_string_add(json
, "asPath",
7696 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7701 json_object_string_add(json
, "origin",
7702 bgp_origin_str
[attr
->origin
]);
7704 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7711 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7712 struct bgp_path_info
*path
, int display
, afi_t afi
,
7713 safi_t safi
, bool use_json
, json_object
*json
)
7716 struct bgp_damp_info
*bdi
;
7717 char timebuf
[BGP_UPTIME_LEN
];
7723 bdi
= path
->extra
->damp_info
;
7725 /* short status lead text */
7726 route_vty_short_status_out(vty
, path
, json
);
7728 /* print prefix and mask */
7731 route_vty_out_route(p
, vty
, NULL
);
7733 vty_out(vty
, "%*s", 17, " ");
7736 len
= vty_out(vty
, "%s", path
->peer
->host
);
7740 vty_out(vty
, "\n%*s", 33, " ");
7743 json_object_int_add(json
, "peerHost", len
);
7745 vty_out(vty
, "%*s", len
, " ");
7748 len
= vty_out(vty
, "%d", bdi
->flap
);
7755 json_object_int_add(json
, "bdiFlap", len
);
7757 vty_out(vty
, "%*s", len
, " ");
7761 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7764 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7765 BGP_UPTIME_LEN
, 0, NULL
));
7767 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7768 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7770 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7771 BGP_UPTIME_LEN
, afi
, safi
,
7775 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7776 BGP_UPTIME_LEN
, afi
,
7777 safi
, use_json
, json
));
7780 vty_out(vty
, "%*s ", 8, " ");
7783 /* Print attribute */
7789 json_object_string_add(json
, "asPath",
7792 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7797 json_object_string_add(json
, "origin",
7798 bgp_origin_str
[attr
->origin
]);
7800 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7806 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7807 int *first
, const char *header
,
7808 json_object
*json_adv_to
)
7810 char buf1
[INET6_ADDRSTRLEN
];
7811 json_object
*json_peer
= NULL
;
7814 /* 'advertised-to' is a dictionary of peers we have advertised
7816 * prefix too. The key is the peer's IP or swpX, the value is
7818 * hostname if we know it and "" if not.
7820 json_peer
= json_object_new_object();
7823 json_object_string_add(json_peer
, "hostname",
7827 json_object_object_add(json_adv_to
, peer
->conf_if
,
7830 json_object_object_add(
7832 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7836 vty_out(vty
, "%s", header
);
7841 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7843 vty_out(vty
, " %s(%s)", peer
->hostname
,
7846 vty_out(vty
, " %s(%s)", peer
->hostname
,
7847 sockunion2str(&peer
->su
, buf1
,
7851 vty_out(vty
, " %s", peer
->conf_if
);
7854 sockunion2str(&peer
->su
, buf1
,
7860 static void route_vty_out_tx_ids(struct vty
*vty
,
7861 struct bgp_addpath_info_data
*d
)
7865 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
7866 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
7867 d
->addpath_tx_id
[i
],
7868 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
7872 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7873 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7874 json_object
*json_paths
)
7876 char buf
[INET6_ADDRSTRLEN
];
7878 char buf2
[EVPN_ROUTE_STRLEN
];
7880 int sockunion_vty_out(struct vty
*, union sockunion
*);
7882 json_object
*json_bestpath
= NULL
;
7883 json_object
*json_cluster_list
= NULL
;
7884 json_object
*json_cluster_list_list
= NULL
;
7885 json_object
*json_ext_community
= NULL
;
7886 json_object
*json_last_update
= NULL
;
7887 json_object
*json_pmsi
= NULL
;
7888 json_object
*json_nexthop_global
= NULL
;
7889 json_object
*json_nexthop_ll
= NULL
;
7890 json_object
*json_nexthops
= NULL
;
7891 json_object
*json_path
= NULL
;
7892 json_object
*json_peer
= NULL
;
7893 json_object
*json_string
= NULL
;
7894 json_object
*json_adv_to
= NULL
;
7896 struct listnode
*node
, *nnode
;
7898 int addpath_capable
;
7900 unsigned int first_as
;
7902 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7904 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
7907 json_path
= json_object_new_object();
7908 json_peer
= json_object_new_object();
7909 json_nexthop_global
= json_object_new_object();
7912 if (!json_paths
&& safi
== SAFI_EVPN
) {
7915 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7916 vty_out(vty
, " Route %s", buf2
);
7918 if (path
->extra
&& path
->extra
->num_labels
) {
7919 bgp_evpn_label2str(path
->extra
->label
,
7920 path
->extra
->num_labels
, tag_buf
,
7922 vty_out(vty
, " VNI %s", tag_buf
);
7925 if (path
->extra
&& path
->extra
->parent
) {
7926 struct bgp_path_info
*parent_ri
;
7927 struct bgp_node
*rn
, *prn
;
7929 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7930 rn
= parent_ri
->net
;
7931 if (rn
&& rn
->prn
) {
7933 vty_out(vty
, " Imported from %s:%s\n",
7935 (struct prefix_rd
*)&prn
->p
,
7936 buf1
, sizeof(buf1
)),
7945 /* Line1 display AS-path, Aggregator */
7948 if (!attr
->aspath
->json
)
7949 aspath_str_update(attr
->aspath
, true);
7950 json_object_lock(attr
->aspath
->json
);
7951 json_object_object_add(json_path
, "aspath",
7952 attr
->aspath
->json
);
7954 if (attr
->aspath
->segments
)
7955 aspath_print_vty(vty
, " %s",
7958 vty_out(vty
, " Local");
7962 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7964 json_object_boolean_true_add(json_path
,
7967 vty_out(vty
, ", (removed)");
7970 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7972 json_object_boolean_true_add(json_path
,
7975 vty_out(vty
, ", (stale)");
7978 if (CHECK_FLAG(attr
->flag
,
7979 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7981 json_object_int_add(json_path
, "aggregatorAs",
7982 attr
->aggregator_as
);
7983 json_object_string_add(
7984 json_path
, "aggregatorId",
7985 inet_ntoa(attr
->aggregator_addr
));
7987 vty_out(vty
, ", (aggregated by %u %s)",
7988 attr
->aggregator_as
,
7989 inet_ntoa(attr
->aggregator_addr
));
7993 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7994 PEER_FLAG_REFLECTOR_CLIENT
)) {
7996 json_object_boolean_true_add(
7997 json_path
, "rxedFromRrClient");
7999 vty_out(vty
, ", (Received from a RR-client)");
8002 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8003 PEER_FLAG_RSERVER_CLIENT
)) {
8005 json_object_boolean_true_add(
8006 json_path
, "rxedFromRsClient");
8008 vty_out(vty
, ", (Received from a RS-client)");
8011 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8013 json_object_boolean_true_add(
8014 json_path
, "dampeningHistoryEntry");
8016 vty_out(vty
, ", (history entry)");
8017 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8019 json_object_boolean_true_add(
8020 json_path
, "dampeningSuppressed");
8022 vty_out(vty
, ", (suppressed due to dampening)");
8028 /* Line2 display Next-hop, Neighbor, Router-id */
8029 /* Display the nexthop */
8030 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
8031 || p
->family
== AF_EVPN
)
8032 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8033 || safi
== SAFI_EVPN
8034 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8035 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8036 || safi
== SAFI_EVPN
) {
8038 json_object_string_add(
8039 json_nexthop_global
,
8040 nexthop_fqdn
? "fqdn" : "ip",
8044 attr
->mp_nexthop_global_in
));
8050 attr
->mp_nexthop_global_in
));
8053 json_object_string_add(
8054 json_nexthop_global
,
8055 nexthop_fqdn
? "fqdn" : "ip",
8069 json_object_string_add(json_nexthop_global
,
8073 json_object_string_add(
8074 json_nexthop_global
,
8075 nexthop_fqdn
? "fqdn" : "ip",
8080 &attr
->mp_nexthop_global
,
8083 json_object_string_add(json_nexthop_global
,
8085 json_object_string_add(json_nexthop_global
,
8093 &attr
->mp_nexthop_global
,
8099 /* Display the IGP cost or 'inaccessible' */
8100 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8102 json_object_boolean_false_add(
8103 json_nexthop_global
, "accessible");
8105 vty_out(vty
, " (inaccessible)");
8107 if (path
->extra
&& path
->extra
->igpmetric
) {
8109 json_object_int_add(
8110 json_nexthop_global
, "metric",
8111 path
->extra
->igpmetric
);
8113 vty_out(vty
, " (metric %u)",
8114 path
->extra
->igpmetric
);
8117 /* IGP cost is 0, display this only for json */
8120 json_object_int_add(json_nexthop_global
,
8125 json_object_boolean_true_add(
8126 json_nexthop_global
, "accessible");
8129 /* Display peer "from" output */
8130 /* This path was originated locally */
8131 if (path
->peer
== bgp
->peer_self
) {
8133 if (safi
== SAFI_EVPN
8134 || (p
->family
== AF_INET
8135 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8137 json_object_string_add(
8138 json_peer
, "peerId", "0.0.0.0");
8140 vty_out(vty
, " from 0.0.0.0 ");
8143 json_object_string_add(json_peer
,
8146 vty_out(vty
, " from :: ");
8150 json_object_string_add(
8151 json_peer
, "routerId",
8152 inet_ntoa(bgp
->router_id
));
8154 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8157 /* We RXed this path from one of our peers */
8161 json_object_string_add(
8162 json_peer
, "peerId",
8163 sockunion2str(&path
->peer
->su
, buf
,
8165 json_object_string_add(
8166 json_peer
, "routerId",
8168 &path
->peer
->remote_id
, buf1
,
8171 if (path
->peer
->hostname
)
8172 json_object_string_add(
8173 json_peer
, "hostname",
8174 path
->peer
->hostname
);
8176 if (path
->peer
->domainname
)
8177 json_object_string_add(
8178 json_peer
, "domainname",
8179 path
->peer
->domainname
);
8181 if (path
->peer
->conf_if
)
8182 json_object_string_add(
8183 json_peer
, "interface",
8184 path
->peer
->conf_if
);
8186 if (path
->peer
->conf_if
) {
8187 if (path
->peer
->hostname
8190 BGP_FLAG_SHOW_HOSTNAME
))
8191 vty_out(vty
, " from %s(%s)",
8192 path
->peer
->hostname
,
8193 path
->peer
->conf_if
);
8195 vty_out(vty
, " from %s",
8196 path
->peer
->conf_if
);
8198 if (path
->peer
->hostname
8201 BGP_FLAG_SHOW_HOSTNAME
))
8202 vty_out(vty
, " from %s(%s)",
8203 path
->peer
->hostname
,
8206 vty_out(vty
, " from %s",
8214 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8215 vty_out(vty
, " (%s)",
8216 inet_ntoa(attr
->originator_id
));
8218 vty_out(vty
, " (%s)",
8221 &path
->peer
->remote_id
,
8222 buf1
, sizeof(buf1
)));
8227 * Note when vrfid of nexthop is different from that of prefix
8229 if (path
->extra
&& path
->extra
->bgp_orig
) {
8230 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8235 if (path
->extra
->bgp_orig
->inst_type
8236 == BGP_INSTANCE_TYPE_DEFAULT
)
8238 vn
= VRF_DEFAULT_NAME
;
8240 vn
= path
->extra
->bgp_orig
->name
;
8242 json_object_string_add(json_path
, "nhVrfName",
8245 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8246 json_object_int_add(json_path
,
8249 json_object_int_add(json_path
,
8250 "nhVrfId", (int)nexthop_vrfid
);
8253 if (nexthop_vrfid
== VRF_UNKNOWN
)
8254 vty_out(vty
, " vrf ?");
8256 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8262 json_object_boolean_true_add(json_path
,
8263 "announceNexthopSelf");
8265 vty_out(vty
, " announce-nh-self");
8272 /* display the link-local nexthop */
8273 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8275 json_nexthop_ll
= json_object_new_object();
8276 json_object_string_add(
8278 nexthop_fqdn
? "fqdn" : "ip",
8283 &attr
->mp_nexthop_local
,
8286 json_object_string_add(json_nexthop_ll
, "afi",
8288 json_object_string_add(json_nexthop_ll
, "scope",
8291 json_object_boolean_true_add(json_nexthop_ll
,
8294 if (!attr
->mp_nexthop_prefer_global
)
8295 json_object_boolean_true_add(
8296 json_nexthop_ll
, "used");
8298 json_object_boolean_true_add(
8299 json_nexthop_global
, "used");
8301 vty_out(vty
, " (%s) %s\n",
8303 &attr
->mp_nexthop_local
, buf
,
8305 attr
->mp_nexthop_prefer_global
8310 /* If we do not have a link-local nexthop then we must flag the
8314 json_object_boolean_true_add(
8315 json_nexthop_global
, "used");
8318 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8319 * Int/Ext/Local, Atomic, best */
8321 json_object_string_add(
8322 json_path
, "origin",
8323 bgp_origin_long_str
[attr
->origin
]);
8325 vty_out(vty
, " Origin %s",
8326 bgp_origin_long_str
[attr
->origin
]);
8328 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8332 * Adding "metric" field to match with
8333 * corresponding CLI. "med" will be
8334 * deprecated in future.
8336 json_object_int_add(json_path
, "med",
8338 json_object_int_add(json_path
, "metric",
8341 vty_out(vty
, ", metric %u", attr
->med
);
8344 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8346 json_object_int_add(json_path
, "localpref",
8349 vty_out(vty
, ", localpref %u",
8353 if (attr
->weight
!= 0) {
8355 json_object_int_add(json_path
, "weight",
8358 vty_out(vty
, ", weight %u", attr
->weight
);
8361 if (attr
->tag
!= 0) {
8363 json_object_int_add(json_path
, "tag",
8366 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
8370 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8372 json_object_boolean_false_add(json_path
,
8375 vty_out(vty
, ", invalid");
8376 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8378 json_object_boolean_true_add(json_path
,
8381 vty_out(vty
, ", valid");
8384 if (path
->peer
!= bgp
->peer_self
) {
8385 if (path
->peer
->as
== path
->peer
->local_as
) {
8386 if (CHECK_FLAG(bgp
->config
,
8387 BGP_CONFIG_CONFEDERATION
)) {
8389 json_object_string_add(
8394 ", confed-internal");
8397 json_object_string_add(
8401 vty_out(vty
, ", internal");
8404 if (bgp_confederation_peers_check(
8405 bgp
, path
->peer
->as
)) {
8407 json_object_string_add(
8412 ", confed-external");
8415 json_object_string_add(
8419 vty_out(vty
, ", external");
8422 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8424 json_object_boolean_true_add(json_path
,
8426 json_object_boolean_true_add(json_path
,
8429 vty_out(vty
, ", aggregated, local");
8431 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8433 json_object_boolean_true_add(json_path
,
8436 vty_out(vty
, ", sourced");
8439 json_object_boolean_true_add(json_path
,
8441 json_object_boolean_true_add(json_path
,
8444 vty_out(vty
, ", sourced, local");
8448 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8450 json_object_boolean_true_add(json_path
,
8453 vty_out(vty
, ", atomic-aggregate");
8456 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8457 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8458 && bgp_path_info_mpath_count(path
))) {
8460 json_object_boolean_true_add(json_path
,
8463 vty_out(vty
, ", multipath");
8466 // Mark the bestpath(s)
8467 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8468 first_as
= aspath_get_first_as(attr
->aspath
);
8473 json_object_new_object();
8474 json_object_int_add(json_bestpath
,
8475 "bestpathFromAs", first_as
);
8478 vty_out(vty
, ", bestpath-from-AS %u",
8482 ", bestpath-from-AS Local");
8486 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8490 json_object_new_object();
8491 json_object_boolean_true_add(json_bestpath
,
8494 vty_out(vty
, ", best");
8498 json_object_object_add(json_path
, "bestpath",
8504 /* Line 4 display Community */
8505 if (attr
->community
) {
8507 if (!attr
->community
->json
)
8508 community_str(attr
->community
, true);
8509 json_object_lock(attr
->community
->json
);
8510 json_object_object_add(json_path
, "community",
8511 attr
->community
->json
);
8513 vty_out(vty
, " Community: %s\n",
8514 attr
->community
->str
);
8518 /* Line 5 display Extended-community */
8519 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8521 json_ext_community
= json_object_new_object();
8522 json_object_string_add(json_ext_community
,
8524 attr
->ecommunity
->str
);
8525 json_object_object_add(json_path
,
8526 "extendedCommunity",
8527 json_ext_community
);
8529 vty_out(vty
, " Extended Community: %s\n",
8530 attr
->ecommunity
->str
);
8534 /* Line 6 display Large community */
8535 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8537 if (!attr
->lcommunity
->json
)
8538 lcommunity_str(attr
->lcommunity
, true);
8539 json_object_lock(attr
->lcommunity
->json
);
8540 json_object_object_add(json_path
,
8542 attr
->lcommunity
->json
);
8544 vty_out(vty
, " Large Community: %s\n",
8545 attr
->lcommunity
->str
);
8549 /* Line 7 display Originator, Cluster-id */
8550 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8551 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8553 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8555 json_object_string_add(
8556 json_path
, "originatorId",
8557 inet_ntoa(attr
->originator_id
));
8559 vty_out(vty
, " Originator: %s",
8560 inet_ntoa(attr
->originator_id
));
8563 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8568 json_object_new_object();
8569 json_cluster_list_list
=
8570 json_object_new_array();
8573 i
< attr
->cluster
->length
/ 4;
8575 json_string
= json_object_new_string(
8579 json_object_array_add(
8580 json_cluster_list_list
,
8584 /* struct cluster_list does not have
8586 * aspath and community do. Add this
8589 json_object_string_add(json_cluster_list,
8590 "string", attr->cluster->str);
8592 json_object_object_add(
8593 json_cluster_list
, "list",
8594 json_cluster_list_list
);
8595 json_object_object_add(
8596 json_path
, "clusterList",
8599 vty_out(vty
, ", Cluster list: ");
8602 i
< attr
->cluster
->length
/ 4;
8616 if (path
->extra
&& path
->extra
->damp_info
)
8617 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
8620 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8621 && safi
!= SAFI_EVPN
) {
8622 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8625 json_object_int_add(json_path
, "remoteLabel",
8628 vty_out(vty
, " Remote label: %d\n", label
);
8632 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8634 json_object_int_add(json_path
, "labelIndex",
8637 vty_out(vty
, " Label Index: %d\n",
8641 /* Line 8 display Addpath IDs */
8642 if (path
->addpath_rx_id
8643 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8645 json_object_int_add(json_path
, "addpathRxId",
8646 path
->addpath_rx_id
);
8648 /* Keep backwards compatibility with the old API
8649 * by putting TX All's ID in the old field
8651 json_object_int_add(
8652 json_path
, "addpathTxId",
8653 path
->tx_addpath
.addpath_tx_id
8656 /* ... but create a specific field for each
8659 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8660 json_object_int_add(
8662 bgp_addpath_names(i
)
8668 vty_out(vty
, " AddPath ID: RX %u, ",
8669 path
->addpath_rx_id
);
8671 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8675 /* If we used addpath to TX a non-bestpath we need to display
8676 * "Advertised to" on a path-by-path basis
8678 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8681 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8683 bgp_addpath_encode_tx(peer
, afi
, safi
);
8684 has_adj
= bgp_adj_out_lookup(
8686 bgp_addpath_id_for_peer(
8688 &path
->tx_addpath
));
8690 if ((addpath_capable
&& has_adj
)
8691 || (!addpath_capable
&& has_adj
8692 && CHECK_FLAG(path
->flags
,
8693 BGP_PATH_SELECTED
))) {
8694 if (json_path
&& !json_adv_to
)
8696 json_object_new_object();
8698 route_vty_out_advertised_to(
8707 json_object_object_add(json_path
,
8718 /* Line 9 display Uptime */
8719 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8721 json_last_update
= json_object_new_object();
8722 json_object_int_add(json_last_update
, "epoch", tbuf
);
8723 json_object_string_add(json_last_update
, "string",
8725 json_object_object_add(json_path
, "lastUpdate",
8728 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8730 /* Line 10 display PMSI tunnel attribute, if present */
8731 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8732 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8733 attr
->pmsi_tnl_type
,
8734 PMSI_TNLTYPE_STR_DEFAULT
);
8737 json_pmsi
= json_object_new_object();
8738 json_object_string_add(json_pmsi
,
8740 json_object_int_add(json_pmsi
,
8742 label2vni(&attr
->label
));
8743 json_object_object_add(json_path
, "pmsi",
8747 " PMSI Tunnel Type: %s, label: %d\n",
8748 str
, label2vni(&attr
->label
));
8753 /* We've constructed the json object for this path, add it to the json
8757 if (json_nexthop_global
|| json_nexthop_ll
) {
8758 json_nexthops
= json_object_new_array();
8760 if (json_nexthop_global
)
8761 json_object_array_add(json_nexthops
,
8762 json_nexthop_global
);
8764 if (json_nexthop_ll
)
8765 json_object_array_add(json_nexthops
,
8768 json_object_object_add(json_path
, "nexthops",
8772 json_object_object_add(json_path
, "peer", json_peer
);
8773 json_object_array_add(json_paths
, json_path
);
8778 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8779 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8780 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8782 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8783 const char *prefix_list_str
, afi_t afi
,
8784 safi_t safi
, enum bgp_show_type type
);
8785 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8786 const char *filter
, afi_t afi
, safi_t safi
,
8787 enum bgp_show_type type
);
8788 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8789 const char *rmap_str
, afi_t afi
, safi_t safi
,
8790 enum bgp_show_type type
);
8791 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8792 const char *com
, int exact
, afi_t afi
,
8794 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8795 const char *prefix
, afi_t afi
, safi_t safi
,
8796 enum bgp_show_type type
);
8797 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8798 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8799 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8800 const char *comstr
, int exact
, afi_t afi
,
8801 safi_t safi
, bool use_json
);
8804 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8805 struct bgp_table
*table
, enum bgp_show_type type
,
8806 void *output_arg
, bool use_json
, char *rd
,
8807 int is_last
, unsigned long *output_cum
,
8808 unsigned long *total_cum
,
8809 unsigned long *json_header_depth
)
8811 struct bgp_path_info
*pi
;
8812 struct bgp_node
*rn
;
8815 unsigned long output_count
= 0;
8816 unsigned long total_count
= 0;
8819 json_object
*json_paths
= NULL
;
8822 if (output_cum
&& *output_cum
!= 0)
8825 if (use_json
&& !*json_header_depth
) {
8827 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8828 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
8829 " \"localAS\": %u,\n \"routes\": { ",
8830 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8831 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8834 table
->version
, inet_ntoa(bgp
->router_id
),
8835 bgp
->default_local_pref
, bgp
->as
);
8836 *json_header_depth
= 2;
8838 vty_out(vty
, " \"routeDistinguishers\" : {");
8839 ++*json_header_depth
;
8843 if (use_json
&& rd
) {
8844 vty_out(vty
, " \"%s\" : { ", rd
);
8847 /* Start processing of routes. */
8848 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8849 pi
= bgp_node_get_bgp_path_info(rn
);
8855 json_paths
= json_object_new_array();
8859 for (; pi
; pi
= pi
->next
) {
8861 if (type
== bgp_show_type_flap_statistics
8862 || type
== bgp_show_type_flap_neighbor
8863 || type
== bgp_show_type_dampend_paths
8864 || type
== bgp_show_type_damp_neighbor
) {
8865 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8868 if (type
== bgp_show_type_regexp
) {
8869 regex_t
*regex
= output_arg
;
8871 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8875 if (type
== bgp_show_type_prefix_list
) {
8876 struct prefix_list
*plist
= output_arg
;
8878 if (prefix_list_apply(plist
, &rn
->p
)
8882 if (type
== bgp_show_type_filter_list
) {
8883 struct as_list
*as_list
= output_arg
;
8885 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8886 != AS_FILTER_PERMIT
)
8889 if (type
== bgp_show_type_route_map
) {
8890 struct route_map
*rmap
= output_arg
;
8891 struct bgp_path_info path
;
8892 struct attr dummy_attr
;
8895 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8897 path
.peer
= pi
->peer
;
8898 path
.attr
= &dummy_attr
;
8900 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8902 if (ret
== RMAP_DENYMATCH
)
8905 if (type
== bgp_show_type_neighbor
8906 || type
== bgp_show_type_flap_neighbor
8907 || type
== bgp_show_type_damp_neighbor
) {
8908 union sockunion
*su
= output_arg
;
8910 if (pi
->peer
== NULL
8911 || pi
->peer
->su_remote
== NULL
8912 || !sockunion_same(pi
->peer
->su_remote
, su
))
8915 if (type
== bgp_show_type_cidr_only
) {
8916 uint32_t destination
;
8918 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8919 if (IN_CLASSC(destination
)
8920 && rn
->p
.prefixlen
== 24)
8922 if (IN_CLASSB(destination
)
8923 && rn
->p
.prefixlen
== 16)
8925 if (IN_CLASSA(destination
)
8926 && rn
->p
.prefixlen
== 8)
8929 if (type
== bgp_show_type_prefix_longer
) {
8931 if (!prefix_match(p
, &rn
->p
))
8934 if (type
== bgp_show_type_community_all
) {
8935 if (!pi
->attr
->community
)
8938 if (type
== bgp_show_type_community
) {
8939 struct community
*com
= output_arg
;
8941 if (!pi
->attr
->community
8942 || !community_match(pi
->attr
->community
,
8946 if (type
== bgp_show_type_community_exact
) {
8947 struct community
*com
= output_arg
;
8949 if (!pi
->attr
->community
8950 || !community_cmp(pi
->attr
->community
, com
))
8953 if (type
== bgp_show_type_community_list
) {
8954 struct community_list
*list
= output_arg
;
8956 if (!community_list_match(pi
->attr
->community
,
8960 if (type
== bgp_show_type_community_list_exact
) {
8961 struct community_list
*list
= output_arg
;
8963 if (!community_list_exact_match(
8964 pi
->attr
->community
, list
))
8967 if (type
== bgp_show_type_lcommunity
) {
8968 struct lcommunity
*lcom
= output_arg
;
8970 if (!pi
->attr
->lcommunity
8971 || !lcommunity_match(pi
->attr
->lcommunity
,
8975 if (type
== bgp_show_type_lcommunity_list
) {
8976 struct community_list
*list
= output_arg
;
8978 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8982 if (type
== bgp_show_type_lcommunity_all
) {
8983 if (!pi
->attr
->lcommunity
)
8986 if (type
== bgp_show_type_dampend_paths
8987 || type
== bgp_show_type_damp_neighbor
) {
8988 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8989 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8993 if (!use_json
&& header
) {
8994 vty_out(vty
, "BGP table version is %" PRIu64
8995 ", local router ID is %s, vrf id ",
8997 inet_ntoa(bgp
->router_id
));
8998 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8999 vty_out(vty
, "%s", VRFID_NONE_STR
);
9001 vty_out(vty
, "%u", bgp
->vrf_id
);
9003 vty_out(vty
, "Default local pref %u, ",
9004 bgp
->default_local_pref
);
9005 vty_out(vty
, "local AS %u\n", bgp
->as
);
9006 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9007 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9008 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9009 if (type
== bgp_show_type_dampend_paths
9010 || type
== bgp_show_type_damp_neighbor
)
9011 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9012 else if (type
== bgp_show_type_flap_statistics
9013 || type
== bgp_show_type_flap_neighbor
)
9014 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9016 vty_out(vty
, BGP_SHOW_HEADER
);
9019 if (rd
!= NULL
&& !display
&& !output_count
) {
9022 "Route Distinguisher: %s\n",
9025 if (type
== bgp_show_type_dampend_paths
9026 || type
== bgp_show_type_damp_neighbor
)
9027 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9028 safi
, use_json
, json_paths
);
9029 else if (type
== bgp_show_type_flap_statistics
9030 || type
== bgp_show_type_flap_neighbor
)
9031 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9032 safi
, use_json
, json_paths
);
9034 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9046 if (p
->family
== AF_FLOWSPEC
) {
9047 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9049 bgp_fs_nlri_get_string((unsigned char *)
9050 p
->u
.prefix_flowspec
.ptr
,
9051 p
->u
.prefix_flowspec
9054 NLRI_STRING_FORMAT_MIN
,
9057 vty_out(vty
, "\"%s/%d\": ",
9059 p
->u
.prefix_flowspec
.prefixlen
);
9061 vty_out(vty
, ",\"%s/%d\": ",
9063 p
->u
.prefix_flowspec
.prefixlen
);
9065 prefix2str(p
, buf2
, sizeof(buf2
));
9067 vty_out(vty
, "\"%s\": ", buf2
);
9069 vty_out(vty
, ",\"%s\": ", buf2
);
9072 json_object_to_json_string(json_paths
));
9073 json_object_free(json_paths
);
9080 output_count
+= *output_cum
;
9081 *output_cum
= output_count
;
9084 total_count
+= *total_cum
;
9085 *total_cum
= total_count
;
9089 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9093 for (i
= 0; i
< *json_header_depth
; ++i
)
9094 vty_out(vty
, " } ");
9099 /* No route is displayed */
9100 if (output_count
== 0) {
9101 if (type
== bgp_show_type_normal
)
9103 "No BGP prefixes displayed, %ld exist\n",
9107 "\nDisplayed %ld routes and %ld total paths\n",
9108 output_count
, total_count
);
9115 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9116 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9117 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9119 struct bgp_node
*rn
, *next
;
9120 unsigned long output_cum
= 0;
9121 unsigned long total_cum
= 0;
9122 unsigned long json_header_depth
= 0;
9123 struct bgp_table
*itable
;
9126 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9128 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9129 next
= bgp_route_next(rn
);
9130 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9133 itable
= bgp_node_get_bgp_table_info(rn
);
9134 if (itable
!= NULL
) {
9135 struct prefix_rd prd
;
9136 char rd
[RD_ADDRSTRLEN
];
9138 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9139 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9140 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9141 use_json
, rd
, next
== NULL
, &output_cum
,
9142 &total_cum
, &json_header_depth
);
9148 if (output_cum
== 0)
9149 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9153 "\nDisplayed %ld routes and %ld total paths\n",
9154 output_cum
, total_cum
);
9158 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9159 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9161 struct bgp_table
*table
;
9162 unsigned long json_header_depth
= 0;
9165 bgp
= bgp_get_default();
9170 vty_out(vty
, "No BGP process is configured\n");
9172 vty_out(vty
, "{}\n");
9176 table
= bgp
->rib
[afi
][safi
];
9177 /* use MPLS and ENCAP specific shows until they are merged */
9178 if (safi
== SAFI_MPLS_VPN
) {
9179 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9180 output_arg
, use_json
);
9183 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9184 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9185 output_arg
, use_json
,
9188 /* labeled-unicast routes live in the unicast table */
9189 else if (safi
== SAFI_LABELED_UNICAST
)
9190 safi
= SAFI_UNICAST
;
9192 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9193 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9196 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9197 safi_t safi
, bool use_json
)
9199 struct listnode
*node
, *nnode
;
9202 bool route_output
= false;
9205 vty_out(vty
, "{\n");
9207 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9208 route_output
= true;
9211 vty_out(vty
, ",\n");
9215 vty_out(vty
, "\"%s\":",
9216 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9220 vty_out(vty
, "\nInstance %s:\n",
9221 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9225 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9230 vty_out(vty
, "}\n");
9231 else if (!route_output
)
9232 vty_out(vty
, "%% BGP instance not found\n");
9235 /* Header of detailed BGP route information */
9236 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9237 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9238 afi_t afi
, safi_t safi
, json_object
*json
)
9240 struct bgp_path_info
*pi
;
9243 struct listnode
*node
, *nnode
;
9244 char buf1
[RD_ADDRSTRLEN
];
9245 char buf2
[INET6_ADDRSTRLEN
];
9246 char buf3
[EVPN_ROUTE_STRLEN
];
9247 char prefix_str
[BUFSIZ
];
9252 int route_filter_translated_v4
= 0;
9253 int route_filter_v4
= 0;
9254 int route_filter_translated_v6
= 0;
9255 int route_filter_v6
= 0;
9258 int accept_own_nexthop
= 0;
9261 int no_advertise
= 0;
9265 int has_valid_label
= 0;
9266 mpls_label_t label
= 0;
9267 json_object
*json_adv_to
= NULL
;
9270 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9272 if (has_valid_label
)
9273 label
= label_pton(&rn
->local_label
);
9276 if (has_valid_label
)
9277 json_object_int_add(json
, "localLabel", label
);
9279 json_object_string_add(
9281 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9283 if (safi
== SAFI_EVPN
)
9284 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9285 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9288 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9289 buf3
, sizeof(buf3
)));
9291 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9292 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9293 ? prefix_rd2str(prd
, buf1
,
9296 safi
== SAFI_MPLS_VPN
? ":" : "",
9297 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9301 if (has_valid_label
)
9302 vty_out(vty
, "Local label: %d\n", label
);
9303 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9304 vty_out(vty
, "not allocated\n");
9307 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9309 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9311 if (pi
->extra
&& pi
->extra
->suppress
)
9314 if (pi
->attr
->community
== NULL
)
9317 no_advertise
+= community_include(
9318 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9319 no_export
+= community_include(pi
->attr
->community
,
9320 COMMUNITY_NO_EXPORT
);
9321 local_as
+= community_include(pi
->attr
->community
,
9322 COMMUNITY_LOCAL_AS
);
9323 accept_own
+= community_include(pi
->attr
->community
,
9324 COMMUNITY_ACCEPT_OWN
);
9325 route_filter_translated_v4
+= community_include(
9326 pi
->attr
->community
,
9327 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9328 route_filter_translated_v6
+= community_include(
9329 pi
->attr
->community
,
9330 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9331 route_filter_v4
+= community_include(
9332 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9333 route_filter_v6
+= community_include(
9334 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9335 llgr_stale
+= community_include(pi
->attr
->community
,
9336 COMMUNITY_LLGR_STALE
);
9337 no_llgr
+= community_include(pi
->attr
->community
,
9339 accept_own_nexthop
+=
9340 community_include(pi
->attr
->community
,
9341 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9342 blackhole
+= community_include(pi
->attr
->community
,
9343 COMMUNITY_BLACKHOLE
);
9344 no_peer
+= community_include(pi
->attr
->community
,
9350 vty_out(vty
, "Paths: (%d available", count
);
9352 vty_out(vty
, ", best #%d", best
);
9353 if (safi
== SAFI_UNICAST
)
9354 vty_out(vty
, ", table %s",
9356 == BGP_INSTANCE_TYPE_DEFAULT
)
9360 vty_out(vty
, ", no best path");
9364 ", accept own local route exported and imported in different VRF");
9365 else if (route_filter_translated_v4
)
9367 ", mark translated RTs for VPNv4 route filtering");
9368 else if (route_filter_v4
)
9370 ", attach RT as-is for VPNv4 route filtering");
9371 else if (route_filter_translated_v6
)
9373 ", mark translated RTs for VPNv6 route filtering");
9374 else if (route_filter_v6
)
9376 ", attach RT as-is for VPNv6 route filtering");
9377 else if (llgr_stale
)
9379 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9382 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9383 else if (accept_own_nexthop
)
9385 ", accept local nexthop");
9387 vty_out(vty
, ", inform peer to blackhole prefix");
9389 vty_out(vty
, ", not advertised to EBGP peer");
9390 else if (no_advertise
)
9391 vty_out(vty
, ", not advertised to any peer");
9393 vty_out(vty
, ", not advertised outside local AS");
9396 ", inform EBGP peer not to advertise to their EBGP peers");
9400 ", Advertisements suppressed by an aggregate.");
9401 vty_out(vty
, ")\n");
9404 /* If we are not using addpath then we can display Advertised to and
9406 * show what peers we advertised the bestpath to. If we are using
9408 * though then we must display Advertised to on a path-by-path basis. */
9409 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9410 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9411 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9412 if (json
&& !json_adv_to
)
9413 json_adv_to
= json_object_new_object();
9415 route_vty_out_advertised_to(
9417 " Advertised to non peer-group peers:\n ",
9424 json_object_object_add(json
, "advertisedTo",
9429 vty_out(vty
, " Not advertised to any peer");
9435 /* Display specified route of BGP table. */
9436 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9437 struct bgp_table
*rib
, const char *ip_str
,
9438 afi_t afi
, safi_t safi
,
9439 struct prefix_rd
*prd
, int prefix_check
,
9440 enum bgp_path_type pathtype
, bool use_json
)
9445 struct prefix match
;
9446 struct bgp_node
*rn
;
9447 struct bgp_node
*rm
;
9448 struct bgp_path_info
*pi
;
9449 struct bgp_table
*table
;
9450 json_object
*json
= NULL
;
9451 json_object
*json_paths
= NULL
;
9453 /* Check IP address argument. */
9454 ret
= str2prefix(ip_str
, &match
);
9456 vty_out(vty
, "address is malformed\n");
9460 match
.family
= afi2family(afi
);
9463 json
= json_object_new_object();
9464 json_paths
= json_object_new_array();
9467 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9468 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9469 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9471 table
= bgp_node_get_bgp_table_info(rn
);
9477 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9481 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9482 bgp_unlock_node(rm
);
9486 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
9489 route_vty_out_detail_header(
9491 (struct prefix_rd
*)&rn
->p
,
9492 AFI_IP
, safi
, json
);
9497 if (pathtype
== BGP_PATH_SHOW_ALL
9498 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9499 && CHECK_FLAG(pi
->flags
,
9501 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9502 && (CHECK_FLAG(pi
->flags
,
9504 || CHECK_FLAG(pi
->flags
,
9505 BGP_PATH_SELECTED
))))
9506 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9511 bgp_unlock_node(rm
);
9513 } else if (safi
== SAFI_FLOWSPEC
) {
9514 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9515 &match
, prefix_check
,
9522 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9524 || rn
->p
.prefixlen
== match
.prefixlen
) {
9525 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
9528 route_vty_out_detail_header(
9529 vty
, bgp
, rn
, NULL
, afi
,
9535 if (pathtype
== BGP_PATH_SHOW_ALL
9537 == BGP_PATH_SHOW_BESTPATH
9542 == BGP_PATH_SHOW_MULTIPATH
9548 BGP_PATH_SELECTED
))))
9549 route_vty_out_detail(
9550 vty
, bgp
, &rn
->p
, pi
,
9551 afi
, safi
, json_paths
);
9555 bgp_unlock_node(rn
);
9561 json_object_object_add(json
, "paths", json_paths
);
9563 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9564 json
, JSON_C_TO_STRING_PRETTY
));
9565 json_object_free(json
);
9568 vty_out(vty
, "%% Network not in table\n");
9576 /* Display specified route of Main RIB */
9577 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9578 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9579 int prefix_check
, enum bgp_path_type pathtype
,
9583 bgp
= bgp_get_default();
9586 vty_out(vty
, "No BGP process is configured\n");
9588 vty_out(vty
, "{}\n");
9593 /* labeled-unicast routes live in the unicast table */
9594 if (safi
== SAFI_LABELED_UNICAST
)
9595 safi
= SAFI_UNICAST
;
9597 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9598 afi
, safi
, prd
, prefix_check
, pathtype
,
9602 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9603 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9606 struct lcommunity
*lcom
;
9612 b
= buffer_new(1024);
9613 for (i
= 0; i
< argc
; i
++) {
9615 buffer_putc(b
, ' ');
9617 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9619 buffer_putstr(b
, argv
[i
]->arg
);
9623 buffer_putc(b
, '\0');
9625 str
= buffer_getstr(b
);
9628 lcom
= lcommunity_str2com(str
);
9629 XFREE(MTYPE_TMP
, str
);
9631 vty_out(vty
, "%% Large-community malformed\n");
9635 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9639 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9640 const char *lcom
, afi_t afi
, safi_t safi
,
9643 struct community_list
*list
;
9645 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9646 LARGE_COMMUNITY_LIST_MASTER
);
9648 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9653 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9657 DEFUN (show_ip_bgp_large_community_list
,
9658 show_ip_bgp_large_community_list_cmd
,
9659 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9663 BGP_INSTANCE_HELP_STR
9665 BGP_SAFI_WITH_LABEL_HELP_STR
9666 "Display routes matching the large-community-list\n"
9667 "large-community-list number\n"
9668 "large-community-list name\n"
9672 afi_t afi
= AFI_IP6
;
9673 safi_t safi
= SAFI_UNICAST
;
9676 if (argv_find(argv
, argc
, "ip", &idx
))
9678 if (argv_find(argv
, argc
, "view", &idx
)
9679 || argv_find(argv
, argc
, "vrf", &idx
))
9680 vrf
= argv
[++idx
]->arg
;
9681 if (argv_find(argv
, argc
, "ipv4", &idx
)
9682 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9683 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9684 if (argv_find(argv
, argc
, "unicast", &idx
)
9685 || argv_find(argv
, argc
, "multicast", &idx
))
9686 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9689 bool uj
= use_json(argc
, argv
);
9691 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9693 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9697 argv_find(argv
, argc
, "large-community-list", &idx
);
9698 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9701 DEFUN (show_ip_bgp_large_community
,
9702 show_ip_bgp_large_community_cmd
,
9703 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9707 BGP_INSTANCE_HELP_STR
9709 BGP_SAFI_WITH_LABEL_HELP_STR
9710 "Display routes matching the large-communities\n"
9711 "List of large-community numbers\n"
9715 afi_t afi
= AFI_IP6
;
9716 safi_t safi
= SAFI_UNICAST
;
9719 if (argv_find(argv
, argc
, "ip", &idx
))
9721 if (argv_find(argv
, argc
, "view", &idx
)
9722 || argv_find(argv
, argc
, "vrf", &idx
))
9723 vrf
= argv
[++idx
]->arg
;
9724 if (argv_find(argv
, argc
, "ipv4", &idx
)
9725 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9726 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9727 if (argv_find(argv
, argc
, "unicast", &idx
)
9728 || argv_find(argv
, argc
, "multicast", &idx
))
9729 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9732 bool uj
= use_json(argc
, argv
);
9734 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9736 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9740 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9741 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9743 return bgp_show(vty
, bgp
, afi
, safi
,
9744 bgp_show_type_lcommunity_all
, NULL
, uj
);
9747 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9751 /* BGP route print out function without JSON */
9754 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9755 <dampening <parameters>\
9760 |community-list <(1-500)|WORD> [exact-match]\
9761 |A.B.C.D/M longer-prefixes\
9762 |X:X::X:X/M longer-prefixes\
9767 BGP_INSTANCE_HELP_STR
9769 BGP_SAFI_WITH_LABEL_HELP_STR
9770 "Display detailed information about dampening\n"
9771 "Display detail of configured dampening parameters\n"
9772 "Display routes matching the route-map\n"
9773 "A route-map to match on\n"
9774 "Display routes conforming to the prefix-list\n"
9775 "Prefix-list name\n"
9776 "Display routes conforming to the filter-list\n"
9777 "Regular expression access list name\n"
9778 "BGP RIB advertisement statistics\n"
9779 "Display routes matching the community-list\n"
9780 "community-list number\n"
9781 "community-list name\n"
9782 "Exact match of the communities\n"
9784 "Display route and more specific routes\n"
9786 "Display route and more specific routes\n")
9788 afi_t afi
= AFI_IP6
;
9789 safi_t safi
= SAFI_UNICAST
;
9790 int exact_match
= 0;
9791 struct bgp
*bgp
= NULL
;
9794 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9799 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9800 if (argv_find(argv
, argc
, "parameters", &idx
))
9801 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9804 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9805 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9806 safi
, bgp_show_type_prefix_list
);
9808 if (argv_find(argv
, argc
, "filter-list", &idx
))
9809 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9810 safi
, bgp_show_type_filter_list
);
9812 if (argv_find(argv
, argc
, "statistics", &idx
))
9813 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9815 if (argv_find(argv
, argc
, "route-map", &idx
))
9816 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9817 safi
, bgp_show_type_route_map
);
9819 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9820 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9821 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9823 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9824 exact_match
, afi
, safi
);
9827 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9828 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9829 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9831 bgp_show_type_prefix_longer
);
9836 /* BGP route print out function with JSON */
9837 DEFUN (show_ip_bgp_json
,
9838 show_ip_bgp_json_cmd
,
9839 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9841 |dampening <flap-statistics|dampened-paths>\
9842 |community [AA:NN|local-AS|no-advertise|no-export\
9843 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9844 |accept-own|accept-own-nexthop|route-filter-v6\
9845 |route-filter-v4|route-filter-translated-v6\
9846 |route-filter-translated-v4] [exact-match]\
9851 BGP_INSTANCE_HELP_STR
9853 BGP_SAFI_WITH_LABEL_HELP_STR
9854 "Display only routes with non-natural netmasks\n"
9855 "Display detailed information about dampening\n"
9856 "Display flap statistics of routes\n"
9857 "Display paths suppressed due to dampening\n"
9858 "Display routes matching the communities\n"
9860 "Do not send outside local AS (well-known community)\n"
9861 "Do not advertise to any peer (well-known community)\n"
9862 "Do not export to next AS (well-known community)\n"
9863 "Graceful shutdown (well-known community)\n"
9864 "Do not export to any peer (well-known community)\n"
9865 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9866 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9867 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9868 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9869 "Should accept VPN route with local nexthop (well-known community)\n"
9870 "RT VPNv6 route filtering (well-known community)\n"
9871 "RT VPNv4 route filtering (well-known community)\n"
9872 "RT translated VPNv6 route filtering (well-known community)\n"
9873 "RT translated VPNv4 route filtering (well-known community)\n"
9874 "Exact match of the communities\n"
9877 afi_t afi
= AFI_IP6
;
9878 safi_t safi
= SAFI_UNICAST
;
9879 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9880 struct bgp
*bgp
= NULL
;
9882 int exact_match
= 0;
9883 bool uj
= use_json(argc
, argv
);
9888 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9893 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9894 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9897 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9898 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9899 return bgp_show(vty
, bgp
, afi
, safi
,
9900 bgp_show_type_dampend_paths
, NULL
, uj
);
9901 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9902 return bgp_show(vty
, bgp
, afi
, safi
,
9903 bgp_show_type_flap_statistics
, NULL
,
9907 if (argv_find(argv
, argc
, "community", &idx
)) {
9908 char *maybecomm
= NULL
;
9909 char *community
= NULL
;
9911 if (idx
+ 1 < argc
) {
9912 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
9913 maybecomm
= argv
[idx
+ 1]->arg
;
9915 maybecomm
= argv
[idx
+ 1]->text
;
9918 if (maybecomm
&& !strmatch(maybecomm
, "json")
9919 && !strmatch(maybecomm
, "exact-match"))
9920 community
= maybecomm
;
9922 if (argv_find(argv
, argc
, "exact-match", &idx
))
9926 return bgp_show_community(vty
, bgp
, community
,
9927 exact_match
, afi
, safi
, uj
);
9929 return (bgp_show(vty
, bgp
, afi
, safi
,
9930 bgp_show_type_community_all
, NULL
,
9934 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9937 DEFUN (show_ip_bgp_route
,
9938 show_ip_bgp_route_cmd
,
9939 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9940 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9944 BGP_INSTANCE_HELP_STR
9946 BGP_SAFI_WITH_LABEL_HELP_STR
9947 "Network in the BGP routing table to display\n"
9949 "Network in the BGP routing table to display\n"
9951 "Display only the bestpath\n"
9952 "Display only multipaths\n"
9955 int prefix_check
= 0;
9957 afi_t afi
= AFI_IP6
;
9958 safi_t safi
= SAFI_UNICAST
;
9959 char *prefix
= NULL
;
9960 struct bgp
*bgp
= NULL
;
9961 enum bgp_path_type path_type
;
9962 bool uj
= use_json(argc
, argv
);
9966 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9973 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9977 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9978 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9979 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9981 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9982 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9985 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9986 && afi
!= AFI_IP6
) {
9988 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9991 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9994 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9998 prefix
= argv
[idx
]->arg
;
10000 /* [<bestpath|multipath>] */
10001 if (argv_find(argv
, argc
, "bestpath", &idx
))
10002 path_type
= BGP_PATH_SHOW_BESTPATH
;
10003 else if (argv_find(argv
, argc
, "multipath", &idx
))
10004 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10006 path_type
= BGP_PATH_SHOW_ALL
;
10008 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10012 DEFUN (show_ip_bgp_regexp
,
10013 show_ip_bgp_regexp_cmd
,
10014 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10018 BGP_INSTANCE_HELP_STR
10020 BGP_SAFI_WITH_LABEL_HELP_STR
10021 "Display routes matching the AS path regular expression\n"
10022 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10024 afi_t afi
= AFI_IP6
;
10025 safi_t safi
= SAFI_UNICAST
;
10026 struct bgp
*bgp
= NULL
;
10029 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10032 return CMD_WARNING
;
10034 // get index of regex
10035 argv_find(argv
, argc
, "regexp", &idx
);
10038 char *regstr
= argv_concat(argv
, argc
, idx
);
10039 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10040 bgp_show_type_regexp
);
10041 XFREE(MTYPE_TMP
, regstr
);
10045 DEFUN (show_ip_bgp_instance_all
,
10046 show_ip_bgp_instance_all_cmd
,
10047 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10051 BGP_INSTANCE_ALL_HELP_STR
10053 BGP_SAFI_WITH_LABEL_HELP_STR
10056 afi_t afi
= AFI_IP
;
10057 safi_t safi
= SAFI_UNICAST
;
10058 struct bgp
*bgp
= NULL
;
10060 bool uj
= use_json(argc
, argv
);
10065 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10068 return CMD_WARNING
;
10070 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10071 return CMD_SUCCESS
;
10074 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10075 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10080 if (!config_bgp_aspath_validate(regstr
)) {
10081 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10083 return CMD_WARNING_CONFIG_FAILED
;
10086 regex
= bgp_regcomp(regstr
);
10088 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10089 return CMD_WARNING
;
10092 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10093 bgp_regex_free(regex
);
10097 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10098 const char *prefix_list_str
, afi_t afi
,
10099 safi_t safi
, enum bgp_show_type type
)
10101 struct prefix_list
*plist
;
10103 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10104 if (plist
== NULL
) {
10105 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10107 return CMD_WARNING
;
10110 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10113 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10114 const char *filter
, afi_t afi
, safi_t safi
,
10115 enum bgp_show_type type
)
10117 struct as_list
*as_list
;
10119 as_list
= as_list_lookup(filter
);
10120 if (as_list
== NULL
) {
10121 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10123 return CMD_WARNING
;
10126 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10129 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10130 const char *rmap_str
, afi_t afi
, safi_t safi
,
10131 enum bgp_show_type type
)
10133 struct route_map
*rmap
;
10135 rmap
= route_map_lookup_by_name(rmap_str
);
10137 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10138 return CMD_WARNING
;
10141 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10144 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10145 const char *comstr
, int exact
, afi_t afi
,
10146 safi_t safi
, bool use_json
)
10148 struct community
*com
;
10151 com
= community_str2com(comstr
);
10153 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10154 return CMD_WARNING
;
10157 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10158 (exact
? bgp_show_type_community_exact
10159 : bgp_show_type_community
),
10161 community_free(&com
);
10166 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10167 const char *com
, int exact
, afi_t afi
,
10170 struct community_list
*list
;
10172 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10173 if (list
== NULL
) {
10174 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10175 return CMD_WARNING
;
10178 return bgp_show(vty
, bgp
, afi
, safi
,
10179 (exact
? bgp_show_type_community_list_exact
10180 : bgp_show_type_community_list
),
10184 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10185 const char *prefix
, afi_t afi
, safi_t safi
,
10186 enum bgp_show_type type
)
10193 ret
= str2prefix(prefix
, p
);
10195 vty_out(vty
, "%% Malformed Prefix\n");
10196 return CMD_WARNING
;
10199 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10204 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
10205 const char *ip_str
, bool use_json
)
10209 union sockunion su
;
10211 /* Get peer sockunion. */
10212 ret
= str2sockunion(ip_str
, &su
);
10214 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
10216 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
10220 json_object
*json_no
= NULL
;
10221 json_no
= json_object_new_object();
10222 json_object_string_add(
10224 "malformedAddressOrName",
10226 vty_out(vty
, "%s\n",
10227 json_object_to_json_string_ext(
10229 JSON_C_TO_STRING_PRETTY
));
10230 json_object_free(json_no
);
10233 "%% Malformed address or name: %s\n",
10241 /* Peer structure lookup. */
10242 peer
= peer_lookup(bgp
, &su
);
10245 json_object
*json_no
= NULL
;
10246 json_no
= json_object_new_object();
10247 json_object_string_add(json_no
, "warning",
10248 "No such neighbor in this view/vrf");
10249 vty_out(vty
, "%s\n",
10250 json_object_to_json_string_ext(
10251 json_no
, JSON_C_TO_STRING_PRETTY
));
10252 json_object_free(json_no
);
10254 vty_out(vty
, "No such neighbor in this view/vrf\n");
10262 BGP_STATS_MAXBITLEN
= 0,
10264 BGP_STATS_PREFIXES
,
10266 BGP_STATS_UNAGGREGATEABLE
,
10267 BGP_STATS_MAX_AGGREGATEABLE
,
10268 BGP_STATS_AGGREGATES
,
10270 BGP_STATS_ASPATH_COUNT
,
10271 BGP_STATS_ASPATH_MAXHOPS
,
10272 BGP_STATS_ASPATH_TOTHOPS
,
10273 BGP_STATS_ASPATH_MAXSIZE
,
10274 BGP_STATS_ASPATH_TOTSIZE
,
10275 BGP_STATS_ASN_HIGHEST
,
10279 static const char *table_stats_strs
[] = {
10280 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10281 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10282 [BGP_STATS_RIB
] = "Total Advertisements",
10283 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10284 [BGP_STATS_MAX_AGGREGATEABLE
] =
10285 "Maximum aggregateable prefixes",
10286 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10287 [BGP_STATS_SPACE
] = "Address space advertised",
10288 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10289 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10290 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10291 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10292 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10293 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10294 [BGP_STATS_MAX
] = NULL
,
10297 struct bgp_table_stats
{
10298 struct bgp_table
*table
;
10299 unsigned long long counts
[BGP_STATS_MAX
];
10300 double total_space
;
10304 #define TALLY_SIGFIG 100000
10305 static unsigned long
10306 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10308 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10309 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10310 unsigned long ret
= newtot
/ count
;
10312 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10319 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10320 struct bgp_table_stats
*ts
, unsigned int space
)
10322 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10323 struct bgp_path_info
*pi
;
10328 if (!bgp_node_has_bgp_path_info_data(rn
))
10331 ts
->counts
[BGP_STATS_PREFIXES
]++;
10332 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10335 ts
->counts
[BGP_STATS_AVGPLEN
]
10336 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10337 ts
->counts
[BGP_STATS_AVGPLEN
],
10341 /* check if the prefix is included by any other announcements */
10342 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10343 prn
= bgp_node_parent_nolock(prn
);
10345 if (prn
== NULL
|| prn
== top
) {
10346 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10347 /* announced address space */
10349 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10350 } else if (bgp_node_has_bgp_path_info_data(prn
))
10351 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10354 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10355 ts
->counts
[BGP_STATS_RIB
]++;
10358 && (CHECK_FLAG(pi
->attr
->flag
,
10359 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))))
10360 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10362 /* as-path stats */
10363 if (pi
->attr
&& pi
->attr
->aspath
) {
10364 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10365 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10366 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10368 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10370 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10371 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10373 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10374 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10376 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10377 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10379 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10380 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10381 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10383 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10384 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10385 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10388 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10389 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10394 static int bgp_table_stats_walker(struct thread
*t
)
10396 struct bgp_node
*rn
, *nrn
;
10397 struct bgp_node
*top
;
10398 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10399 unsigned int space
= 0;
10401 if (!(top
= bgp_table_top(ts
->table
)))
10404 switch (ts
->table
->afi
) {
10406 space
= IPV4_MAX_BITLEN
;
10409 space
= IPV6_MAX_BITLEN
;
10415 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10417 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10418 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10419 struct bgp_table
*table
;
10421 table
= bgp_node_get_bgp_table_info(rn
);
10425 top
= bgp_table_top(table
);
10426 for (nrn
= bgp_table_top(table
); nrn
;
10427 nrn
= bgp_route_next(nrn
))
10428 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10430 bgp_table_stats_rn(rn
, top
, ts
, space
);
10437 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10440 struct bgp_table_stats ts
;
10443 if (!bgp
->rib
[afi
][safi
]) {
10444 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10446 return CMD_WARNING
;
10449 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
10451 /* labeled-unicast routes live in the unicast table */
10452 if (safi
== SAFI_LABELED_UNICAST
)
10453 safi
= SAFI_UNICAST
;
10455 memset(&ts
, 0, sizeof(ts
));
10456 ts
.table
= bgp
->rib
[afi
][safi
];
10457 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10459 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10460 if (!table_stats_strs
[i
])
10465 case BGP_STATS_ASPATH_AVGHOPS
:
10466 case BGP_STATS_ASPATH_AVGSIZE
:
10467 case BGP_STATS_AVGPLEN
:
10468 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10469 vty_out (vty
, "%12.2f",
10470 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10473 case BGP_STATS_ASPATH_TOTHOPS
:
10474 case BGP_STATS_ASPATH_TOTSIZE
:
10475 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10476 vty_out(vty
, "%12.2f",
10478 ? (float)ts
.counts
[i
]
10480 [BGP_STATS_ASPATH_COUNT
]
10483 case BGP_STATS_TOTPLEN
:
10484 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10485 vty_out(vty
, "%12.2f",
10487 ? (float)ts
.counts
[i
]
10489 [BGP_STATS_PREFIXES
]
10492 case BGP_STATS_SPACE
:
10493 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10494 vty_out(vty
, "%12g\n", ts
.total_space
);
10496 if (afi
== AFI_IP6
) {
10497 vty_out(vty
, "%30s: ", "/32 equivalent ");
10498 vty_out(vty
, "%12g\n",
10499 ts
.total_space
* pow(2.0, -128 + 32));
10500 vty_out(vty
, "%30s: ", "/48 equivalent ");
10501 vty_out(vty
, "%12g\n",
10502 ts
.total_space
* pow(2.0, -128 + 48));
10504 vty_out(vty
, "%30s: ", "% announced ");
10505 vty_out(vty
, "%12.2f\n",
10506 ts
.total_space
* 100. * pow(2.0, -32));
10507 vty_out(vty
, "%30s: ", "/8 equivalent ");
10508 vty_out(vty
, "%12.2f\n",
10509 ts
.total_space
* pow(2.0, -32 + 8));
10510 vty_out(vty
, "%30s: ", "/24 equivalent ");
10511 vty_out(vty
, "%12.2f\n",
10512 ts
.total_space
* pow(2.0, -32 + 24));
10516 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10517 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10520 vty_out(vty
, "\n");
10522 return CMD_SUCCESS
;
10534 PCOUNT_PFCNT
, /* the figure we display to users */
10538 static const char *pcount_strs
[] = {
10539 [PCOUNT_ADJ_IN
] = "Adj-in",
10540 [PCOUNT_DAMPED
] = "Damped",
10541 [PCOUNT_REMOVED
] = "Removed",
10542 [PCOUNT_HISTORY
] = "History",
10543 [PCOUNT_STALE
] = "Stale",
10544 [PCOUNT_VALID
] = "Valid",
10545 [PCOUNT_ALL
] = "All RIB",
10546 [PCOUNT_COUNTED
] = "PfxCt counted",
10547 [PCOUNT_PFCNT
] = "Useable",
10548 [PCOUNT_MAX
] = NULL
,
10551 struct peer_pcounts
{
10552 unsigned int count
[PCOUNT_MAX
];
10553 const struct peer
*peer
;
10554 const struct bgp_table
*table
;
10557 static int bgp_peer_count_walker(struct thread
*t
)
10559 struct bgp_node
*rn
;
10560 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10561 const struct peer
*peer
= pc
->peer
;
10563 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10564 struct bgp_adj_in
*ain
;
10565 struct bgp_path_info
*pi
;
10567 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10568 if (ain
->peer
== peer
)
10569 pc
->count
[PCOUNT_ADJ_IN
]++;
10571 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10573 if (pi
->peer
!= peer
)
10576 pc
->count
[PCOUNT_ALL
]++;
10578 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10579 pc
->count
[PCOUNT_DAMPED
]++;
10580 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10581 pc
->count
[PCOUNT_HISTORY
]++;
10582 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10583 pc
->count
[PCOUNT_REMOVED
]++;
10584 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10585 pc
->count
[PCOUNT_STALE
]++;
10586 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10587 pc
->count
[PCOUNT_VALID
]++;
10588 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10589 pc
->count
[PCOUNT_PFCNT
]++;
10591 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10592 pc
->count
[PCOUNT_COUNTED
]++;
10593 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10595 EC_LIB_DEVELOPMENT
,
10596 "Attempting to count but flags say it is unusable");
10598 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10600 EC_LIB_DEVELOPMENT
,
10601 "Not counted but flags say we should");
10608 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10609 safi_t safi
, bool use_json
)
10611 struct peer_pcounts pcounts
= {.peer
= peer
};
10613 json_object
*json
= NULL
;
10614 json_object
*json_loop
= NULL
;
10617 json
= json_object_new_object();
10618 json_loop
= json_object_new_object();
10621 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10622 || !peer
->bgp
->rib
[afi
][safi
]) {
10624 json_object_string_add(
10626 "No such neighbor or address family");
10627 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10628 json_object_free(json
);
10630 vty_out(vty
, "%% No such neighbor or address family\n");
10632 return CMD_WARNING
;
10635 memset(&pcounts
, 0, sizeof(pcounts
));
10636 pcounts
.peer
= peer
;
10637 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10639 /* in-place call via thread subsystem so as to record execution time
10640 * stats for the thread-walk (i.e. ensure this can't be blamed on
10641 * on just vty_read()).
10643 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10646 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10647 json_object_string_add(json
, "multiProtocol",
10648 afi_safi_print(afi
, safi
));
10649 json_object_int_add(json
, "pfxCounter",
10650 peer
->pcount
[afi
][safi
]);
10652 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10653 json_object_int_add(json_loop
, pcount_strs
[i
],
10656 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10658 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10659 json_object_string_add(json
, "pfxctDriftFor",
10661 json_object_string_add(
10662 json
, "recommended",
10663 "Please report this bug, with the above command output");
10665 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10666 json
, JSON_C_TO_STRING_PRETTY
));
10667 json_object_free(json
);
10671 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10672 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10673 peer
->hostname
, peer
->host
,
10674 afi_safi_print(afi
, safi
));
10676 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10677 afi_safi_print(afi
, safi
));
10680 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
10681 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10683 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10684 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10687 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10688 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10690 "Please report this bug, with the above command output\n");
10694 return CMD_SUCCESS
;
10697 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10698 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10699 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10700 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10704 BGP_INSTANCE_HELP_STR
10707 "Detailed information on TCP and BGP neighbor connections\n"
10708 "Neighbor to display information about\n"
10709 "Neighbor to display information about\n"
10710 "Neighbor on BGP configured interface\n"
10711 "Display detailed prefix count information\n"
10714 afi_t afi
= AFI_IP6
;
10715 safi_t safi
= SAFI_UNICAST
;
10718 struct bgp
*bgp
= NULL
;
10719 bool uj
= use_json(argc
, argv
);
10724 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10727 return CMD_WARNING
;
10729 argv_find(argv
, argc
, "neighbors", &idx
);
10730 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10732 return CMD_WARNING
;
10734 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10737 #ifdef KEEP_OLD_VPN_COMMANDS
10738 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10739 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10740 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10745 "Display information about all VPNv4 NLRIs\n"
10746 "Detailed information on TCP and BGP neighbor connections\n"
10747 "Neighbor to display information about\n"
10748 "Neighbor to display information about\n"
10749 "Neighbor on BGP configured interface\n"
10750 "Display detailed prefix count information\n"
10755 bool uj
= use_json(argc
, argv
);
10757 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10759 return CMD_WARNING
;
10761 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10764 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10765 show_ip_bgp_vpn_all_route_prefix_cmd
,
10766 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10771 "Display information about all VPNv4 NLRIs\n"
10772 "Network in the BGP routing table to display\n"
10773 "Network in the BGP routing table to display\n"
10777 char *network
= NULL
;
10778 struct bgp
*bgp
= bgp_get_default();
10780 vty_out(vty
, "Can't find default instance\n");
10781 return CMD_WARNING
;
10784 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10785 network
= argv
[idx
]->arg
;
10786 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10787 network
= argv
[idx
]->arg
;
10789 vty_out(vty
, "Unable to figure out Network\n");
10790 return CMD_WARNING
;
10793 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10794 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10796 #endif /* KEEP_OLD_VPN_COMMANDS */
10798 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10799 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10800 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10806 "Display information about all EVPN NLRIs\n"
10807 "Network in the BGP routing table to display\n"
10808 "Network in the BGP routing table to display\n"
10812 char *network
= NULL
;
10814 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10815 network
= argv
[idx
]->arg
;
10816 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10817 network
= argv
[idx
]->arg
;
10819 vty_out(vty
, "Unable to figure out Network\n");
10820 return CMD_WARNING
;
10822 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10823 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10826 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10827 safi_t safi
, enum bgp_show_adj_route_type type
,
10828 const char *rmap_name
, bool use_json
,
10831 struct bgp_table
*table
;
10832 struct bgp_adj_in
*ain
;
10833 struct bgp_adj_out
*adj
;
10834 unsigned long output_count
;
10835 unsigned long filtered_count
;
10836 struct bgp_node
*rn
;
10842 struct update_subgroup
*subgrp
;
10843 json_object
*json_scode
= NULL
;
10844 json_object
*json_ocode
= NULL
;
10845 json_object
*json_ar
= NULL
;
10846 struct peer_af
*paf
;
10847 bool route_filtered
;
10850 json_scode
= json_object_new_object();
10851 json_ocode
= json_object_new_object();
10852 json_ar
= json_object_new_object();
10854 json_object_string_add(json_scode
, "suppressed", "s");
10855 json_object_string_add(json_scode
, "damped", "d");
10856 json_object_string_add(json_scode
, "history", "h");
10857 json_object_string_add(json_scode
, "valid", "*");
10858 json_object_string_add(json_scode
, "best", ">");
10859 json_object_string_add(json_scode
, "multipath", "=");
10860 json_object_string_add(json_scode
, "internal", "i");
10861 json_object_string_add(json_scode
, "ribFailure", "r");
10862 json_object_string_add(json_scode
, "stale", "S");
10863 json_object_string_add(json_scode
, "removed", "R");
10865 json_object_string_add(json_ocode
, "igp", "i");
10866 json_object_string_add(json_ocode
, "egp", "e");
10867 json_object_string_add(json_ocode
, "incomplete", "?");
10874 json_object_string_add(json
, "alert", "no BGP");
10875 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10876 json_object_free(json
);
10878 vty_out(vty
, "%% No bgp\n");
10882 /* labeled-unicast routes live in the unicast table */
10883 if (safi
== SAFI_LABELED_UNICAST
)
10884 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
10886 table
= bgp
->rib
[afi
][safi
];
10888 output_count
= filtered_count
= 0;
10889 subgrp
= peer_subgroup(peer
, afi
, safi
);
10891 if (type
== bgp_show_adj_route_advertised
&& subgrp
10892 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10894 json_object_int_add(json
, "bgpTableVersion",
10896 json_object_string_add(json
, "bgpLocalRouterId",
10897 inet_ntoa(bgp
->router_id
));
10898 json_object_int_add(json
, "defaultLocPrf",
10899 bgp
->default_local_pref
);
10900 json_object_int_add(json
, "localAS", bgp
->as
);
10901 json_object_object_add(json
, "bgpStatusCodes",
10903 json_object_object_add(json
, "bgpOriginCodes",
10905 json_object_string_add(
10906 json
, "bgpOriginatingDefaultNetwork",
10907 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10909 vty_out(vty
, "BGP table version is %" PRIu64
10910 ", local router ID is %s, vrf id ",
10911 table
->version
, inet_ntoa(bgp
->router_id
));
10912 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10913 vty_out(vty
, "%s", VRFID_NONE_STR
);
10915 vty_out(vty
, "%u", bgp
->vrf_id
);
10916 vty_out(vty
, "\n");
10917 vty_out(vty
, "Default local pref %u, ",
10918 bgp
->default_local_pref
);
10919 vty_out(vty
, "local AS %u\n", bgp
->as
);
10920 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10921 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10922 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10924 vty_out(vty
, "Originating default network %s\n\n",
10925 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10930 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10931 if (type
== bgp_show_adj_route_received
10932 || type
== bgp_show_adj_route_filtered
) {
10933 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10934 if (ain
->peer
!= peer
|| !ain
->attr
)
10939 json_object_int_add(
10940 json
, "bgpTableVersion",
10942 json_object_string_add(
10944 "bgpLocalRouterId",
10947 json_object_int_add(json
,
10949 bgp
->default_local_pref
);
10950 json_object_int_add(json
,
10951 "localAS", bgp
->as
);
10952 json_object_object_add(
10953 json
, "bgpStatusCodes",
10955 json_object_object_add(
10956 json
, "bgpOriginCodes",
10960 "BGP table version is 0, local router ID is %s, vrf id ",
10963 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10969 vty_out(vty
, "\n");
10971 "Default local pref %u, ",
10972 bgp
->default_local_pref
);
10973 vty_out(vty
, "local AS %u\n",
10976 BGP_SHOW_SCODE_HEADER
);
10978 BGP_SHOW_NCODE_HEADER
);
10980 BGP_SHOW_OCODE_HEADER
);
10986 vty_out(vty
, BGP_SHOW_HEADER
);
10990 bgp_attr_dup(&attr
, ain
->attr
);
10991 route_filtered
= false;
10993 /* Filter prefix using distribute list,
10994 * filter list or prefix list
10996 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10997 safi
)) == FILTER_DENY
)
10998 route_filtered
= true;
11000 /* Filter prefix using route-map */
11001 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11002 afi
, safi
, rmap_name
);
11004 if (type
== bgp_show_adj_route_filtered
&&
11005 !route_filtered
&& ret
!= RMAP_DENY
) {
11006 bgp_attr_undup(&attr
, ain
->attr
);
11010 if (type
== bgp_show_adj_route_received
&&
11011 (route_filtered
|| ret
== RMAP_DENY
))
11014 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11015 use_json
, json_ar
);
11016 bgp_attr_undup(&attr
, ain
->attr
);
11019 } else if (type
== bgp_show_adj_route_advertised
) {
11020 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11021 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11022 if (paf
->peer
!= peer
|| !adj
->attr
)
11027 json_object_int_add(
11031 json_object_string_add(
11033 "bgpLocalRouterId",
11036 json_object_int_add(
11037 json
, "defaultLocPrf",
11038 bgp
->default_local_pref
11040 json_object_int_add(
11043 json_object_object_add(
11047 json_object_object_add(
11053 "BGP table version is %" PRIu64
11054 ", local router ID is %s, vrf id ",
11067 vty_out(vty
, "\n");
11069 "Default local pref %u, ",
11070 bgp
->default_local_pref
11076 BGP_SHOW_SCODE_HEADER
);
11078 BGP_SHOW_NCODE_HEADER
);
11080 BGP_SHOW_OCODE_HEADER
);
11091 bgp_attr_dup(&attr
, adj
->attr
);
11092 ret
= bgp_output_modifier(
11093 peer
, &rn
->p
, &attr
, afi
, safi
,
11096 if (ret
!= RMAP_DENY
) {
11097 route_vty_out_tmp(vty
, &rn
->p
,
11106 bgp_attr_undup(&attr
, adj
->attr
);
11112 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11113 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11114 json_object_int_add(json
, "filteredPrefixCounter",
11117 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11118 json
, JSON_C_TO_STRING_PRETTY
));
11119 json_object_free(json
);
11120 } else if (output_count
> 0) {
11121 if (filtered_count
> 0)
11123 "\nTotal number of prefixes %ld (%ld filtered)\n",
11124 output_count
, filtered_count
);
11126 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11131 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11132 safi_t safi
, enum bgp_show_adj_route_type type
,
11133 const char *rmap_name
, bool use_json
)
11135 json_object
*json
= NULL
;
11138 json
= json_object_new_object();
11140 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11142 json_object_string_add(
11144 "No such neighbor or address family");
11145 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11146 json_object_free(json
);
11148 vty_out(vty
, "%% No such neighbor or address family\n");
11150 return CMD_WARNING
;
11153 if ((type
== bgp_show_adj_route_received
11154 || type
== bgp_show_adj_route_filtered
)
11155 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11156 PEER_FLAG_SOFT_RECONFIG
)) {
11158 json_object_string_add(
11160 "Inbound soft reconfiguration not enabled");
11161 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11162 json_object_free(json
);
11165 "%% Inbound soft reconfiguration not enabled\n");
11167 return CMD_WARNING
;
11170 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11172 return CMD_SUCCESS
;
11175 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11176 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11177 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11178 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11182 BGP_INSTANCE_HELP_STR
11184 BGP_SAFI_WITH_LABEL_HELP_STR
11185 "Detailed information on TCP and BGP neighbor connections\n"
11186 "Neighbor to display information about\n"
11187 "Neighbor to display information about\n"
11188 "Neighbor on BGP configured interface\n"
11189 "Display the routes advertised to a BGP neighbor\n"
11190 "Display the received routes from neighbor\n"
11191 "Display the filtered routes received from neighbor\n"
11192 "Route-map to modify the attributes\n"
11193 "Name of the route map\n"
11196 afi_t afi
= AFI_IP6
;
11197 safi_t safi
= SAFI_UNICAST
;
11198 char *rmap_name
= NULL
;
11199 char *peerstr
= NULL
;
11200 struct bgp
*bgp
= NULL
;
11202 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11204 bool uj
= use_json(argc
, argv
);
11209 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11212 return CMD_WARNING
;
11214 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11215 argv_find(argv
, argc
, "neighbors", &idx
);
11216 peerstr
= argv
[++idx
]->arg
;
11218 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11220 return CMD_WARNING
;
11222 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11223 type
= bgp_show_adj_route_advertised
;
11224 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11225 type
= bgp_show_adj_route_received
;
11226 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11227 type
= bgp_show_adj_route_filtered
;
11229 if (argv_find(argv
, argc
, "route-map", &idx
))
11230 rmap_name
= argv
[++idx
]->arg
;
11232 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11235 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11236 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11237 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11243 "Address Family modifier\n"
11244 "Detailed information on TCP and BGP neighbor connections\n"
11245 "Neighbor to display information about\n"
11246 "Neighbor to display information about\n"
11247 "Neighbor on BGP configured interface\n"
11248 "Display information received from a BGP neighbor\n"
11249 "Display the prefixlist filter\n"
11252 afi_t afi
= AFI_IP6
;
11253 safi_t safi
= SAFI_UNICAST
;
11254 char *peerstr
= NULL
;
11257 union sockunion su
;
11263 /* show [ip] bgp */
11264 if (argv_find(argv
, argc
, "ip", &idx
))
11266 /* [<ipv4|ipv6> [unicast]] */
11267 if (argv_find(argv
, argc
, "ipv4", &idx
))
11269 if (argv_find(argv
, argc
, "ipv6", &idx
))
11271 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11272 argv_find(argv
, argc
, "neighbors", &idx
);
11273 peerstr
= argv
[++idx
]->arg
;
11275 bool uj
= use_json(argc
, argv
);
11277 ret
= str2sockunion(peerstr
, &su
);
11279 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11282 vty_out(vty
, "{}\n");
11285 "%% Malformed address or name: %s\n",
11287 return CMD_WARNING
;
11290 peer
= peer_lookup(NULL
, &su
);
11293 vty_out(vty
, "{}\n");
11295 vty_out(vty
, "No peer\n");
11296 return CMD_WARNING
;
11300 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11301 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11304 vty_out(vty
, "Address Family: %s\n",
11305 afi_safi_print(afi
, safi
));
11306 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11309 vty_out(vty
, "{}\n");
11311 vty_out(vty
, "No functional output\n");
11314 return CMD_SUCCESS
;
11317 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11318 afi_t afi
, safi_t safi
,
11319 enum bgp_show_type type
, bool use_json
)
11321 /* labeled-unicast routes live in the unicast table */
11322 if (safi
== SAFI_LABELED_UNICAST
)
11323 safi
= SAFI_UNICAST
;
11325 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11327 json_object
*json_no
= NULL
;
11328 json_no
= json_object_new_object();
11329 json_object_string_add(
11330 json_no
, "warning",
11331 "No such neighbor or address family");
11332 vty_out(vty
, "%s\n",
11333 json_object_to_json_string(json_no
));
11334 json_object_free(json_no
);
11336 vty_out(vty
, "%% No such neighbor or address family\n");
11337 return CMD_WARNING
;
11340 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11343 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11344 show_ip_bgp_flowspec_routes_detailed_cmd
,
11345 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11349 BGP_INSTANCE_HELP_STR
11352 "Detailed information on flowspec entries\n"
11355 afi_t afi
= AFI_IP
;
11356 safi_t safi
= SAFI_UNICAST
;
11357 struct bgp
*bgp
= NULL
;
11359 bool uj
= use_json(argc
, argv
);
11364 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11367 return CMD_WARNING
;
11369 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11372 DEFUN (show_ip_bgp_neighbor_routes
,
11373 show_ip_bgp_neighbor_routes_cmd
,
11374 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11375 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11379 BGP_INSTANCE_HELP_STR
11381 BGP_SAFI_WITH_LABEL_HELP_STR
11382 "Detailed information on TCP and BGP neighbor connections\n"
11383 "Neighbor to display information about\n"
11384 "Neighbor to display information about\n"
11385 "Neighbor on BGP configured interface\n"
11386 "Display flap statistics of the routes learned from neighbor\n"
11387 "Display the dampened routes received from neighbor\n"
11388 "Display routes learned from neighbor\n"
11391 char *peerstr
= NULL
;
11392 struct bgp
*bgp
= NULL
;
11393 afi_t afi
= AFI_IP6
;
11394 safi_t safi
= SAFI_UNICAST
;
11396 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11398 bool uj
= use_json(argc
, argv
);
11403 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11406 return CMD_WARNING
;
11408 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11409 argv_find(argv
, argc
, "neighbors", &idx
);
11410 peerstr
= argv
[++idx
]->arg
;
11412 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11414 return CMD_WARNING
;
11416 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11417 sh_type
= bgp_show_type_flap_neighbor
;
11418 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11419 sh_type
= bgp_show_type_damp_neighbor
;
11420 else if (argv_find(argv
, argc
, "routes", &idx
))
11421 sh_type
= bgp_show_type_neighbor
;
11423 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11426 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11428 struct bgp_distance
{
11429 /* Distance value for the IP source prefix. */
11432 /* Name of the access-list to be matched. */
11436 DEFUN (show_bgp_afi_vpn_rd_route
,
11437 show_bgp_afi_vpn_rd_route_cmd
,
11438 "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]",
11442 "Address Family modifier\n"
11443 "Display information for a route distinguisher\n"
11444 "Route Distinguisher\n"
11445 "Network in the BGP routing table to display\n"
11446 "Network in the BGP routing table to display\n"
11450 struct prefix_rd prd
;
11451 afi_t afi
= AFI_MAX
;
11454 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11455 vty_out(vty
, "%% Malformed Address Family\n");
11456 return CMD_WARNING
;
11459 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11461 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11462 return CMD_WARNING
;
11465 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11466 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11469 static struct bgp_distance
*bgp_distance_new(void)
11471 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11474 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11476 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11479 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11480 const char *ip_str
, const char *access_list_str
)
11487 struct bgp_node
*rn
;
11488 struct bgp_distance
*bdistance
;
11490 afi
= bgp_node_afi(vty
);
11491 safi
= bgp_node_safi(vty
);
11493 ret
= str2prefix(ip_str
, &p
);
11495 vty_out(vty
, "Malformed prefix\n");
11496 return CMD_WARNING_CONFIG_FAILED
;
11499 distance
= atoi(distance_str
);
11501 /* Get BGP distance node. */
11502 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11503 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11505 bgp_unlock_node(rn
);
11507 bdistance
= bgp_distance_new();
11508 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11511 /* Set distance value. */
11512 bdistance
->distance
= distance
;
11514 /* Reset access-list configuration. */
11515 if (bdistance
->access_list
) {
11516 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11517 bdistance
->access_list
= NULL
;
11519 if (access_list_str
)
11520 bdistance
->access_list
=
11521 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11523 return CMD_SUCCESS
;
11526 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11527 const char *ip_str
, const char *access_list_str
)
11534 struct bgp_node
*rn
;
11535 struct bgp_distance
*bdistance
;
11537 afi
= bgp_node_afi(vty
);
11538 safi
= bgp_node_safi(vty
);
11540 ret
= str2prefix(ip_str
, &p
);
11542 vty_out(vty
, "Malformed prefix\n");
11543 return CMD_WARNING_CONFIG_FAILED
;
11546 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11547 (struct prefix
*)&p
);
11549 vty_out(vty
, "Can't find specified prefix\n");
11550 return CMD_WARNING_CONFIG_FAILED
;
11553 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11554 distance
= atoi(distance_str
);
11556 if (bdistance
->distance
!= distance
) {
11557 vty_out(vty
, "Distance does not match configured\n");
11558 return CMD_WARNING_CONFIG_FAILED
;
11561 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11562 bgp_distance_free(bdistance
);
11564 bgp_node_set_bgp_path_info(rn
, NULL
);
11565 bgp_unlock_node(rn
);
11566 bgp_unlock_node(rn
);
11568 return CMD_SUCCESS
;
11571 /* Apply BGP information to distance method. */
11572 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11573 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11575 struct bgp_node
*rn
;
11578 struct bgp_distance
*bdistance
;
11579 struct access_list
*alist
;
11580 struct bgp_static
*bgp_static
;
11585 peer
= pinfo
->peer
;
11587 /* Check source address. */
11588 sockunion2hostprefix(&peer
->su
, &q
);
11589 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11591 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11592 bgp_unlock_node(rn
);
11594 if (bdistance
->access_list
) {
11595 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11597 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11598 return bdistance
->distance
;
11600 return bdistance
->distance
;
11603 /* Backdoor check. */
11604 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11606 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11607 bgp_unlock_node(rn
);
11609 if (bgp_static
->backdoor
) {
11610 if (bgp
->distance_local
[afi
][safi
])
11611 return bgp
->distance_local
[afi
][safi
];
11613 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11617 if (peer
->sort
== BGP_PEER_EBGP
) {
11618 if (bgp
->distance_ebgp
[afi
][safi
])
11619 return bgp
->distance_ebgp
[afi
][safi
];
11620 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11622 if (bgp
->distance_ibgp
[afi
][safi
])
11623 return bgp
->distance_ibgp
[afi
][safi
];
11624 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11628 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
11629 * we should tell ZEBRA update the routes for a specific
11630 * AFI/SAFI to reflect changes in RIB.
11632 static void bgp_announce_routes_distance_update(struct bgp
*bgp
)
11637 FOREACH_AFI_SAFI (afi
, safi
) {
11638 if (!bgp_fibupd_safi(safi
))
11641 if (bgp
->distance_ebgp
[afi
][safi
]
11642 && bgp
->distance_ibgp
[afi
][safi
]
11643 && bgp
->distance_local
[afi
][safi
]) {
11644 if (BGP_DEBUG(zebra
, ZEBRA
))
11646 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
11647 __func__
, afi
, safi
);
11648 bgp_zebra_announce_table(bgp
, afi
, safi
);
11653 DEFUN (bgp_distance
,
11655 "distance bgp (1-255) (1-255) (1-255)",
11656 "Define an administrative distance\n"
11658 "Distance for routes external to the AS\n"
11659 "Distance for routes internal to the AS\n"
11660 "Distance for local routes\n")
11662 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11663 int idx_number
= 2;
11664 int idx_number_2
= 3;
11665 int idx_number_3
= 4;
11669 afi
= bgp_node_afi(vty
);
11670 safi
= bgp_node_safi(vty
);
11672 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11673 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11674 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11675 bgp_announce_routes_distance_update(bgp
);
11676 return CMD_SUCCESS
;
11679 DEFUN (no_bgp_distance
,
11680 no_bgp_distance_cmd
,
11681 "no distance bgp [(1-255) (1-255) (1-255)]",
11683 "Define an administrative distance\n"
11685 "Distance for routes external to the AS\n"
11686 "Distance for routes internal to the AS\n"
11687 "Distance for local routes\n")
11689 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11693 afi
= bgp_node_afi(vty
);
11694 safi
= bgp_node_safi(vty
);
11696 bgp
->distance_ebgp
[afi
][safi
] = 0;
11697 bgp
->distance_ibgp
[afi
][safi
] = 0;
11698 bgp
->distance_local
[afi
][safi
] = 0;
11699 bgp_announce_routes_distance_update(bgp
);
11700 return CMD_SUCCESS
;
11704 DEFUN (bgp_distance_source
,
11705 bgp_distance_source_cmd
,
11706 "distance (1-255) A.B.C.D/M",
11707 "Define an administrative distance\n"
11708 "Administrative distance\n"
11709 "IP source prefix\n")
11711 int idx_number
= 1;
11712 int idx_ipv4_prefixlen
= 2;
11713 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11714 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11715 return CMD_SUCCESS
;
11718 DEFUN (no_bgp_distance_source
,
11719 no_bgp_distance_source_cmd
,
11720 "no distance (1-255) A.B.C.D/M",
11722 "Define an administrative distance\n"
11723 "Administrative distance\n"
11724 "IP source prefix\n")
11726 int idx_number
= 2;
11727 int idx_ipv4_prefixlen
= 3;
11728 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11729 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11730 return CMD_SUCCESS
;
11733 DEFUN (bgp_distance_source_access_list
,
11734 bgp_distance_source_access_list_cmd
,
11735 "distance (1-255) A.B.C.D/M WORD",
11736 "Define an administrative distance\n"
11737 "Administrative distance\n"
11738 "IP source prefix\n"
11739 "Access list name\n")
11741 int idx_number
= 1;
11742 int idx_ipv4_prefixlen
= 2;
11744 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11745 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11746 return CMD_SUCCESS
;
11749 DEFUN (no_bgp_distance_source_access_list
,
11750 no_bgp_distance_source_access_list_cmd
,
11751 "no distance (1-255) A.B.C.D/M WORD",
11753 "Define an administrative distance\n"
11754 "Administrative distance\n"
11755 "IP source prefix\n"
11756 "Access list name\n")
11758 int idx_number
= 2;
11759 int idx_ipv4_prefixlen
= 3;
11761 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11762 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11763 return CMD_SUCCESS
;
11766 DEFUN (ipv6_bgp_distance_source
,
11767 ipv6_bgp_distance_source_cmd
,
11768 "distance (1-255) X:X::X:X/M",
11769 "Define an administrative distance\n"
11770 "Administrative distance\n"
11771 "IP source prefix\n")
11773 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11774 return CMD_SUCCESS
;
11777 DEFUN (no_ipv6_bgp_distance_source
,
11778 no_ipv6_bgp_distance_source_cmd
,
11779 "no distance (1-255) X:X::X:X/M",
11781 "Define an administrative distance\n"
11782 "Administrative distance\n"
11783 "IP source prefix\n")
11785 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11786 return CMD_SUCCESS
;
11789 DEFUN (ipv6_bgp_distance_source_access_list
,
11790 ipv6_bgp_distance_source_access_list_cmd
,
11791 "distance (1-255) X:X::X:X/M WORD",
11792 "Define an administrative distance\n"
11793 "Administrative distance\n"
11794 "IP source prefix\n"
11795 "Access list name\n")
11797 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11798 return CMD_SUCCESS
;
11801 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11802 no_ipv6_bgp_distance_source_access_list_cmd
,
11803 "no distance (1-255) X:X::X:X/M WORD",
11805 "Define an administrative distance\n"
11806 "Administrative distance\n"
11807 "IP source prefix\n"
11808 "Access list name\n")
11810 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11811 return CMD_SUCCESS
;
11814 DEFUN (bgp_damp_set
,
11816 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11817 "BGP Specific commands\n"
11818 "Enable route-flap dampening\n"
11819 "Half-life time for the penalty\n"
11820 "Value to start reusing a route\n"
11821 "Value to start suppressing a route\n"
11822 "Maximum duration to suppress a stable route\n")
11824 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11825 int idx_half_life
= 2;
11827 int idx_suppress
= 4;
11828 int idx_max_suppress
= 5;
11829 int half
= DEFAULT_HALF_LIFE
* 60;
11830 int reuse
= DEFAULT_REUSE
;
11831 int suppress
= DEFAULT_SUPPRESS
;
11832 int max
= 4 * half
;
11835 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11836 reuse
= atoi(argv
[idx_reuse
]->arg
);
11837 suppress
= atoi(argv
[idx_suppress
]->arg
);
11838 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11839 } else if (argc
== 3) {
11840 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11844 if (suppress
< reuse
) {
11846 "Suppress value cannot be less than reuse value \n");
11850 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11851 reuse
, suppress
, max
);
11854 DEFUN (bgp_damp_unset
,
11855 bgp_damp_unset_cmd
,
11856 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11858 "BGP Specific commands\n"
11859 "Enable route-flap dampening\n"
11860 "Half-life time for the penalty\n"
11861 "Value to start reusing a route\n"
11862 "Value to start suppressing a route\n"
11863 "Maximum duration to suppress a stable route\n")
11865 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11866 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11869 /* Display specified route of BGP table. */
11870 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11871 const char *ip_str
, afi_t afi
, safi_t safi
,
11872 struct prefix_rd
*prd
, int prefix_check
)
11875 struct prefix match
;
11876 struct bgp_node
*rn
;
11877 struct bgp_node
*rm
;
11878 struct bgp_path_info
*pi
;
11879 struct bgp_path_info
*pi_temp
;
11881 struct bgp_table
*table
;
11883 /* BGP structure lookup. */
11885 bgp
= bgp_lookup_by_name(view_name
);
11887 vty_out(vty
, "%% Can't find BGP instance %s\n",
11889 return CMD_WARNING
;
11892 bgp
= bgp_get_default();
11894 vty_out(vty
, "%% No BGP process is configured\n");
11895 return CMD_WARNING
;
11899 /* Check IP address argument. */
11900 ret
= str2prefix(ip_str
, &match
);
11902 vty_out(vty
, "%% address is malformed\n");
11903 return CMD_WARNING
;
11906 match
.family
= afi2family(afi
);
11908 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11909 || (safi
== SAFI_EVPN
)) {
11910 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11911 rn
= bgp_route_next(rn
)) {
11912 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11914 table
= bgp_node_get_bgp_table_info(rn
);
11917 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11921 || rm
->p
.prefixlen
== match
.prefixlen
) {
11922 pi
= bgp_node_get_bgp_path_info(rm
);
11924 if (pi
->extra
&& pi
->extra
->damp_info
) {
11925 pi_temp
= pi
->next
;
11926 bgp_damp_info_free(
11927 pi
->extra
->damp_info
,
11935 bgp_unlock_node(rm
);
11938 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11941 || rn
->p
.prefixlen
== match
.prefixlen
) {
11942 pi
= bgp_node_get_bgp_path_info(rn
);
11944 if (pi
->extra
&& pi
->extra
->damp_info
) {
11945 pi_temp
= pi
->next
;
11946 bgp_damp_info_free(
11947 pi
->extra
->damp_info
,
11955 bgp_unlock_node(rn
);
11959 return CMD_SUCCESS
;
11962 DEFUN (clear_ip_bgp_dampening
,
11963 clear_ip_bgp_dampening_cmd
,
11964 "clear ip bgp dampening",
11968 "Clear route flap dampening information\n")
11970 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
11971 return CMD_SUCCESS
;
11974 DEFUN (clear_ip_bgp_dampening_prefix
,
11975 clear_ip_bgp_dampening_prefix_cmd
,
11976 "clear ip bgp dampening A.B.C.D/M",
11980 "Clear route flap dampening information\n"
11983 int idx_ipv4_prefixlen
= 4;
11984 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11985 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11988 DEFUN (clear_ip_bgp_dampening_address
,
11989 clear_ip_bgp_dampening_address_cmd
,
11990 "clear ip bgp dampening A.B.C.D",
11994 "Clear route flap dampening information\n"
11995 "Network to clear damping information\n")
11998 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11999 SAFI_UNICAST
, NULL
, 0);
12002 DEFUN (clear_ip_bgp_dampening_address_mask
,
12003 clear_ip_bgp_dampening_address_mask_cmd
,
12004 "clear ip bgp dampening A.B.C.D A.B.C.D",
12008 "Clear route flap dampening information\n"
12009 "Network to clear damping information\n"
12013 int idx_ipv4_2
= 5;
12015 char prefix_str
[BUFSIZ
];
12017 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12020 vty_out(vty
, "%% Inconsistent address and mask\n");
12021 return CMD_WARNING
;
12024 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12028 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12030 struct vty
*vty
= arg
;
12031 struct peer
*peer
= bucket
->data
;
12032 char buf
[SU_ADDRSTRLEN
];
12034 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12035 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12038 DEFUN (show_bgp_peerhash
,
12039 show_bgp_peerhash_cmd
,
12040 "show bgp peerhash",
12043 "Display information about the BGP peerhash\n")
12045 struct list
*instances
= bm
->bgp
;
12046 struct listnode
*node
;
12049 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12050 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12051 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12055 return CMD_SUCCESS
;
12058 /* also used for encap safi */
12059 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12060 afi_t afi
, safi_t safi
)
12062 struct bgp_node
*prn
;
12063 struct bgp_node
*rn
;
12064 struct bgp_table
*table
;
12066 struct prefix_rd
*prd
;
12067 struct bgp_static
*bgp_static
;
12068 mpls_label_t label
;
12069 char buf
[SU_ADDRSTRLEN
];
12070 char rdbuf
[RD_ADDRSTRLEN
];
12072 /* Network configuration. */
12073 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12074 prn
= bgp_route_next(prn
)) {
12075 table
= bgp_node_get_bgp_table_info(prn
);
12079 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12080 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12081 if (bgp_static
== NULL
)
12085 prd
= (struct prefix_rd
*)&prn
->p
;
12087 /* "network" configuration display. */
12088 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12089 label
= decode_label(&bgp_static
->label
);
12091 vty_out(vty
, " network %s/%d rd %s",
12092 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12094 p
->prefixlen
, rdbuf
);
12095 if (safi
== SAFI_MPLS_VPN
)
12096 vty_out(vty
, " label %u", label
);
12098 if (bgp_static
->rmap
.name
)
12099 vty_out(vty
, " route-map %s",
12100 bgp_static
->rmap
.name
);
12102 if (bgp_static
->backdoor
)
12103 vty_out(vty
, " backdoor");
12105 vty_out(vty
, "\n");
12110 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12111 afi_t afi
, safi_t safi
)
12113 struct bgp_node
*prn
;
12114 struct bgp_node
*rn
;
12115 struct bgp_table
*table
;
12117 struct prefix_rd
*prd
;
12118 struct bgp_static
*bgp_static
;
12119 char buf
[PREFIX_STRLEN
* 2];
12120 char buf2
[SU_ADDRSTRLEN
];
12121 char rdbuf
[RD_ADDRSTRLEN
];
12123 /* Network configuration. */
12124 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12125 prn
= bgp_route_next(prn
)) {
12126 table
= bgp_node_get_bgp_table_info(prn
);
12130 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12131 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12132 if (bgp_static
== NULL
)
12135 char *macrouter
= NULL
;
12138 if (bgp_static
->router_mac
)
12139 macrouter
= prefix_mac2str(
12140 bgp_static
->router_mac
, NULL
, 0);
12141 if (bgp_static
->eth_s_id
)
12142 esi
= esi2str(bgp_static
->eth_s_id
);
12144 prd
= (struct prefix_rd
*)&prn
->p
;
12146 /* "network" configuration display. */
12147 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12148 if (p
->u
.prefix_evpn
.route_type
== 5) {
12149 char local_buf
[PREFIX_STRLEN
];
12150 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12151 struct prefix_evpn
*)p
)
12155 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12156 local_buf
, PREFIX_STRLEN
);
12157 sprintf(buf
, "%s/%u", local_buf
,
12158 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12160 prefix2str(p
, buf
, sizeof(buf
));
12163 if (bgp_static
->gatewayIp
.family
== AF_INET
12164 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12165 inet_ntop(bgp_static
->gatewayIp
.family
,
12166 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12169 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12171 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12172 decode_label(&bgp_static
->label
), esi
, buf2
,
12175 XFREE(MTYPE_TMP
, macrouter
);
12176 XFREE(MTYPE_TMP
, esi
);
12181 /* Configuration of static route announcement and aggregate
12183 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12186 struct bgp_node
*rn
;
12188 struct bgp_static
*bgp_static
;
12189 struct bgp_aggregate
*bgp_aggregate
;
12190 char buf
[SU_ADDRSTRLEN
];
12192 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12193 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12197 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12198 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12202 /* Network configuration. */
12203 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12204 rn
= bgp_route_next(rn
)) {
12205 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12206 if (bgp_static
== NULL
)
12211 /* "network" configuration display. */
12212 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
12213 uint32_t destination
;
12214 struct in_addr netmask
;
12216 destination
= ntohl(p
->u
.prefix4
.s_addr
);
12217 masklen2ip(p
->prefixlen
, &netmask
);
12218 vty_out(vty
, " network %s",
12219 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12222 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
12223 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
12224 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
12225 || p
->u
.prefix4
.s_addr
== 0) {
12226 /* Natural mask is not display. */
12228 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
12230 vty_out(vty
, " network %s/%d",
12231 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12236 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12237 vty_out(vty
, " label-index %u",
12238 bgp_static
->label_index
);
12240 if (bgp_static
->rmap
.name
)
12241 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12243 if (bgp_static
->backdoor
)
12244 vty_out(vty
, " backdoor");
12246 vty_out(vty
, "\n");
12249 /* Aggregate-address configuration. */
12250 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12251 rn
= bgp_route_next(rn
)) {
12252 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12253 if (bgp_aggregate
== NULL
)
12258 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
12259 struct in_addr netmask
;
12261 masklen2ip(p
->prefixlen
, &netmask
);
12262 vty_out(vty
, " aggregate-address %s %s",
12263 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12265 inet_ntoa(netmask
));
12267 vty_out(vty
, " aggregate-address %s/%d",
12268 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12273 if (bgp_aggregate
->as_set
)
12274 vty_out(vty
, " as-set");
12276 if (bgp_aggregate
->summary_only
)
12277 vty_out(vty
, " summary-only");
12279 vty_out(vty
, "\n");
12283 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12286 struct bgp_node
*rn
;
12287 struct bgp_distance
*bdistance
;
12289 /* Distance configuration. */
12290 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12291 && bgp
->distance_local
[afi
][safi
]
12292 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12293 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12294 || bgp
->distance_local
[afi
][safi
]
12295 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12296 vty_out(vty
, " distance bgp %d %d %d\n",
12297 bgp
->distance_ebgp
[afi
][safi
],
12298 bgp
->distance_ibgp
[afi
][safi
],
12299 bgp
->distance_local
[afi
][safi
]);
12302 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12303 rn
= bgp_route_next(rn
)) {
12304 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12305 if (bdistance
!= NULL
) {
12306 char buf
[PREFIX_STRLEN
];
12308 vty_out(vty
, " distance %d %s %s\n",
12309 bdistance
->distance
,
12310 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12311 bdistance
->access_list
? bdistance
->access_list
12317 /* Allocate routing table structure and install commands. */
12318 void bgp_route_init(void)
12323 /* Init BGP distance table. */
12324 FOREACH_AFI_SAFI (afi
, safi
)
12325 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12327 /* IPv4 BGP commands. */
12328 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12329 install_element(BGP_NODE
, &bgp_network_cmd
);
12330 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12332 install_element(BGP_NODE
, &aggregate_address_cmd
);
12333 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12334 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12335 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12337 /* IPv4 unicast configuration. */
12338 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12339 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12340 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12342 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12343 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12344 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12345 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12347 /* IPv4 multicast configuration. */
12348 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12349 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12350 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12351 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12352 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12353 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12354 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12356 /* IPv4 labeled-unicast configuration. */
12357 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12358 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12359 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12360 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12361 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12363 install_element(VIEW_NODE
,
12364 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12365 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12366 install_element(VIEW_NODE
,
12367 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12368 #ifdef KEEP_OLD_VPN_COMMANDS
12369 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12370 #endif /* KEEP_OLD_VPN_COMMANDS */
12371 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12372 install_element(VIEW_NODE
,
12373 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
12375 /* BGP dampening clear commands */
12376 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12377 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12379 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12380 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12383 install_element(ENABLE_NODE
,
12384 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12385 #ifdef KEEP_OLD_VPN_COMMANDS
12386 install_element(ENABLE_NODE
,
12387 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12388 #endif /* KEEP_OLD_VPN_COMMANDS */
12390 /* New config IPv6 BGP commands. */
12391 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12392 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12393 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12395 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12396 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12398 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12400 install_element(BGP_NODE
, &bgp_distance_cmd
);
12401 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12402 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12403 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12404 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12405 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12406 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12407 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12408 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12409 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12410 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12411 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12412 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12413 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12414 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12415 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12416 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12417 install_element(BGP_IPV4M_NODE
,
12418 &no_bgp_distance_source_access_list_cmd
);
12419 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12420 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12421 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12422 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12423 install_element(BGP_IPV6_NODE
,
12424 &ipv6_bgp_distance_source_access_list_cmd
);
12425 install_element(BGP_IPV6_NODE
,
12426 &no_ipv6_bgp_distance_source_access_list_cmd
);
12427 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12428 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12429 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12430 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12431 install_element(BGP_IPV6M_NODE
,
12432 &ipv6_bgp_distance_source_access_list_cmd
);
12433 install_element(BGP_IPV6M_NODE
,
12434 &no_ipv6_bgp_distance_source_access_list_cmd
);
12436 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12437 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12438 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12439 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12441 /* IPv4 Multicast Mode */
12442 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12443 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12445 /* Large Communities */
12446 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12447 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12449 /* show bgp ipv4 flowspec detailed */
12450 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12452 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12455 void bgp_route_finish(void)
12460 FOREACH_AFI_SAFI (afi
, safi
) {
12461 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12462 bgp_distance_table
[afi
][safi
] = NULL
;