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"
70 #include "bgpd/rfapi/rfapi_backend.h"
71 #include "bgpd/rfapi/vnc_import_bgp.h"
72 #include "bgpd/rfapi/vnc_export_bgp.h"
74 #include "bgpd/bgp_encap_types.h"
75 #include "bgpd/bgp_encap_tlv.h"
76 #include "bgpd/bgp_evpn.h"
77 #include "bgpd/bgp_evpn_vty.h"
78 #include "bgpd/bgp_flowspec.h"
79 #include "bgpd/bgp_flowspec_util.h"
80 #include "bgpd/bgp_pbr.h"
82 #ifndef VTYSH_EXTRACT_PL
83 #include "bgpd/bgp_route_clippy.c"
86 /* Extern from bgp_dump.c */
87 extern const char *bgp_origin_str
[];
88 extern const char *bgp_origin_long_str
[];
91 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
92 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
93 static const struct message bgp_pmsi_tnltype_str
[] = {
94 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
95 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
96 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
97 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
98 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
99 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
100 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
101 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
105 #define VRFID_NONE_STR "-"
107 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
108 safi_t safi
, struct prefix
*p
,
109 struct prefix_rd
*prd
)
112 struct bgp_node
*prn
= NULL
;
118 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
119 || (safi
== SAFI_EVPN
)) {
120 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
122 if (prn
->info
== NULL
)
123 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
125 bgp_unlock_node(prn
);
129 rn
= bgp_node_get(table
, p
);
131 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
132 || (safi
== SAFI_EVPN
))
138 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
139 safi_t safi
, struct prefix
*p
,
140 struct prefix_rd
*prd
)
143 struct bgp_node
*prn
= NULL
;
148 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
149 || (safi
== SAFI_EVPN
)) {
150 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
154 if (prn
->info
== NULL
) {
155 bgp_unlock_node(prn
);
162 rn
= bgp_node_lookup(table
, p
);
167 /* Allocate bgp_path_info_extra */
168 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
170 struct bgp_path_info_extra
*new;
171 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
172 sizeof(struct bgp_path_info_extra
));
173 new->label
[0] = MPLS_INVALID_LABEL
;
178 static void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
180 struct bgp_path_info_extra
*e
;
182 if (!extra
|| !*extra
)
187 bgp_damp_info_free(e
->damp_info
, 0);
191 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
194 /* FIXME: since multiple e may have the same e->parent
195 * and e->parent->net is holding a refcount for each
196 * of them, we need to do some fudging here.
198 * WARNING: if bpi->net->lock drops to 0, bpi may be
199 * freed as well (because bpi->net was holding the
200 * last reference to bpi) => write after free!
204 bpi
= bgp_path_info_lock(bpi
);
205 refcount
= bpi
->net
->lock
- 1;
206 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
209 bgp_path_info_unlock(bpi
);
211 bgp_path_info_unlock(e
->parent
);
216 bgp_unlock(e
->bgp_orig
);
218 if ((*extra
)->bgp_fs_pbr
)
219 list_delete(&((*extra
)->bgp_fs_pbr
));
220 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
225 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
226 * allocated if required.
228 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
231 pi
->extra
= bgp_path_info_extra_new();
235 /* Allocate new bgp info structure. */
236 struct bgp_path_info
*bgp_path_info_new(void)
238 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
241 /* Free bgp route information. */
242 static void bgp_path_info_free(struct bgp_path_info
*path
)
245 bgp_attr_unintern(&path
->attr
);
247 bgp_unlink_nexthop(path
);
248 bgp_path_info_extra_free(&path
->extra
);
249 bgp_path_info_mpath_free(&path
->mpath
);
251 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
253 XFREE(MTYPE_BGP_ROUTE
, path
);
256 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
262 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
264 assert(path
&& path
->lock
> 0);
267 if (path
->lock
== 0) {
269 zlog_debug ("%s: unlocked and freeing", __func__
);
270 zlog_backtrace (LOG_DEBUG
);
272 bgp_path_info_free(path
);
279 zlog_debug ("%s: unlocked to 1", __func__
);
280 zlog_backtrace (LOG_DEBUG
);
287 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
289 struct bgp_path_info
*top
;
299 bgp_path_info_lock(pi
);
301 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
304 /* Do the actual removal of info from RIB, for use by bgp_process
305 completion callback *only* */
306 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
309 pi
->next
->prev
= pi
->prev
;
311 pi
->prev
->next
= pi
->next
;
315 bgp_path_info_mpath_dequeue(pi
);
316 bgp_path_info_unlock(pi
);
320 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
322 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
323 /* set of previous already took care of pcount */
324 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
327 /* undo the effects of a previous call to bgp_path_info_delete; typically
328 called when a route is deleted and then quickly re-added before the
329 deletion has been processed */
330 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
332 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
333 /* unset of previous already took care of pcount */
334 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
337 /* Adjust pcount as required */
338 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
340 struct bgp_table
*table
;
342 assert(rn
&& bgp_node_table(rn
));
343 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
345 table
= bgp_node_table(rn
);
347 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
350 if (!BGP_PATH_COUNTABLE(pi
)
351 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
353 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
355 /* slight hack, but more robust against errors. */
356 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
357 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
359 flog_err(EC_LIB_DEVELOPMENT
,
360 "Asked to decrement 0 prefix count for peer");
361 } else if (BGP_PATH_COUNTABLE(pi
)
362 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
363 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
364 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
368 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
369 struct bgp_path_info
*pi2
)
371 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
374 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
375 * This is here primarily to keep prefix-count in check.
377 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
380 SET_FLAG(pi
->flags
, flag
);
382 /* early bath if we know it's not a flag that changes countability state
384 if (!CHECK_FLAG(flag
,
385 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
388 bgp_pcount_adjust(rn
, pi
);
391 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
394 UNSET_FLAG(pi
->flags
, flag
);
396 /* early bath if we know it's not a flag that changes countability state
398 if (!CHECK_FLAG(flag
,
399 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
402 bgp_pcount_adjust(rn
, pi
);
405 /* Get MED value. If MED value is missing and "bgp bestpath
406 missing-as-worst" is specified, treat it as the worst value. */
407 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
409 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
412 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
419 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
421 if (pi
->addpath_rx_id
)
422 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
425 sprintf(buf
, "path %s", pi
->peer
->host
);
428 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
430 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
431 struct bgp_path_info
*exist
, int *paths_eq
,
432 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
433 char *pfx_buf
, afi_t afi
, safi_t safi
)
435 struct attr
*newattr
, *existattr
;
436 bgp_peer_sort_t new_sort
;
437 bgp_peer_sort_t exist_sort
;
443 uint32_t exist_weight
;
444 uint32_t newm
, existm
;
445 struct in_addr new_id
;
446 struct in_addr exist_id
;
449 int internal_as_route
;
452 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
453 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
455 uint32_t exist_mm_seq
;
462 zlog_debug("%s: new is NULL", pfx_buf
);
467 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
471 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
477 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
478 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
479 pfx_buf
, new_buf
, new->flags
, exist_buf
,
484 existattr
= exist
->attr
;
486 /* For EVPN routes, we cannot just go by local vs remote, we have to
487 * look at the MAC mobility sequence number, if present.
489 if (safi
== SAFI_EVPN
) {
490 /* This is an error condition described in RFC 7432 Section
492 * states that in this scenario "the PE MUST alert the operator"
494 * does not state what other action to take. In order to provide
496 * consistency in this scenario we are going to prefer the path
500 if (newattr
->sticky
!= existattr
->sticky
) {
502 prefix2str(&new->net
->p
, pfx_buf
,
504 * PREFIX2STR_BUFFER
);
505 bgp_path_info_path_with_addpath_rx_str(new,
507 bgp_path_info_path_with_addpath_rx_str(
511 if (newattr
->sticky
&& !existattr
->sticky
) {
514 "%s: %s wins over %s due to sticky MAC flag",
515 pfx_buf
, new_buf
, exist_buf
);
519 if (!newattr
->sticky
&& existattr
->sticky
) {
522 "%s: %s loses to %s due to sticky MAC flag",
523 pfx_buf
, new_buf
, exist_buf
);
528 new_mm_seq
= mac_mobility_seqnum(newattr
);
529 exist_mm_seq
= mac_mobility_seqnum(existattr
);
531 if (new_mm_seq
> exist_mm_seq
) {
534 "%s: %s wins over %s due to MM seq %u > %u",
535 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
540 if (new_mm_seq
< exist_mm_seq
) {
543 "%s: %s loses to %s due to MM seq %u < %u",
544 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
550 /* 1. Weight check. */
551 new_weight
= newattr
->weight
;
552 exist_weight
= existattr
->weight
;
554 if (new_weight
> exist_weight
) {
556 zlog_debug("%s: %s wins over %s due to weight %d > %d",
557 pfx_buf
, new_buf
, exist_buf
, new_weight
,
562 if (new_weight
< exist_weight
) {
564 zlog_debug("%s: %s loses to %s due to weight %d < %d",
565 pfx_buf
, new_buf
, exist_buf
, new_weight
,
570 /* 2. Local preference check. */
571 new_pref
= exist_pref
= bgp
->default_local_pref
;
573 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
574 new_pref
= newattr
->local_pref
;
575 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
576 exist_pref
= existattr
->local_pref
;
578 if (new_pref
> exist_pref
) {
581 "%s: %s wins over %s due to localpref %d > %d",
582 pfx_buf
, new_buf
, exist_buf
, new_pref
,
587 if (new_pref
< exist_pref
) {
590 "%s: %s loses to %s due to localpref %d < %d",
591 pfx_buf
, new_buf
, exist_buf
, new_pref
,
596 /* 3. Local route check. We prefer:
598 * - BGP_ROUTE_AGGREGATE
599 * - BGP_ROUTE_REDISTRIBUTE
601 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
602 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
605 "%s: %s wins over %s due to preferred BGP_ROUTE type",
606 pfx_buf
, new_buf
, exist_buf
);
610 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
611 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
614 "%s: %s loses to %s due to preferred BGP_ROUTE type",
615 pfx_buf
, new_buf
, exist_buf
);
619 /* 4. AS path length check. */
620 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
621 int exist_hops
= aspath_count_hops(existattr
->aspath
);
622 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
624 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
627 aspath_hops
= aspath_count_hops(newattr
->aspath
);
628 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
630 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
633 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
634 pfx_buf
, new_buf
, exist_buf
,
636 (exist_hops
+ exist_confeds
));
640 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
643 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
644 pfx_buf
, new_buf
, exist_buf
,
646 (exist_hops
+ exist_confeds
));
650 int newhops
= aspath_count_hops(newattr
->aspath
);
652 if (newhops
< exist_hops
) {
655 "%s: %s wins over %s due to aspath hopcount %d < %d",
656 pfx_buf
, new_buf
, exist_buf
,
657 newhops
, exist_hops
);
661 if (newhops
> exist_hops
) {
664 "%s: %s loses to %s due to aspath hopcount %d > %d",
665 pfx_buf
, new_buf
, exist_buf
,
666 newhops
, exist_hops
);
672 /* 5. Origin check. */
673 if (newattr
->origin
< existattr
->origin
) {
675 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
676 pfx_buf
, new_buf
, exist_buf
,
677 bgp_origin_long_str
[newattr
->origin
],
678 bgp_origin_long_str
[existattr
->origin
]);
682 if (newattr
->origin
> existattr
->origin
) {
684 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
685 pfx_buf
, new_buf
, exist_buf
,
686 bgp_origin_long_str
[newattr
->origin
],
687 bgp_origin_long_str
[existattr
->origin
]);
692 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
693 && aspath_count_hops(existattr
->aspath
) == 0);
694 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
695 && aspath_count_confeds(existattr
->aspath
) > 0
696 && aspath_count_hops(newattr
->aspath
) == 0
697 && aspath_count_hops(existattr
->aspath
) == 0);
699 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
700 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
701 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
702 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
703 || internal_as_route
) {
704 new_med
= bgp_med_value(new->attr
, bgp
);
705 exist_med
= bgp_med_value(exist
->attr
, bgp
);
707 if (new_med
< exist_med
) {
710 "%s: %s wins over %s due to MED %d < %d",
711 pfx_buf
, new_buf
, exist_buf
, new_med
,
716 if (new_med
> exist_med
) {
719 "%s: %s loses to %s due to MED %d > %d",
720 pfx_buf
, new_buf
, exist_buf
, new_med
,
726 /* 7. Peer type check. */
727 new_sort
= new->peer
->sort
;
728 exist_sort
= exist
->peer
->sort
;
730 if (new_sort
== BGP_PEER_EBGP
731 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
734 "%s: %s wins over %s due to eBGP peer > iBGP peer",
735 pfx_buf
, new_buf
, exist_buf
);
739 if (exist_sort
== BGP_PEER_EBGP
740 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
743 "%s: %s loses to %s due to iBGP peer < eBGP peer",
744 pfx_buf
, new_buf
, exist_buf
);
748 /* 8. IGP metric check. */
752 newm
= new->extra
->igpmetric
;
754 existm
= exist
->extra
->igpmetric
;
759 "%s: %s wins over %s due to IGP metric %d < %d",
760 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
767 "%s: %s loses to %s due to IGP metric %d > %d",
768 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
772 /* 9. Same IGP metric. Compare the cluster list length as
773 representative of IGP hops metric. Rewrite the metric value
774 pair (newm, existm) with the cluster list length. Prefer the
775 path with smaller cluster list length. */
776 if (newm
== existm
) {
777 if (peer_sort(new->peer
) == BGP_PEER_IBGP
778 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
779 && (mpath_cfg
== NULL
781 mpath_cfg
->ibgp_flags
,
782 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
783 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
784 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
789 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
790 pfx_buf
, new_buf
, exist_buf
,
798 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
799 pfx_buf
, new_buf
, exist_buf
,
806 /* 10. confed-external vs. confed-internal */
807 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
808 if (new_sort
== BGP_PEER_CONFED
809 && exist_sort
== BGP_PEER_IBGP
) {
812 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
813 pfx_buf
, new_buf
, exist_buf
);
817 if (exist_sort
== BGP_PEER_CONFED
818 && new_sort
== BGP_PEER_IBGP
) {
821 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
822 pfx_buf
, new_buf
, exist_buf
);
827 /* 11. Maximum path check. */
828 if (newm
== existm
) {
829 /* If one path has a label but the other does not, do not treat
830 * them as equals for multipath
832 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
834 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
837 "%s: %s and %s cannot be multipath, one has a label while the other does not",
838 pfx_buf
, new_buf
, exist_buf
);
839 } else if (bgp_flag_check(bgp
,
840 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
843 * For the two paths, all comparison steps till IGP
845 * have succeeded - including AS_PATH hop count. Since
847 * bestpath as-path multipath-relax' knob is on, we
849 * an exact match of AS_PATH. Thus, mark the paths are
851 * That will trigger both these paths to get into the
859 "%s: %s and %s are equal via multipath-relax",
860 pfx_buf
, new_buf
, exist_buf
);
861 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
862 if (aspath_cmp(new->attr
->aspath
,
863 exist
->attr
->aspath
)) {
868 "%s: %s and %s are equal via matching aspaths",
869 pfx_buf
, new_buf
, exist_buf
);
871 } else if (new->peer
->as
== exist
->peer
->as
) {
876 "%s: %s and %s are equal via same remote-as",
877 pfx_buf
, new_buf
, exist_buf
);
881 * TODO: If unequal cost ibgp multipath is enabled we can
882 * mark the paths as equal here instead of returning
887 "%s: %s wins over %s after IGP metric comparison",
888 pfx_buf
, new_buf
, exist_buf
);
891 "%s: %s loses to %s after IGP metric comparison",
892 pfx_buf
, new_buf
, exist_buf
);
897 /* 12. If both paths are external, prefer the path that was received
898 first (the oldest one). This step minimizes route-flap, since a
899 newer path won't displace an older one, even if it was the
900 preferred route based on the additional decision criteria below. */
901 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
902 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
903 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
906 "%s: %s wins over %s due to oldest external",
907 pfx_buf
, new_buf
, exist_buf
);
911 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
914 "%s: %s loses to %s due to oldest external",
915 pfx_buf
, new_buf
, exist_buf
);
920 /* 13. Router-ID comparision. */
921 /* If one of the paths is "stale", the corresponding peer router-id will
922 * be 0 and would always win over the other path. If originator id is
923 * used for the comparision, it will decide which path is better.
925 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
926 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
928 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
929 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
930 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
932 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
934 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
937 "%s: %s wins over %s due to Router-ID comparison",
938 pfx_buf
, new_buf
, exist_buf
);
942 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
945 "%s: %s loses to %s due to Router-ID comparison",
946 pfx_buf
, new_buf
, exist_buf
);
950 /* 14. Cluster length comparision. */
951 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
952 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
954 if (new_cluster
< exist_cluster
) {
957 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
958 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
963 if (new_cluster
> exist_cluster
) {
966 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
967 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
972 /* 15. Neighbor address comparision. */
973 /* Do this only if neither path is "stale" as stale paths do not have
974 * valid peer information (as the connection may or may not be up).
976 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
979 "%s: %s wins over %s due to latter path being STALE",
980 pfx_buf
, new_buf
, exist_buf
);
984 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
987 "%s: %s loses to %s due to former path being STALE",
988 pfx_buf
, new_buf
, exist_buf
);
992 /* locally configured routes to advertise do not have su_remote */
993 if (new->peer
->su_remote
== NULL
)
995 if (exist
->peer
->su_remote
== NULL
)
998 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1003 "%s: %s loses to %s due to Neighor IP comparison",
1004 pfx_buf
, new_buf
, exist_buf
);
1011 "%s: %s wins over %s due to Neighor IP comparison",
1012 pfx_buf
, new_buf
, exist_buf
);
1017 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1018 pfx_buf
, new_buf
, exist_buf
);
1023 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1024 * is preferred, or 0 if they are the same (usually will only occur if
1025 * multipath is enabled
1026 * This version is compatible with */
1027 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1028 struct bgp_path_info
*exist
, char *pfx_buf
,
1029 afi_t afi
, safi_t safi
)
1033 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1047 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1048 struct attr
*attr
, afi_t afi
,
1051 struct bgp_filter
*filter
;
1053 filter
= &peer
->filter
[afi
][safi
];
1055 #define FILTER_EXIST_WARN(F, f, filter) \
1056 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1057 zlog_debug("%s: Could not find configured input %s-list %s!", \
1058 peer->host, #f, F##_IN_NAME(filter));
1060 if (DISTRIBUTE_IN_NAME(filter
)) {
1061 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1063 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1067 if (PREFIX_LIST_IN_NAME(filter
)) {
1068 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1070 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1074 if (FILTER_LIST_IN_NAME(filter
)) {
1075 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1077 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1082 return FILTER_PERMIT
;
1083 #undef FILTER_EXIST_WARN
1086 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1087 struct attr
*attr
, afi_t afi
,
1090 struct bgp_filter
*filter
;
1092 filter
= &peer
->filter
[afi
][safi
];
1094 #define FILTER_EXIST_WARN(F, f, filter) \
1095 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1096 zlog_debug("%s: Could not find configured output %s-list %s!", \
1097 peer->host, #f, F##_OUT_NAME(filter));
1099 if (DISTRIBUTE_OUT_NAME(filter
)) {
1100 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1102 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1106 if (PREFIX_LIST_OUT_NAME(filter
)) {
1107 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1109 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1114 if (FILTER_LIST_OUT_NAME(filter
)) {
1115 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1117 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1122 return FILTER_PERMIT
;
1123 #undef FILTER_EXIST_WARN
1126 /* If community attribute includes no_export then return 1. */
1127 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1129 if (attr
->community
) {
1130 /* NO_ADVERTISE check. */
1131 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1134 /* NO_EXPORT check. */
1135 if (peer
->sort
== BGP_PEER_EBGP
1136 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1139 /* NO_EXPORT_SUBCONFED check. */
1140 if (peer
->sort
== BGP_PEER_EBGP
1141 || peer
->sort
== BGP_PEER_CONFED
)
1142 if (community_include(attr
->community
,
1143 COMMUNITY_NO_EXPORT_SUBCONFED
))
1149 /* Route reflection loop check. */
1150 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1152 struct in_addr cluster_id
;
1154 if (attr
->cluster
) {
1155 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1156 cluster_id
= peer
->bgp
->cluster_id
;
1158 cluster_id
= peer
->bgp
->router_id
;
1160 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1166 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1167 struct attr
*attr
, afi_t afi
, safi_t safi
,
1168 const char *rmap_name
)
1170 struct bgp_filter
*filter
;
1171 struct bgp_path_info rmap_path
;
1172 route_map_result_t ret
;
1173 struct route_map
*rmap
= NULL
;
1175 filter
= &peer
->filter
[afi
][safi
];
1177 /* Apply default weight value. */
1178 if (peer
->weight
[afi
][safi
])
1179 attr
->weight
= peer
->weight
[afi
][safi
];
1182 rmap
= route_map_lookup_by_name(rmap_name
);
1187 if (ROUTE_MAP_IN_NAME(filter
)) {
1188 rmap
= ROUTE_MAP_IN(filter
);
1195 /* Route map apply. */
1197 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1198 /* Duplicate current value to new strucutre for modification. */
1199 rmap_path
.peer
= peer
;
1200 rmap_path
.attr
= attr
;
1202 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1204 /* Apply BGP route map to the attribute. */
1205 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1207 peer
->rmap_type
= 0;
1209 if (ret
== RMAP_DENYMATCH
)
1215 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1216 struct attr
*attr
, afi_t afi
, safi_t safi
,
1217 const char *rmap_name
)
1219 struct bgp_path_info rmap_path
;
1220 route_map_result_t ret
;
1221 struct route_map
*rmap
= NULL
;
1225 * So if we get to this point and have no rmap_name
1226 * we want to just show the output as it currently
1232 /* Apply default weight value. */
1233 if (peer
->weight
[afi
][safi
])
1234 attr
->weight
= peer
->weight
[afi
][safi
];
1236 rmap
= route_map_lookup_by_name(rmap_name
);
1239 * If we have a route map name and we do not find
1240 * the routemap that means we have an implicit
1246 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1247 /* Route map apply. */
1248 /* Duplicate current value to new strucutre for modification. */
1249 rmap_path
.peer
= peer
;
1250 rmap_path
.attr
= attr
;
1252 rmap_type
= peer
->rmap_type
;
1253 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1255 /* Apply BGP route map to the attribute. */
1256 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1258 peer
->rmap_type
= rmap_type
;
1260 if (ret
== RMAP_DENYMATCH
)
1262 * caller has multiple error paths with bgp_attr_flush()
1269 /* If this is an EBGP peer with remove-private-AS */
1270 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1271 struct peer
*peer
, struct attr
*attr
)
1273 if (peer
->sort
== BGP_PEER_EBGP
1274 && (peer_af_flag_check(peer
, afi
, safi
,
1275 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1276 || peer_af_flag_check(peer
, afi
, safi
,
1277 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1278 || peer_af_flag_check(peer
, afi
, safi
,
1279 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1280 || peer_af_flag_check(peer
, afi
, safi
,
1281 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1282 // Take action on the entire aspath
1283 if (peer_af_flag_check(peer
, afi
, safi
,
1284 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1285 || peer_af_flag_check(peer
, afi
, safi
,
1286 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1287 if (peer_af_flag_check(
1289 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1290 attr
->aspath
= aspath_replace_private_asns(
1291 attr
->aspath
, bgp
->as
);
1293 // The entire aspath consists of private ASNs so create
1295 else if (aspath_private_as_check(attr
->aspath
))
1296 attr
->aspath
= aspath_empty_get();
1298 // There are some public and some private ASNs, remove
1301 attr
->aspath
= aspath_remove_private_asns(
1305 // 'all' was not specified so the entire aspath must be private
1307 // for us to do anything
1308 else if (aspath_private_as_check(attr
->aspath
)) {
1309 if (peer_af_flag_check(
1311 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1312 attr
->aspath
= aspath_replace_private_asns(
1313 attr
->aspath
, bgp
->as
);
1315 attr
->aspath
= aspath_empty_get();
1320 /* If this is an EBGP peer with as-override */
1321 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1322 struct peer
*peer
, struct attr
*attr
)
1324 if (peer
->sort
== BGP_PEER_EBGP
1325 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1326 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1327 attr
->aspath
= aspath_replace_specific_asn(
1328 attr
->aspath
, peer
->as
, bgp
->as
);
1332 void bgp_attr_add_gshut_community(struct attr
*attr
)
1334 struct community
*old
;
1335 struct community
*new;
1336 struct community
*merge
;
1337 struct community
*gshut
;
1339 old
= attr
->community
;
1340 gshut
= community_str2com("graceful-shutdown");
1345 merge
= community_merge(community_dup(old
), gshut
);
1347 if (old
->refcnt
== 0)
1348 community_free(&old
);
1350 new = community_uniq_sort(merge
);
1351 community_free(&merge
);
1353 new = community_dup(gshut
);
1356 community_free(&gshut
);
1357 attr
->community
= new;
1358 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1360 /* When we add the graceful-shutdown community we must also
1361 * lower the local-preference */
1362 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1363 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1367 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1369 if (family
== AF_INET
) {
1370 attr
->nexthop
.s_addr
= 0;
1371 attr
->mp_nexthop_global_in
.s_addr
= 0;
1373 if (family
== AF_INET6
)
1374 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1375 if (family
== AF_EVPN
)
1376 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1379 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1380 struct update_subgroup
*subgrp
, struct prefix
*p
,
1383 struct bgp_filter
*filter
;
1386 struct peer
*onlypeer
;
1388 struct attr
*piattr
;
1389 char buf
[PREFIX_STRLEN
];
1395 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1397 if (DISABLE_BGP_ANNOUNCE
)
1400 afi
= SUBGRP_AFI(subgrp
);
1401 safi
= SUBGRP_SAFI(subgrp
);
1402 peer
= SUBGRP_PEER(subgrp
);
1404 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1405 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1408 filter
= &peer
->filter
[afi
][safi
];
1409 bgp
= SUBGRP_INST(subgrp
);
1410 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1414 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1415 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1416 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1419 * direct and direct_ext type routes originate internally even
1420 * though they can have peer pointers that reference other
1423 prefix2str(p
, buf
, PREFIX_STRLEN
);
1424 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1430 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1431 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1432 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1433 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1435 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1440 /* With addpath we may be asked to TX all kinds of paths so make sure
1442 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1443 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1444 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1448 /* If this is not the bestpath then check to see if there is an enabled
1450 * feature that requires us to advertise it */
1451 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1452 if (!bgp_addpath_tx_path(peer
, afi
, safi
, pi
)) {
1457 /* Aggregate-address suppress check. */
1458 if (pi
->extra
&& pi
->extra
->suppress
)
1459 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1464 * If we are doing VRF 2 VRF leaking via the import
1465 * statement, we want to prevent the route going
1466 * off box as that the RT and RD created are localy
1467 * significant and globaly useless.
1469 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1470 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1473 /* If it's labeled safi, make sure the route has a valid label. */
1474 if (safi
== SAFI_LABELED_UNICAST
) {
1475 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1476 if (!bgp_is_valid_label(&label
)) {
1477 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1478 zlog_debug("u%" PRIu64
":s%" PRIu64
1479 " %s/%d is filtered - no label (%p)",
1480 subgrp
->update_group
->id
, subgrp
->id
,
1481 inet_ntop(p
->family
, &p
->u
.prefix
,
1482 buf
, SU_ADDRSTRLEN
),
1483 p
->prefixlen
, &label
);
1488 /* Do not send back route to sender. */
1489 if (onlypeer
&& from
== onlypeer
) {
1493 /* Do not send the default route in the BGP table if the neighbor is
1494 * configured for default-originate */
1495 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1496 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1497 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1499 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1503 /* Transparency check. */
1504 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1505 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1510 /* If community is not disabled check the no-export and local. */
1511 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1512 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1514 "subgrpannouncecheck: community filter check fail");
1518 /* If the attribute has originator-id and it is same as remote
1520 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1521 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1522 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1524 "%s [Update:SEND] %s originator-id is same as "
1527 prefix2str(p
, buf
, sizeof(buf
)));
1531 /* ORF prefix-list filter check */
1532 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1533 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1534 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1535 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1536 if (peer
->orf_plist
[afi
][safi
]) {
1537 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1539 if (bgp_debug_update(NULL
, p
,
1540 subgrp
->update_group
, 0))
1542 "%s [Update:SEND] %s is filtered via ORF",
1550 /* Output filter check. */
1551 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1552 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1553 zlog_debug("%s [Update:SEND] %s is filtered",
1554 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1558 #ifdef BGP_SEND_ASPATH_CHECK
1559 /* AS path loop check. */
1560 if (onlypeer
&& aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1561 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1563 "%s [Update:SEND] suppress announcement to peer AS %u "
1564 "that is part of AS path.",
1565 onlypeer
->host
, onlypeer
->as
);
1568 #endif /* BGP_SEND_ASPATH_CHECK */
1570 /* If we're a CONFED we need to loop check the CONFED ID too */
1571 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1572 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1573 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1575 "%s [Update:SEND] suppress announcement to peer AS %u"
1577 peer
->host
, bgp
->confed_id
);
1582 /* Route-Reflect check. */
1583 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1588 /* IBGP reflection check. */
1589 if (reflect
&& !samepeer_safe
) {
1590 /* A route from a Client peer. */
1591 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1592 PEER_FLAG_REFLECTOR_CLIENT
)) {
1593 /* Reflect to all the Non-Client peers and also to the
1594 Client peers other than the originator. Originator
1596 is already done. So there is noting to do. */
1597 /* no bgp client-to-client reflection check. */
1598 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1599 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1600 PEER_FLAG_REFLECTOR_CLIENT
))
1603 /* A route from a Non-client peer. Reflect to all other
1605 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1606 PEER_FLAG_REFLECTOR_CLIENT
))
1611 /* For modify attribute, copy it to temporary structure. */
1612 bgp_attr_dup(attr
, piattr
);
1614 /* If local-preference is not set. */
1615 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1616 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1617 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1618 attr
->local_pref
= bgp
->default_local_pref
;
1621 /* If originator-id is not set and the route is to be reflected,
1622 set the originator id */
1624 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1625 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1626 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1629 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1631 if (peer
->sort
== BGP_PEER_EBGP
1632 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1633 if (from
!= bgp
->peer_self
&& !transparent
1634 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1635 PEER_FLAG_MED_UNCHANGED
))
1637 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1640 /* Since the nexthop attribute can vary per peer, it is not explicitly
1642 * in announce check, only certain flags and length (or number of
1644 * -- for IPv6/MP_REACH) are set here in order to guide the update
1646 * code in setting the nexthop(s) on a per peer basis in
1648 * Typically, the source nexthop in the attribute is preserved but in
1650 * scenarios where we know it will always be overwritten, we reset the
1651 * nexthop to "0" in an attempt to achieve better Update packing. An
1652 * example of this is when a prefix from each of 2 IBGP peers needs to
1654 * announced to an EBGP peer (and they have the same attributes barring
1658 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1660 #define NEXTHOP_IS_V6 \
1661 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1662 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1663 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1664 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1666 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1668 * the peer (group) is configured to receive link-local nexthop
1670 * and it is available in the prefix OR we're not reflecting the route
1672 * the peer (group) to whom we're going to announce is on a shared
1674 * and this is either a self-originated route or the peer is EBGP.
1676 if (NEXTHOP_IS_V6
) {
1677 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1678 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1679 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1680 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1681 || (!reflect
&& peer
->shared_network
1682 && (from
== bgp
->peer_self
1683 || peer
->sort
== BGP_PEER_EBGP
))) {
1684 attr
->mp_nexthop_len
=
1685 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1688 /* Clear off link-local nexthop in source, whenever it is not
1690 * ensure more prefixes share the same attribute for
1693 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1694 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1695 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1698 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1699 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1701 /* Route map & unsuppress-map apply. */
1702 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1703 struct bgp_path_info rmap_path
;
1704 struct bgp_path_info_extra dummy_rmap_path_extra
;
1705 struct attr dummy_attr
;
1707 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1708 rmap_path
.peer
= peer
;
1709 rmap_path
.attr
= attr
;
1712 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1713 sizeof(struct bgp_path_info_extra
));
1714 rmap_path
.extra
= &dummy_rmap_path_extra
;
1717 /* don't confuse inbound and outbound setting */
1718 RESET_FLAG(attr
->rmap_change_flags
);
1721 * The route reflector is not allowed to modify the attributes
1722 * of the reflected IBGP routes unless explicitly allowed.
1724 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1725 && !bgp_flag_check(bgp
,
1726 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1727 bgp_attr_dup(&dummy_attr
, attr
);
1728 rmap_path
.attr
= &dummy_attr
;
1731 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1733 if (pi
->extra
&& pi
->extra
->suppress
)
1734 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1735 RMAP_BGP
, &rmap_path
);
1737 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1738 RMAP_BGP
, &rmap_path
);
1740 peer
->rmap_type
= 0;
1742 if (ret
== RMAP_DENYMATCH
) {
1743 bgp_attr_flush(attr
);
1748 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1749 if (peer
->sort
== BGP_PEER_IBGP
1750 || peer
->sort
== BGP_PEER_CONFED
) {
1751 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1752 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1754 bgp_attr_add_gshut_community(attr
);
1758 /* After route-map has been applied, we check to see if the nexthop to
1759 * be carried in the attribute (that is used for the announcement) can
1760 * be cleared off or not. We do this in all cases where we would be
1761 * setting the nexthop to "ourselves". For IPv6, we only need to
1763 * the global nexthop here; the link-local nexthop would have been
1765 * already, and if not, it is required by the update formation code.
1766 * Also see earlier comments in this function.
1769 * If route-map has performed some operation on the nexthop or the peer
1770 * configuration says to pass it unchanged, we cannot reset the nexthop
1771 * here, so only attempt to do it if these aren't true. Note that the
1772 * route-map handler itself might have cleared the nexthop, if for
1774 * it is configured as 'peer-address'.
1776 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1777 piattr
->rmap_change_flags
)
1779 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1780 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1781 /* We can reset the nexthop, if setting (or forcing) it to
1783 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1784 PEER_FLAG_NEXTHOP_SELF
)
1785 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1786 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1788 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1789 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1790 subgroup_announce_reset_nhop(
1791 (peer_cap_enhe(peer
, afi
, safi
)
1795 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1796 /* Can also reset the nexthop if announcing to EBGP, but
1798 * no peer in the subgroup is on a shared subnet.
1799 * Note: 3rd party nexthop currently implemented for
1802 if (!bgp_subgrp_multiaccess_check_v4(piattr
->nexthop
,
1804 subgroup_announce_reset_nhop(
1805 (peer_cap_enhe(peer
, afi
, safi
)
1809 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1811 * This flag is used for leaked vpn-vrf routes
1813 int family
= p
->family
;
1815 if (peer_cap_enhe(peer
, afi
, safi
))
1818 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1820 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1821 __func__
, family2str(family
));
1822 subgroup_announce_reset_nhop(family
, attr
);
1825 /* If IPv6/MP and nexthop does not have any override and happens
1827 * be a link-local address, reset it so that we don't pass along
1829 * source's link-local IPv6 address to recipients who may not be
1831 * the same interface.
1833 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1834 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1835 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1842 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1843 struct bgp_maxpaths_cfg
*mpath_cfg
,
1844 struct bgp_path_info_pair
*result
, afi_t afi
,
1847 struct bgp_path_info
*new_select
;
1848 struct bgp_path_info
*old_select
;
1849 struct bgp_path_info
*pi
;
1850 struct bgp_path_info
*pi1
;
1851 struct bgp_path_info
*pi2
;
1852 struct bgp_path_info
*nextpi
= NULL
;
1853 int paths_eq
, do_mpath
, debug
;
1854 struct list mp_list
;
1855 char pfx_buf
[PREFIX2STR_BUFFER
];
1856 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1858 bgp_mp_list_init(&mp_list
);
1860 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1862 debug
= bgp_debug_bestpath(&rn
->p
);
1865 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1867 /* bgp deterministic-med */
1869 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1871 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1872 for (pi1
= rn
->info
; pi1
; pi1
= pi1
->next
)
1873 bgp_path_info_unset_flag(rn
, pi1
,
1874 BGP_PATH_DMED_SELECTED
);
1876 for (pi1
= rn
->info
; pi1
; pi1
= pi1
->next
) {
1877 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1879 if (BGP_PATH_HOLDDOWN(pi1
))
1881 if (pi1
->peer
&& pi1
->peer
!= bgp
->peer_self
)
1882 if (pi1
->peer
->status
!= Established
)
1887 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
1888 if (CHECK_FLAG(pi2
->flags
,
1889 BGP_PATH_DMED_CHECK
))
1891 if (BGP_PATH_HOLDDOWN(pi2
))
1894 && pi2
->peer
!= bgp
->peer_self
1897 PEER_STATUS_NSF_WAIT
))
1898 if (pi2
->peer
->status
1902 if (!aspath_cmp_left(pi1
->attr
->aspath
,
1904 && !aspath_cmp_left_confed(
1909 if (bgp_path_info_cmp(
1910 bgp
, pi2
, new_select
,
1911 &paths_eq
, mpath_cfg
, debug
,
1912 pfx_buf
, afi
, safi
)) {
1913 bgp_path_info_unset_flag(
1915 BGP_PATH_DMED_SELECTED
);
1919 bgp_path_info_set_flag(
1920 rn
, pi2
, BGP_PATH_DMED_CHECK
);
1923 bgp_path_info_set_flag(rn
, new_select
,
1924 BGP_PATH_DMED_CHECK
);
1925 bgp_path_info_set_flag(rn
, new_select
,
1926 BGP_PATH_DMED_SELECTED
);
1929 bgp_path_info_path_with_addpath_rx_str(
1930 new_select
, path_buf
);
1931 zlog_debug("%s: %s is the bestpath from AS %u",
1933 aspath_get_first_as(
1934 new_select
->attr
->aspath
));
1939 /* Check old selected route and new selected route. */
1942 for (pi
= rn
->info
; (pi
!= NULL
) && (nextpi
= pi
->next
, 1);
1944 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
1947 if (BGP_PATH_HOLDDOWN(pi
)) {
1948 /* reap REMOVED routes, if needs be
1949 * selected route must stay for a while longer though
1951 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
1952 && (pi
!= old_select
))
1953 bgp_path_info_reap(rn
, pi
);
1956 zlog_debug("%s: pi %p in holddown", __func__
,
1962 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
1963 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1964 if (pi
->peer
->status
!= Established
) {
1968 "%s: pi %p non self peer %s not estab state",
1969 __func__
, pi
, pi
->peer
->host
);
1974 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1975 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
1976 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
1978 zlog_debug("%s: pi %p dmed", __func__
, pi
);
1982 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
1984 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
1985 debug
, pfx_buf
, afi
, safi
)) {
1990 /* Now that we know which path is the bestpath see if any of the other
1992 * qualify as multipaths
1996 bgp_path_info_path_with_addpath_rx_str(new_select
,
1999 sprintf(path_buf
, "NONE");
2001 "%s: After path selection, newbest is %s oldbest was %s",
2003 old_select
? old_select
->peer
->host
: "NONE");
2006 if (do_mpath
&& new_select
) {
2007 for (pi
= rn
->info
; (pi
!= NULL
) && (nextpi
= pi
->next
, 1);
2011 bgp_path_info_path_with_addpath_rx_str(
2014 if (pi
== new_select
) {
2017 "%s: %s is the bestpath, add to the multipath list",
2019 bgp_mp_list_add(&mp_list
, pi
);
2023 if (BGP_PATH_HOLDDOWN(pi
))
2026 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2027 && !CHECK_FLAG(pi
->peer
->sflags
,
2028 PEER_STATUS_NSF_WAIT
))
2029 if (pi
->peer
->status
!= Established
)
2032 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2035 "%s: %s has the same nexthop as the bestpath, skip it",
2040 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2041 mpath_cfg
, debug
, pfx_buf
, afi
, safi
);
2046 "%s: %s is equivalent to the bestpath, add to the multipath list",
2048 bgp_mp_list_add(&mp_list
, pi
);
2053 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2055 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2056 bgp_mp_list_clear(&mp_list
);
2058 result
->old
= old_select
;
2059 result
->new = new_select
;
2065 * A new route/change in bestpath of an existing route. Evaluate the path
2066 * for advertisement to the subgroup.
2068 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2069 struct bgp_path_info
*selected
,
2070 struct bgp_node
*rn
,
2071 uint32_t addpath_tx_id
)
2074 struct peer
*onlypeer
;
2080 afi
= SUBGRP_AFI(subgrp
);
2081 safi
= SUBGRP_SAFI(subgrp
);
2082 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2085 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2086 char buf_prefix
[PREFIX_STRLEN
];
2087 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2088 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2092 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2093 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2094 PEER_STATUS_ORF_WAIT_REFRESH
))
2097 memset(&attr
, 0, sizeof(struct attr
));
2098 /* It's initialized in bgp_announce_check() */
2100 /* Announcement to the subgroup. If the route is filtered withdraw it.
2103 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2104 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2106 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2107 selected
->addpath_tx_id
);
2110 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2112 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2119 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2120 * This is called at the end of route processing.
2122 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2124 struct bgp_path_info
*pi
;
2126 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
2127 if (BGP_PATH_HOLDDOWN(pi
))
2129 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2130 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2135 * Has the route changed from the RIB's perspective? This is invoked only
2136 * if the route selection returns the same best route as earlier - to
2137 * determine if we need to update zebra or not.
2139 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2140 struct bgp_path_info
*selected
)
2142 struct bgp_path_info
*mpinfo
;
2144 /* If this is multipath, check all selected paths for any nexthop
2145 * change or attribute change. Some attribute changes (e.g., community)
2146 * aren't of relevance to the RIB, but we'll update zebra to ensure
2147 * we handle the case of BGP nexthop change. This is the behavior
2148 * when the best path has an attribute change anyway.
2150 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2151 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2155 * If this is multipath, check all selected paths for any nexthop change
2157 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2158 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2159 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2160 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2164 /* Nothing has changed from the RIB's perspective. */
2168 struct bgp_process_queue
{
2170 STAILQ_HEAD(, bgp_node
) pqueue
;
2171 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2173 unsigned int queued
;
2177 * old_select = The old best path
2178 * new_select = the new best path
2180 * if (!old_select && new_select)
2181 * We are sending new information on.
2183 * if (old_select && new_select) {
2184 * if (new_select != old_select)
2185 * We have a new best path send a change
2187 * We've received a update with new attributes that needs
2191 * if (old_select && !new_select)
2192 * We have no eligible route that we can announce or the rn
2195 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2196 afi_t afi
, safi_t safi
)
2198 struct bgp_path_info
*new_select
;
2199 struct bgp_path_info
*old_select
;
2200 struct bgp_path_info_pair old_and_new
;
2201 char pfx_buf
[PREFIX2STR_BUFFER
];
2204 /* Is it end of initial update? (after startup) */
2206 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2207 sizeof(bgp
->update_delay_zebra_resume_time
));
2209 bgp
->main_zebra_update_hold
= 0;
2210 FOREACH_AFI_SAFI (afi
, safi
) {
2211 if (bgp_fibupd_safi(safi
))
2212 bgp_zebra_announce_table(bgp
, afi
, safi
);
2214 bgp
->main_peers_update_hold
= 0;
2216 bgp_start_routeadv(bgp
);
2220 struct prefix
*p
= &rn
->p
;
2222 debug
= bgp_debug_bestpath(&rn
->p
);
2224 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2225 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2226 afi2str(afi
), safi2str(safi
));
2229 /* Best path selection. */
2230 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2232 old_select
= old_and_new
.old
;
2233 new_select
= old_and_new
.new;
2235 /* Do we need to allocate or free labels?
2236 * Right now, since we only deal with per-prefix labels, it is not
2237 * necessary to do this upon changes to best path except if the label
2240 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2243 || bgp_label_index_differs(new_select
, old_select
)
2244 || new_select
->sub_type
!= old_select
->sub_type
) {
2245 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2246 && new_select
->attr
->flag
2248 BGP_ATTR_PREFIX_SID
)
2249 && new_select
->attr
->label_index
2250 != BGP_INVALID_LABEL_INDEX
) {
2253 BGP_NODE_REGISTERED_FOR_LABEL
))
2254 bgp_unregister_for_label(rn
);
2255 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2257 bgp_set_valid_label(&rn
->local_label
);
2259 bgp_register_for_label(rn
, new_select
);
2261 } else if (CHECK_FLAG(rn
->flags
,
2262 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2263 bgp_unregister_for_label(rn
);
2265 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2266 bgp_unregister_for_label(rn
);
2270 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2272 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2273 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2274 old_select
, new_select
);
2277 /* If best route remains the same and this is not due to user-initiated
2278 * clear, see exactly what needs to be done.
2280 if (old_select
&& old_select
== new_select
2281 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2282 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2283 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2284 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2286 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2287 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2289 if (bgp_fibupd_safi(safi
)
2290 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2292 if (new_select
->type
== ZEBRA_ROUTE_BGP
2293 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2294 || new_select
->sub_type
2295 == BGP_ROUTE_IMPORTED
))
2297 bgp_zebra_announce(rn
, p
, old_select
,
2301 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2302 bgp_zebra_clear_route_change_flags(rn
);
2304 /* If there is a change of interest to peers, reannounce the
2306 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2307 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2308 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2310 /* unicast routes must also be annouced to
2311 * labeled-unicast update-groups */
2312 if (safi
== SAFI_UNICAST
)
2313 group_announce_route(bgp
, afi
,
2314 SAFI_LABELED_UNICAST
, rn
,
2317 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2318 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2321 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2325 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2327 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2329 /* bestpath has changed; bump version */
2330 if (old_select
|| new_select
) {
2331 bgp_bump_version(rn
);
2333 if (!bgp
->t_rmap_def_originate_eval
) {
2337 update_group_refresh_default_originate_route_map
,
2338 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2339 &bgp
->t_rmap_def_originate_eval
);
2344 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2347 zlog_debug("%s: setting SELECTED flag", __func__
);
2348 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2349 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2350 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2354 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2355 if (old_select
!= new_select
) {
2357 vnc_import_bgp_exterior_del_route(bgp
, p
,
2359 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2362 vnc_import_bgp_exterior_add_route(bgp
, p
,
2364 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2370 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2372 /* unicast routes must also be annouced to labeled-unicast update-groups
2374 if (safi
== SAFI_UNICAST
)
2375 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2379 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2380 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2381 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2382 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2383 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2384 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2386 /* if this is an evpn imported type-5 prefix,
2387 * we need to withdraw the route first to clear
2388 * the nh neigh and the RMAC entry.
2391 is_route_parent_evpn(old_select
))
2392 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2394 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2396 /* Withdraw the route from the kernel. */
2397 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2398 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2399 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2400 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2402 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2406 /* advertise/withdraw type-5 routes */
2407 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2408 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2409 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2411 /* apply the route-map */
2412 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2415 ret
= route_map_apply(
2416 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2417 &rn
->p
, RMAP_BGP
, new_select
);
2418 if (ret
== RMAP_MATCH
)
2419 bgp_evpn_advertise_type5_route(
2420 bgp
, &rn
->p
, new_select
->attr
,
2423 bgp_evpn_advertise_type5_route(bgp
,
2429 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2430 (!old_select
->extra
|| !old_select
->extra
->parent
))
2431 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2434 /* Clear any route change flags. */
2435 bgp_zebra_clear_route_change_flags(rn
);
2437 /* Reap old select bgp_path_info, if it has been removed */
2438 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2439 bgp_path_info_reap(rn
, old_select
);
2441 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2445 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2447 struct bgp_process_queue
*pqnode
= data
;
2448 struct bgp
*bgp
= pqnode
->bgp
;
2449 struct bgp_table
*table
;
2450 struct bgp_node
*rn
;
2453 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2454 bgp_process_main_one(bgp
, NULL
, 0, 0);
2455 /* should always have dedicated wq call */
2456 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2460 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2461 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2462 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2463 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2464 table
= bgp_node_table(rn
);
2465 /* note, new RNs may be added as part of processing */
2466 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2468 bgp_unlock_node(rn
);
2469 bgp_table_unlock(table
);
2475 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2477 struct bgp_process_queue
*pqnode
= data
;
2479 bgp_unlock(pqnode
->bgp
);
2481 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2484 void bgp_process_queue_init(void)
2486 if (!bm
->process_main_queue
)
2487 bm
->process_main_queue
=
2488 work_queue_new(bm
->master
, "process_main_queue");
2490 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2491 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2492 bm
->process_main_queue
->spec
.max_retries
= 0;
2493 bm
->process_main_queue
->spec
.hold
= 50;
2494 /* Use a higher yield value of 50ms for main queue processing */
2495 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2498 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2500 struct bgp_process_queue
*pqnode
;
2502 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2503 sizeof(struct bgp_process_queue
));
2505 /* unlocked in bgp_processq_del */
2506 pqnode
->bgp
= bgp_lock(bgp
);
2507 STAILQ_INIT(&pqnode
->pqueue
);
2512 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2514 #define ARBITRARY_PROCESS_QLEN 10000
2515 struct work_queue
*wq
= bm
->process_main_queue
;
2516 struct bgp_process_queue
*pqnode
;
2517 int pqnode_reuse
= 0;
2519 /* already scheduled for processing? */
2520 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2526 /* Add route nodes to an existing work queue item until reaching the
2527 limit only if is from the same BGP view and it's not an EOIU marker
2529 if (work_queue_item_count(wq
)) {
2530 struct work_queue_item
*item
= work_queue_last_item(wq
);
2531 pqnode
= item
->data
;
2533 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2534 || pqnode
->bgp
!= bgp
2535 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2536 pqnode
= bgp_processq_alloc(bgp
);
2540 pqnode
= bgp_processq_alloc(bgp
);
2541 /* all unlocked in bgp_process_wq */
2542 bgp_table_lock(bgp_node_table(rn
));
2544 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2547 /* can't be enqueued twice */
2548 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2549 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2553 work_queue_add(wq
, pqnode
);
2558 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2560 struct bgp_process_queue
*pqnode
;
2562 if (bm
->process_main_queue
== NULL
)
2565 pqnode
= bgp_processq_alloc(bgp
);
2567 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2568 work_queue_add(bm
->process_main_queue
, pqnode
);
2571 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2575 peer
= THREAD_ARG(thread
);
2576 peer
->t_pmax_restart
= NULL
;
2578 if (bgp_debug_neighbor_events(peer
))
2580 "%s Maximum-prefix restart timer expired, restore peering",
2583 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2584 zlog_debug("%s: %s peer_clear failed",
2585 __PRETTY_FUNCTION__
, peer
->host
);
2590 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2594 iana_safi_t pkt_safi
;
2596 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2599 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2600 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2601 PEER_STATUS_PREFIX_LIMIT
)
2606 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2608 afi_safi_print(afi
, safi
), peer
->host
,
2609 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2610 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2612 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2613 PEER_FLAG_MAX_PREFIX_WARNING
))
2616 /* Convert AFI, SAFI to values for packet. */
2617 pkt_afi
= afi_int2iana(afi
);
2618 pkt_safi
= safi_int2iana(safi
);
2622 ndata
[0] = (pkt_afi
>> 8);
2624 ndata
[2] = pkt_safi
;
2625 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2626 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2627 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2628 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2630 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2631 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2632 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2636 /* Dynamic peers will just close their connection. */
2637 if (peer_dynamic_neighbor(peer
))
2640 /* restart timer start */
2641 if (peer
->pmax_restart
[afi
][safi
]) {
2642 peer
->v_pmax_restart
=
2643 peer
->pmax_restart
[afi
][safi
] * 60;
2645 if (bgp_debug_neighbor_events(peer
))
2647 "%s Maximum-prefix restart timer started for %d secs",
2648 peer
->host
, peer
->v_pmax_restart
);
2650 BGP_TIMER_ON(peer
->t_pmax_restart
,
2651 bgp_maximum_prefix_restart_timer
,
2652 peer
->v_pmax_restart
);
2657 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2658 PEER_STATUS_PREFIX_LIMIT
);
2660 if (peer
->pcount
[afi
][safi
]
2661 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2662 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2663 PEER_STATUS_PREFIX_THRESHOLD
)
2668 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2669 afi_safi_print(afi
, safi
), peer
->host
,
2670 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2671 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2672 PEER_STATUS_PREFIX_THRESHOLD
);
2674 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2675 PEER_STATUS_PREFIX_THRESHOLD
);
2679 /* Unconditionally remove the route from the RIB, without taking
2680 * damping into consideration (eg, because the session went down)
2682 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2683 struct peer
*peer
, afi_t afi
, safi_t safi
)
2685 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2687 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2688 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2690 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2693 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2694 struct peer
*peer
, afi_t afi
, safi_t safi
,
2695 struct prefix_rd
*prd
)
2697 /* apply dampening, if result is suppressed, we'll be retaining
2698 * the bgp_path_info in the RIB for historical reference.
2700 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2701 && peer
->sort
== BGP_PEER_EBGP
)
2702 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2703 == BGP_DAMP_SUPPRESSED
) {
2704 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2710 if (safi
== SAFI_MPLS_VPN
) {
2711 struct bgp_node
*prn
= NULL
;
2712 struct bgp_table
*table
= NULL
;
2714 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2715 (struct prefix
*)prd
);
2717 table
= (struct bgp_table
*)(prn
->info
);
2719 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2720 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2722 bgp_unlock_node(prn
);
2724 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2725 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2727 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2728 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2734 /* If this is an EVPN route, process for un-import. */
2735 if (safi
== SAFI_EVPN
)
2736 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2738 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2741 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2742 struct peer
*peer
, struct attr
*attr
,
2743 struct bgp_node
*rn
)
2745 struct bgp_path_info
*new;
2747 /* Make new BGP info. */
2748 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2750 new->instance
= instance
;
2751 new->sub_type
= sub_type
;
2754 new->uptime
= bgp_clock();
2756 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2760 static void overlay_index_update(struct attr
*attr
,
2761 struct eth_segment_id
*eth_s_id
,
2762 union gw_addr
*gw_ip
)
2767 if (eth_s_id
== NULL
) {
2768 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2769 sizeof(struct eth_segment_id
));
2771 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2772 sizeof(struct eth_segment_id
));
2774 if (gw_ip
== NULL
) {
2775 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2777 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2778 sizeof(union gw_addr
));
2782 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2783 struct eth_segment_id
*eth_s_id
,
2784 union gw_addr
*gw_ip
)
2786 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2787 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2789 struct eth_segment_id esi
;
2793 if (afi
!= AFI_L2VPN
)
2796 memset(&temp
, 0, sizeof(temp
));
2797 path_eth_s_id
= &temp
.esi
;
2798 path_gw_ip
= &temp
.ip
;
2800 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2803 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2804 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2807 if (gw_ip
== NULL
) {
2808 memset(&temp
, 0, sizeof(temp
));
2809 path_gw_ip_remote
= &temp
.ip
;
2811 path_gw_ip_remote
= gw_ip
;
2813 if (eth_s_id
== NULL
) {
2814 memset(&temp
, 0, sizeof(temp
));
2815 path_eth_s_id_remote
= &temp
.esi
;
2817 path_eth_s_id_remote
= eth_s_id
;
2819 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2822 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2823 sizeof(struct eth_segment_id
));
2826 /* Check if received nexthop is valid or not. */
2827 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2832 /* Only validated for unicast and multicast currently. */
2833 /* Also valid for EVPN where the nexthop is an IP address. */
2834 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2837 /* If NEXT_HOP is present, validate it. */
2838 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2839 if (attr
->nexthop
.s_addr
== 0
2840 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2841 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2845 /* If MP_NEXTHOP is present, validate it. */
2846 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2847 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2848 * it is not an IPv6 link-local address.
2850 if (attr
->mp_nexthop_len
) {
2851 switch (attr
->mp_nexthop_len
) {
2852 case BGP_ATTR_NHLEN_IPV4
:
2853 case BGP_ATTR_NHLEN_VPNV4
:
2854 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2855 || IPV4_CLASS_DE(ntohl(
2856 attr
->mp_nexthop_global_in
.s_addr
))
2857 || bgp_nexthop_self(bgp
,
2858 attr
->mp_nexthop_global_in
));
2861 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2862 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2863 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2864 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2865 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2866 || IN6_IS_ADDR_MULTICAST(
2867 &attr
->mp_nexthop_global
));
2879 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2880 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2881 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2882 uint32_t num_labels
, int soft_reconfig
,
2883 struct bgp_route_evpn
*evpn
)
2886 int aspath_loop_count
= 0;
2887 struct bgp_node
*rn
;
2889 struct attr new_attr
;
2890 struct attr
*attr_new
;
2891 struct bgp_path_info
*pi
;
2892 struct bgp_path_info
*new;
2893 struct bgp_path_info_extra
*extra
;
2895 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2897 int do_loop_check
= 1;
2898 int has_valid_label
= 0;
2900 int vnc_implicit_withdraw
= 0;
2904 memset(&new_attr
, 0, sizeof(struct attr
));
2905 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2906 new_attr
.label
= MPLS_INVALID_LABEL
;
2909 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2910 /* TODO: Check to see if we can get rid of "is_valid_label" */
2911 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2912 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2914 has_valid_label
= bgp_is_valid_label(label
);
2916 /* When peer's soft reconfiguration enabled. Record input packet in
2919 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2920 && peer
!= bgp
->peer_self
)
2921 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2923 /* Check previously received route. */
2924 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
2925 if (pi
->peer
== peer
&& pi
->type
== type
2926 && pi
->sub_type
== sub_type
2927 && pi
->addpath_rx_id
== addpath_id
)
2930 /* AS path local-as loop check. */
2931 if (peer
->change_local_as
) {
2932 if (peer
->allowas_in
[afi
][safi
])
2933 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2934 else if (!CHECK_FLAG(peer
->flags
,
2935 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2936 aspath_loop_count
= 1;
2938 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2939 > aspath_loop_count
) {
2940 reason
= "as-path contains our own AS;";
2945 /* If the peer is configured for "allowas-in origin" and the last ASN in
2947 * as-path is our ASN then we do not need to call aspath_loop_check
2949 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2950 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2953 /* AS path loop check. */
2954 if (do_loop_check
) {
2955 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2956 > peer
->allowas_in
[afi
][safi
]
2957 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2958 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2959 > peer
->allowas_in
[afi
][safi
])) {
2960 reason
= "as-path contains our own AS;";
2965 /* Route reflector originator ID check. */
2966 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2967 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2968 reason
= "originator is us;";
2972 /* Route reflector cluster ID check. */
2973 if (bgp_cluster_filter(peer
, attr
)) {
2974 reason
= "reflected from the same cluster;";
2978 /* Apply incoming filter. */
2979 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2984 bgp_attr_dup(&new_attr
, attr
);
2986 /* Apply incoming route-map.
2987 * NB: new_attr may now contain newly allocated values from route-map
2989 * commands, so we need bgp_attr_flush in the error paths, until we
2991 * the attr (which takes over the memory references) */
2992 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2994 reason
= "route-map;";
2995 bgp_attr_flush(&new_attr
);
2999 if (peer
->sort
== BGP_PEER_EBGP
) {
3001 /* If we receive the graceful-shutdown community from an eBGP
3002 * peer we must lower local-preference */
3003 if (new_attr
.community
3004 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3005 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3006 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3008 /* If graceful-shutdown is configured then add the GSHUT
3009 * community to all paths received from eBGP peers */
3010 } else if (bgp_flag_check(peer
->bgp
,
3011 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3012 bgp_attr_add_gshut_community(&new_attr
);
3016 /* next hop check. */
3017 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3018 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3019 reason
= "martian or self next-hop;";
3020 bgp_attr_flush(&new_attr
);
3024 attr_new
= bgp_attr_intern(&new_attr
);
3026 /* If the update is implicit withdraw. */
3028 pi
->uptime
= bgp_clock();
3029 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3031 /* Same attribute comes in. */
3032 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3033 && attrhash_cmp(pi
->attr
, attr_new
)
3034 && (!has_valid_label
3035 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3036 num_labels
* sizeof(mpls_label_t
))
3038 && (overlay_index_equal(
3039 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3040 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3041 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3042 BGP_CONFIG_DAMPENING
)
3043 && peer
->sort
== BGP_PEER_EBGP
3044 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3045 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3046 bgp_debug_rdpfxpath2str(
3047 afi
, safi
, prd
, p
, label
,
3048 num_labels
, addpath_id
? 1 : 0,
3049 addpath_id
, pfx_buf
,
3051 zlog_debug("%s rcvd %s", peer
->host
,
3055 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3056 != BGP_DAMP_SUPPRESSED
) {
3057 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3059 bgp_process(bgp
, rn
, afi
, safi
);
3061 } else /* Duplicate - odd */
3063 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3064 if (!peer
->rcvd_attr_printed
) {
3066 "%s rcvd UPDATE w/ attr: %s",
3068 peer
->rcvd_attr_str
);
3069 peer
->rcvd_attr_printed
= 1;
3072 bgp_debug_rdpfxpath2str(
3073 afi
, safi
, prd
, p
, label
,
3074 num_labels
, addpath_id
? 1 : 0,
3075 addpath_id
, pfx_buf
,
3078 "%s rcvd %s...duplicate ignored",
3079 peer
->host
, pfx_buf
);
3082 /* graceful restart STALE flag unset. */
3083 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3084 bgp_path_info_unset_flag(
3085 rn
, pi
, BGP_PATH_STALE
);
3086 bgp_process(bgp
, rn
, afi
, safi
);
3090 bgp_unlock_node(rn
);
3091 bgp_attr_unintern(&attr_new
);
3096 /* Withdraw/Announce before we fully processed the withdraw */
3097 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3098 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3099 bgp_debug_rdpfxpath2str(
3100 afi
, safi
, prd
, p
, label
, num_labels
,
3101 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3104 "%s rcvd %s, flapped quicker than processing",
3105 peer
->host
, pfx_buf
);
3108 bgp_path_info_restore(rn
, pi
);
3111 /* Received Logging. */
3112 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3113 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3114 num_labels
, addpath_id
? 1 : 0,
3115 addpath_id
, pfx_buf
,
3117 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3120 /* graceful restart STALE flag unset. */
3121 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3122 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3124 /* The attribute is changed. */
3125 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3127 /* implicit withdraw, decrement aggregate and pcount here.
3128 * only if update is accepted, they'll increment below.
3130 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3132 /* Update bgp route dampening information. */
3133 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3134 && peer
->sort
== BGP_PEER_EBGP
) {
3135 /* This is implicit withdraw so we should update
3138 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3139 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3142 if (safi
== SAFI_MPLS_VPN
) {
3143 struct bgp_node
*prn
= NULL
;
3144 struct bgp_table
*table
= NULL
;
3146 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3147 (struct prefix
*)prd
);
3149 table
= (struct bgp_table
*)(prn
->info
);
3151 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3152 bgp
, prd
, table
, p
, pi
);
3154 bgp_unlock_node(prn
);
3156 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3157 && (safi
== SAFI_UNICAST
)) {
3158 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3160 * Implicit withdraw case.
3162 ++vnc_implicit_withdraw
;
3163 vnc_import_bgp_del_route(bgp
, p
, pi
);
3164 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3169 /* Special handling for EVPN update of an existing route. If the
3170 * extended community attribute has changed, we need to
3172 * the route using its existing extended community. It will be
3173 * subsequently processed for import with the new extended
3176 if (safi
== SAFI_EVPN
&& !same_attr
) {
3178 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3180 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3183 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3184 attr_new
->ecommunity
);
3186 if (bgp_debug_update(peer
, p
, NULL
, 1))
3188 "Change in EXT-COMM, existing %s new %s",
3190 pi
->attr
->ecommunity
),
3192 attr_new
->ecommunity
));
3193 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3199 /* Update to new attribute. */
3200 bgp_attr_unintern(&pi
->attr
);
3201 pi
->attr
= attr_new
;
3203 /* Update MPLS label */
3204 if (has_valid_label
) {
3205 extra
= bgp_path_info_extra_get(pi
);
3206 memcpy(&extra
->label
, label
,
3207 num_labels
* sizeof(mpls_label_t
));
3208 extra
->num_labels
= num_labels
;
3209 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3210 bgp_set_valid_label(&extra
->label
[0]);
3214 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3215 && (safi
== SAFI_UNICAST
)) {
3216 if (vnc_implicit_withdraw
) {
3218 * Add back the route with its new attributes
3220 * The route is still selected, until the route
3222 * queued by bgp_process actually runs. We have
3224 * update to the VNC side immediately to avoid
3226 * configuration changes (e.g., route-map
3228 * trigger re-importation of the entire RIB.
3230 vnc_import_bgp_add_route(bgp
, p
, pi
);
3231 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3235 /* Update Overlay Index */
3236 if (afi
== AFI_L2VPN
) {
3237 overlay_index_update(
3238 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3239 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3242 /* Update bgp route dampening information. */
3243 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3244 && peer
->sort
== BGP_PEER_EBGP
) {
3245 /* Now we do normal update dampening. */
3246 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3247 if (ret
== BGP_DAMP_SUPPRESSED
) {
3248 bgp_unlock_node(rn
);
3253 /* Nexthop reachability check - for unicast and
3254 * labeled-unicast.. */
3255 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3256 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3257 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3258 && !CHECK_FLAG(peer
->flags
,
3259 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3261 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3266 struct bgp
*bgp_nexthop
= bgp
;
3268 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3269 bgp_nexthop
= pi
->extra
->bgp_orig
;
3271 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3273 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3274 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3276 if (BGP_DEBUG(nht
, NHT
)) {
3277 char buf1
[INET6_ADDRSTRLEN
];
3279 (const void *)&attr_new
3281 buf1
, INET6_ADDRSTRLEN
);
3282 zlog_debug("%s(%s): NH unresolved",
3283 __FUNCTION__
, buf1
);
3285 bgp_path_info_unset_flag(rn
, pi
,
3289 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3292 if (safi
== SAFI_MPLS_VPN
) {
3293 struct bgp_node
*prn
= NULL
;
3294 struct bgp_table
*table
= NULL
;
3296 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3297 (struct prefix
*)prd
);
3299 table
= (struct bgp_table
*)(prn
->info
);
3301 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3302 bgp
, prd
, table
, p
, pi
);
3304 bgp_unlock_node(prn
);
3308 /* If this is an EVPN route and some attribute has changed,
3310 * route for import. If the extended community has changed, we
3312 * have done the un-import earlier and the import would result
3314 * route getting injected into appropriate L2 VNIs. If it is
3316 * some other attribute change, the import will result in
3318 * the attributes for the route in the VNI(s).
3320 if (safi
== SAFI_EVPN
&& !same_attr
)
3321 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3323 /* Process change. */
3324 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3326 bgp_process(bgp
, rn
, afi
, safi
);
3327 bgp_unlock_node(rn
);
3329 if (SAFI_UNICAST
== safi
3330 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3331 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3333 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3335 if ((SAFI_MPLS_VPN
== safi
)
3336 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3338 vpn_leak_to_vrf_update(bgp
, pi
);
3342 if (SAFI_MPLS_VPN
== safi
) {
3343 mpls_label_t label_decoded
= decode_label(label
);
3345 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3346 type
, sub_type
, &label_decoded
);
3348 if (SAFI_ENCAP
== safi
) {
3349 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3350 type
, sub_type
, NULL
);
3355 } // End of implicit withdraw
3357 /* Received Logging. */
3358 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3359 if (!peer
->rcvd_attr_printed
) {
3360 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3361 peer
->rcvd_attr_str
);
3362 peer
->rcvd_attr_printed
= 1;
3365 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3366 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3368 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3371 /* Make new BGP info. */
3372 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3374 /* Update MPLS label */
3375 if (has_valid_label
) {
3376 extra
= bgp_path_info_extra_get(new);
3377 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3378 extra
->num_labels
= num_labels
;
3379 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3380 bgp_set_valid_label(&extra
->label
[0]);
3383 /* Update Overlay Index */
3384 if (afi
== AFI_L2VPN
) {
3385 overlay_index_update(new->attr
,
3386 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3387 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3389 /* Nexthop reachability check. */
3390 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3391 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3392 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3393 && !CHECK_FLAG(peer
->flags
,
3394 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3395 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3400 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3401 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3402 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3404 if (BGP_DEBUG(nht
, NHT
)) {
3405 char buf1
[INET6_ADDRSTRLEN
];
3407 (const void *)&attr_new
->nexthop
,
3408 buf1
, INET6_ADDRSTRLEN
);
3409 zlog_debug("%s(%s): NH unresolved",
3410 __FUNCTION__
, buf1
);
3412 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3415 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3418 new->addpath_rx_id
= addpath_id
;
3420 /* Increment prefix */
3421 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3423 /* Register new BGP information. */
3424 bgp_path_info_add(rn
, new);
3426 /* route_node_get lock */
3427 bgp_unlock_node(rn
);
3430 if (safi
== SAFI_MPLS_VPN
) {
3431 struct bgp_node
*prn
= NULL
;
3432 struct bgp_table
*table
= NULL
;
3434 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3436 table
= (struct bgp_table
*)(prn
->info
);
3438 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3439 bgp
, prd
, table
, p
, new);
3441 bgp_unlock_node(prn
);
3445 /* If maximum prefix count is configured and current prefix
3447 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3450 /* If this is an EVPN route, process for import. */
3451 if (safi
== SAFI_EVPN
)
3452 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3454 /* Process change. */
3455 bgp_process(bgp
, rn
, afi
, safi
);
3457 if (SAFI_UNICAST
== safi
3458 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3459 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3460 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3462 if ((SAFI_MPLS_VPN
== safi
)
3463 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3465 vpn_leak_to_vrf_update(bgp
, new);
3468 if (SAFI_MPLS_VPN
== safi
) {
3469 mpls_label_t label_decoded
= decode_label(label
);
3471 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3472 sub_type
, &label_decoded
);
3474 if (SAFI_ENCAP
== safi
) {
3475 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3482 /* This BGP update is filtered. Log the reason then update BGP
3485 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3486 if (!peer
->rcvd_attr_printed
) {
3487 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3488 peer
->rcvd_attr_str
);
3489 peer
->rcvd_attr_printed
= 1;
3492 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3493 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3495 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3496 peer
->host
, pfx_buf
, reason
);
3500 /* If this is an EVPN route, un-import it as it is now filtered.
3502 if (safi
== SAFI_EVPN
)
3503 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3505 if (SAFI_UNICAST
== safi
3506 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3507 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3509 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3511 if ((SAFI_MPLS_VPN
== safi
)
3512 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3514 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3517 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3520 bgp_unlock_node(rn
);
3524 * Filtered update is treated as an implicit withdrawal (see
3526 * a few lines above)
3528 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3529 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3537 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3538 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3539 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3540 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3543 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3544 struct bgp_node
*rn
;
3545 struct bgp_path_info
*pi
;
3548 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3549 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3557 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3559 /* If peer is soft reconfiguration enabled. Record input packet for
3560 * further calculation.
3562 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3563 * routes that are filtered. This tanks out Quagga RS pretty badly due
3565 * the iteration over all RS clients.
3566 * Since we need to remove the entry from adj_in anyway, do that first
3568 * if there was no entry, we don't need to do anything more.
3570 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3571 && peer
!= bgp
->peer_self
)
3572 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3573 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3574 bgp_debug_rdpfxpath2str(
3575 afi
, safi
, prd
, p
, label
, num_labels
,
3576 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3579 "%s withdrawing route %s not in adj-in",
3580 peer
->host
, pfx_buf
);
3582 bgp_unlock_node(rn
);
3586 /* Lookup withdrawn route. */
3587 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
3588 if (pi
->peer
== peer
&& pi
->type
== type
3589 && pi
->sub_type
== sub_type
3590 && pi
->addpath_rx_id
== addpath_id
)
3594 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3595 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3596 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3598 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3602 /* Withdraw specified route from routing table. */
3603 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3604 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3605 if (SAFI_UNICAST
== safi
3606 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3607 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3608 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3610 if ((SAFI_MPLS_VPN
== safi
)
3611 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3613 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3615 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3616 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3617 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3619 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3622 /* Unlock bgp_node_get() lock. */
3623 bgp_unlock_node(rn
);
3628 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3631 struct update_subgroup
*subgrp
;
3632 subgrp
= peer_subgroup(peer
, afi
, safi
);
3633 subgroup_default_originate(subgrp
, withdraw
);
3638 * bgp_stop_announce_route_timer
3640 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3642 if (!paf
->t_announce_route
)
3645 THREAD_TIMER_OFF(paf
->t_announce_route
);
3649 * bgp_announce_route_timer_expired
3651 * Callback that is invoked when the route announcement timer for a
3654 static int bgp_announce_route_timer_expired(struct thread
*t
)
3656 struct peer_af
*paf
;
3659 paf
= THREAD_ARG(t
);
3662 if (peer
->status
!= Established
)
3665 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3668 peer_af_announce_route(paf
, 1);
3673 * bgp_announce_route
3675 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3677 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3679 struct peer_af
*paf
;
3680 struct update_subgroup
*subgrp
;
3682 paf
= peer_af_find(peer
, afi
, safi
);
3685 subgrp
= PAF_SUBGRP(paf
);
3688 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3689 * or a refresh has already been triggered.
3691 if (!subgrp
|| paf
->t_announce_route
)
3695 * Start a timer to stagger/delay the announce. This serves
3696 * two purposes - announcement can potentially be combined for
3697 * multiple peers and the announcement doesn't happen in the
3700 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3701 (subgrp
->peer_count
== 1)
3702 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3703 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3704 &paf
->t_announce_route
);
3708 * Announce routes from all AF tables to a peer.
3710 * This should ONLY be called when there is a need to refresh the
3711 * routes to the peer based on a policy change for this peer alone
3712 * or a route refresh request received from the peer.
3713 * The operation will result in splitting the peer from its existing
3714 * subgroups and putting it in new subgroups.
3716 void bgp_announce_route_all(struct peer
*peer
)
3721 FOREACH_AFI_SAFI (afi
, safi
)
3722 bgp_announce_route(peer
, afi
, safi
);
3725 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3726 struct bgp_table
*table
,
3727 struct prefix_rd
*prd
)
3730 struct bgp_node
*rn
;
3731 struct bgp_adj_in
*ain
;
3734 table
= peer
->bgp
->rib
[afi
][safi
];
3736 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3737 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3738 if (ain
->peer
!= peer
)
3741 struct bgp_path_info
*pi
= rn
->info
;
3742 uint32_t num_labels
= 0;
3743 mpls_label_t
*label_pnt
= NULL
;
3745 if (pi
&& pi
->extra
)
3746 num_labels
= pi
->extra
->num_labels
;
3748 label_pnt
= &pi
->extra
->label
[0];
3750 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3751 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3752 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3753 num_labels
, 1, NULL
);
3756 bgp_unlock_node(rn
);
3762 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3764 struct bgp_node
*rn
;
3765 struct bgp_table
*table
;
3767 if (peer
->status
!= Established
)
3770 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3771 && (safi
!= SAFI_EVPN
))
3772 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3774 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3775 rn
= bgp_route_next(rn
))
3776 if ((table
= rn
->info
) != NULL
) {
3777 struct prefix_rd prd
;
3778 prd
.family
= AF_UNSPEC
;
3780 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3782 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3788 struct bgp_clear_node_queue
{
3789 struct bgp_node
*rn
;
3792 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3794 struct bgp_clear_node_queue
*cnq
= data
;
3795 struct bgp_node
*rn
= cnq
->rn
;
3796 struct peer
*peer
= wq
->spec
.data
;
3797 struct bgp_path_info
*pi
;
3799 afi_t afi
= bgp_node_table(rn
)->afi
;
3800 safi_t safi
= bgp_node_table(rn
)->safi
;
3805 /* It is possible that we have multiple paths for a prefix from a peer
3806 * if that peer is using AddPath.
3808 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
3809 if (pi
->peer
!= peer
)
3812 /* graceful restart STALE flag set. */
3813 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3814 && peer
->nsf
[afi
][safi
]
3815 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3816 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3817 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3819 /* If this is an EVPN route, process for
3821 if (safi
== SAFI_EVPN
)
3822 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3824 /* Handle withdraw for VRF route-leaking and L3VPN */
3825 if (SAFI_UNICAST
== safi
3826 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3827 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3828 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3831 if (SAFI_MPLS_VPN
== safi
&&
3832 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3833 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3836 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3842 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3844 struct bgp_clear_node_queue
*cnq
= data
;
3845 struct bgp_node
*rn
= cnq
->rn
;
3846 struct bgp_table
*table
= bgp_node_table(rn
);
3848 bgp_unlock_node(rn
);
3849 bgp_table_unlock(table
);
3850 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3853 static void bgp_clear_node_complete(struct work_queue
*wq
)
3855 struct peer
*peer
= wq
->spec
.data
;
3857 /* Tickle FSM to start moving again */
3858 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3860 peer_unlock(peer
); /* bgp_clear_route */
3863 static void bgp_clear_node_queue_init(struct peer
*peer
)
3865 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3867 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3868 #undef CLEAR_QUEUE_NAME_LEN
3870 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3871 peer
->clear_node_queue
->spec
.hold
= 10;
3872 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3873 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3874 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3875 peer
->clear_node_queue
->spec
.max_retries
= 0;
3877 /* we only 'lock' this peer reference when the queue is actually active
3879 peer
->clear_node_queue
->spec
.data
= peer
;
3882 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3883 struct bgp_table
*table
)
3885 struct bgp_node
*rn
;
3886 int force
= bm
->process_main_queue
? 0 : 1;
3889 table
= peer
->bgp
->rib
[afi
][safi
];
3891 /* If still no table => afi/safi isn't configured at all or smth. */
3895 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3896 struct bgp_path_info
*pi
, *next
;
3897 struct bgp_adj_in
*ain
;
3898 struct bgp_adj_in
*ain_next
;
3900 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3901 * queued for every clearing peer, regardless of whether it is
3902 * relevant to the peer at hand.
3904 * Overview: There are 3 different indices which need to be
3905 * scrubbed, potentially, when a peer is removed:
3907 * 1 peer's routes visible via the RIB (ie accepted routes)
3908 * 2 peer's routes visible by the (optional) peer's adj-in index
3909 * 3 other routes visible by the peer's adj-out index
3911 * 3 there is no hurry in scrubbing, once the struct peer is
3912 * removed from bgp->peer, we could just GC such deleted peer's
3913 * adj-outs at our leisure.
3915 * 1 and 2 must be 'scrubbed' in some way, at least made
3916 * invisible via RIB index before peer session is allowed to be
3917 * brought back up. So one needs to know when such a 'search' is
3922 * - there'd be a single global queue or a single RIB walker
3923 * - rather than tracking which route_nodes still need to be
3924 * examined on a peer basis, we'd track which peers still
3927 * Given that our per-peer prefix-counts now should be reliable,
3928 * this may actually be achievable. It doesn't seem to be a huge
3929 * problem at this time,
3931 * It is possible that we have multiple paths for a prefix from
3933 * if that peer is using AddPath.
3937 ain_next
= ain
->next
;
3939 if (ain
->peer
== peer
) {
3940 bgp_adj_in_remove(rn
, ain
);
3941 bgp_unlock_node(rn
);
3947 for (pi
= rn
->info
; pi
; pi
= next
) {
3949 if (pi
->peer
!= peer
)
3953 bgp_path_info_reap(rn
, pi
);
3955 struct bgp_clear_node_queue
*cnq
;
3957 /* both unlocked in bgp_clear_node_queue_del */
3958 bgp_table_lock(bgp_node_table(rn
));
3961 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3962 sizeof(struct bgp_clear_node_queue
));
3964 work_queue_add(peer
->clear_node_queue
, cnq
);
3972 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3974 struct bgp_node
*rn
;
3975 struct bgp_table
*table
;
3977 if (peer
->clear_node_queue
== NULL
)
3978 bgp_clear_node_queue_init(peer
);
3980 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3981 * Idle until it receives a Clearing_Completed event. This protects
3982 * against peers which flap faster than we can we clear, which could
3985 * a) race with routes from the new session being installed before
3986 * clear_route_node visits the node (to delete the route of that
3988 * b) resource exhaustion, clear_route_node likely leads to an entry
3989 * on the process_main queue. Fast-flapping could cause that queue
3993 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3994 * the unlock will happen upon work-queue completion; other wise, the
3995 * unlock happens at the end of this function.
3997 if (!peer
->clear_node_queue
->thread
)
4000 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4001 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4003 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4004 rn
= bgp_route_next(rn
))
4005 if ((table
= rn
->info
) != NULL
)
4006 bgp_clear_route_table(peer
, afi
, safi
, table
);
4008 /* unlock if no nodes got added to the clear-node-queue. */
4009 if (!peer
->clear_node_queue
->thread
)
4013 void bgp_clear_route_all(struct peer
*peer
)
4018 FOREACH_AFI_SAFI (afi
, safi
)
4019 bgp_clear_route(peer
, afi
, safi
);
4022 rfapiProcessPeerDown(peer
);
4026 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4028 struct bgp_table
*table
;
4029 struct bgp_node
*rn
;
4030 struct bgp_adj_in
*ain
;
4031 struct bgp_adj_in
*ain_next
;
4033 table
= peer
->bgp
->rib
[afi
][safi
];
4035 /* It is possible that we have multiple paths for a prefix from a peer
4036 * if that peer is using AddPath.
4038 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4042 ain_next
= ain
->next
;
4044 if (ain
->peer
== peer
) {
4045 bgp_adj_in_remove(rn
, ain
);
4046 bgp_unlock_node(rn
);
4054 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4056 struct bgp_node
*rn
;
4057 struct bgp_path_info
*pi
;
4058 struct bgp_table
*table
;
4060 if (safi
== SAFI_MPLS_VPN
) {
4061 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4062 rn
= bgp_route_next(rn
)) {
4063 struct bgp_node
*rm
;
4065 /* look for neighbor in tables */
4066 if ((table
= rn
->info
) == NULL
)
4069 for (rm
= bgp_table_top(table
); rm
;
4070 rm
= bgp_route_next(rm
))
4071 for (pi
= rm
->info
; pi
; pi
= pi
->next
) {
4072 if (pi
->peer
!= peer
)
4074 if (!CHECK_FLAG(pi
->flags
,
4078 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4083 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4084 rn
= bgp_route_next(rn
))
4085 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
4086 if (pi
->peer
!= peer
)
4088 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4090 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4096 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4099 struct bgp_node
*rn
;
4100 struct bgp_path_info
*pi
;
4101 struct bgp_path_info
*next
;
4103 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4104 for (pi
= rn
->info
; pi
; pi
= next
) {
4106 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4107 && pi
->type
== ZEBRA_ROUTE_BGP
4108 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4109 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4110 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4112 if (bgp_fibupd_safi(safi
))
4113 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4115 bgp_path_info_reap(rn
, pi
);
4120 /* Delete all kernel routes. */
4121 void bgp_cleanup_routes(struct bgp
*bgp
)
4124 struct bgp_node
*rn
;
4126 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4127 if (afi
== AFI_L2VPN
)
4129 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4132 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4134 if (afi
!= AFI_L2VPN
) {
4136 safi
= SAFI_MPLS_VPN
;
4137 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4138 rn
= bgp_route_next(rn
)) {
4140 bgp_cleanup_table(bgp
,
4141 (struct bgp_table
*)(rn
->info
),
4143 bgp_table_finish((struct bgp_table
**)&(
4146 bgp_unlock_node(rn
);
4150 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4151 rn
= bgp_route_next(rn
)) {
4153 bgp_cleanup_table(bgp
,
4154 (struct bgp_table
*)(rn
->info
),
4156 bgp_table_finish((struct bgp_table
**)&(
4159 bgp_unlock_node(rn
);
4164 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4165 rn
= bgp_route_next(rn
)) {
4167 bgp_cleanup_table(bgp
,
4168 (struct bgp_table
*)(rn
->info
),
4170 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4172 bgp_unlock_node(rn
);
4177 void bgp_reset(void)
4180 bgp_zclient_reset();
4181 access_list_reset();
4182 prefix_list_reset();
4185 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4187 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4188 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4189 PEER_CAP_ADDPATH_AF_TX_RCV
));
4192 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4194 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4195 struct bgp_nlri
*packet
)
4204 int addpath_encoded
;
4205 uint32_t addpath_id
;
4208 lim
= pnt
+ packet
->length
;
4210 safi
= packet
->safi
;
4212 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4214 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4215 syntactic validity. If the field is syntactically incorrect,
4216 then the Error Subcode is set to Invalid Network Field. */
4217 for (; pnt
< lim
; pnt
+= psize
) {
4218 /* Clear prefix structure. */
4219 memset(&p
, 0, sizeof(struct prefix
));
4221 if (addpath_encoded
) {
4223 /* When packet overflow occurs return immediately. */
4224 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4227 addpath_id
= ntohl(*((uint32_t *)pnt
));
4228 pnt
+= BGP_ADDPATH_ID_LEN
;
4231 /* Fetch prefix length. */
4232 p
.prefixlen
= *pnt
++;
4233 /* afi/safi validity already verified by caller,
4234 * bgp_update_receive */
4235 p
.family
= afi2family(afi
);
4237 /* Prefix length check. */
4238 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4241 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4242 peer
->host
, p
.prefixlen
, packet
->afi
);
4246 /* Packet size overflow check. */
4247 psize
= PSIZE(p
.prefixlen
);
4249 /* When packet overflow occur return immediately. */
4250 if (pnt
+ psize
> lim
) {
4253 "%s [Error] Update packet error (prefix length %d overflows packet)",
4254 peer
->host
, p
.prefixlen
);
4258 /* Defensive coding, double-check the psize fits in a struct
4260 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4263 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4264 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4268 /* Fetch prefix from NLRI packet. */
4269 memcpy(p
.u
.val
, pnt
, psize
);
4271 /* Check address. */
4272 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4273 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4274 /* From RFC4271 Section 6.3:
4276 * If a prefix in the NLRI field is semantically
4278 * (e.g., an unexpected multicast IP address),
4280 * be logged locally, and the prefix SHOULD be
4285 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4286 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4291 /* Check address. */
4292 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4293 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4298 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4300 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4305 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4310 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4312 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4319 /* Normal process. */
4321 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4322 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4323 NULL
, NULL
, 0, 0, NULL
);
4325 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4326 safi
, ZEBRA_ROUTE_BGP
,
4327 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4330 /* Address family configuration mismatch or maximum-prefix count
4336 /* Packet length consistency check. */
4340 "%s [Error] Update packet error (prefix length mismatch with total length)",
4348 static struct bgp_static
*bgp_static_new(void)
4350 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4353 static void bgp_static_free(struct bgp_static
*bgp_static
)
4355 if (bgp_static
->rmap
.name
)
4356 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4357 if (bgp_static
->eth_s_id
)
4358 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4359 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4362 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4363 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4365 struct bgp_node
*rn
;
4366 struct bgp_path_info
*pi
;
4367 struct bgp_path_info
*new;
4368 struct bgp_path_info rmap_path
;
4370 struct attr
*attr_new
;
4373 int vnc_implicit_withdraw
= 0;
4380 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4382 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4384 attr
.nexthop
= bgp_static
->igpnexthop
;
4385 attr
.med
= bgp_static
->igpmetric
;
4386 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4388 if (bgp_static
->atomic
)
4389 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4391 /* Store label index, if required. */
4392 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4393 attr
.label_index
= bgp_static
->label_index
;
4394 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4397 /* Apply route-map. */
4398 if (bgp_static
->rmap
.name
) {
4399 struct attr attr_tmp
= attr
;
4401 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4402 rmap_path
.peer
= bgp
->peer_self
;
4403 rmap_path
.attr
= &attr_tmp
;
4405 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4407 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4410 bgp
->peer_self
->rmap_type
= 0;
4412 if (ret
== RMAP_DENYMATCH
) {
4413 /* Free uninterned attribute. */
4414 bgp_attr_flush(&attr_tmp
);
4416 /* Unintern original. */
4417 aspath_unintern(&attr
.aspath
);
4418 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4422 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4423 bgp_attr_add_gshut_community(&attr_tmp
);
4425 attr_new
= bgp_attr_intern(&attr_tmp
);
4428 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4429 bgp_attr_add_gshut_community(&attr
);
4431 attr_new
= bgp_attr_intern(&attr
);
4434 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
4435 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4436 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4440 if (attrhash_cmp(pi
->attr
, attr_new
)
4441 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4442 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4443 bgp_unlock_node(rn
);
4444 bgp_attr_unintern(&attr_new
);
4445 aspath_unintern(&attr
.aspath
);
4448 /* The attribute is changed. */
4449 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4451 /* Rewrite BGP route information. */
4452 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4453 bgp_path_info_restore(rn
, pi
);
4455 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4457 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4458 && (safi
== SAFI_UNICAST
)) {
4459 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4461 * Implicit withdraw case.
4462 * We have to do this before pi is
4465 ++vnc_implicit_withdraw
;
4466 vnc_import_bgp_del_route(bgp
, p
, pi
);
4467 vnc_import_bgp_exterior_del_route(
4472 bgp_attr_unintern(&pi
->attr
);
4473 pi
->attr
= attr_new
;
4474 pi
->uptime
= bgp_clock();
4476 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4477 && (safi
== SAFI_UNICAST
)) {
4478 if (vnc_implicit_withdraw
) {
4479 vnc_import_bgp_add_route(bgp
, p
, pi
);
4480 vnc_import_bgp_exterior_add_route(
4486 /* Nexthop reachability check. */
4487 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4488 && (safi
== SAFI_UNICAST
4489 || safi
== SAFI_LABELED_UNICAST
)) {
4491 struct bgp
*bgp_nexthop
= bgp
;
4493 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4494 bgp_nexthop
= pi
->extra
->bgp_orig
;
4496 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4498 bgp_path_info_set_flag(rn
, pi
,
4501 if (BGP_DEBUG(nht
, NHT
)) {
4502 char buf1
[INET6_ADDRSTRLEN
];
4503 inet_ntop(p
->family
,
4507 "%s(%s): Route not in table, not advertising",
4508 __FUNCTION__
, buf1
);
4510 bgp_path_info_unset_flag(
4511 rn
, pi
, BGP_PATH_VALID
);
4514 /* Delete the NHT structure if any, if we're
4516 * enabling/disabling import check. We
4517 * deregister the route
4518 * from NHT to avoid overloading NHT and the
4519 * process interaction
4521 bgp_unlink_nexthop(pi
);
4522 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4524 /* Process change. */
4525 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4526 bgp_process(bgp
, rn
, afi
, safi
);
4528 if (SAFI_UNICAST
== safi
4529 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4531 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4532 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4536 bgp_unlock_node(rn
);
4537 aspath_unintern(&attr
.aspath
);
4542 /* Make new BGP info. */
4543 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4545 /* Nexthop reachability check. */
4546 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4547 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4548 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4549 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4551 if (BGP_DEBUG(nht
, NHT
)) {
4552 char buf1
[INET6_ADDRSTRLEN
];
4553 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4556 "%s(%s): Route not in table, not advertising",
4557 __FUNCTION__
, buf1
);
4559 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4562 /* Delete the NHT structure if any, if we're toggling between
4563 * enabling/disabling import check. We deregister the route
4564 * from NHT to avoid overloading NHT and the process interaction
4566 bgp_unlink_nexthop(new);
4568 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4571 /* Aggregate address increment. */
4572 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4574 /* Register new BGP information. */
4575 bgp_path_info_add(rn
, new);
4577 /* route_node_get lock */
4578 bgp_unlock_node(rn
);
4580 /* Process change. */
4581 bgp_process(bgp
, rn
, afi
, safi
);
4583 if (SAFI_UNICAST
== safi
4584 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4585 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4586 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4589 /* Unintern original. */
4590 aspath_unintern(&attr
.aspath
);
4593 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4596 struct bgp_node
*rn
;
4597 struct bgp_path_info
*pi
;
4599 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4601 /* Check selected route and self inserted route. */
4602 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
4603 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4604 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4607 /* Withdraw static BGP route from routing table. */
4609 if (SAFI_UNICAST
== safi
4610 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4611 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4612 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4614 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4615 bgp_unlink_nexthop(pi
);
4616 bgp_path_info_delete(rn
, pi
);
4617 bgp_process(bgp
, rn
, afi
, safi
);
4620 /* Unlock bgp_node_lookup. */
4621 bgp_unlock_node(rn
);
4625 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4627 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4628 afi_t afi
, safi_t safi
,
4629 struct prefix_rd
*prd
)
4631 struct bgp_node
*rn
;
4632 struct bgp_path_info
*pi
;
4634 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4636 /* Check selected route and self inserted route. */
4637 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
4638 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4639 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4642 /* Withdraw static BGP route from routing table. */
4645 rfapiProcessWithdraw(
4646 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4647 1); /* Kill, since it is an administrative change */
4649 if (SAFI_MPLS_VPN
== safi
4650 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4651 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4653 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4654 bgp_path_info_delete(rn
, pi
);
4655 bgp_process(bgp
, rn
, afi
, safi
);
4658 /* Unlock bgp_node_lookup. */
4659 bgp_unlock_node(rn
);
4662 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4663 struct bgp_static
*bgp_static
, afi_t afi
,
4666 struct bgp_node
*rn
;
4667 struct bgp_path_info
*new;
4668 struct attr
*attr_new
;
4669 struct attr attr
= {0};
4670 struct bgp_path_info
*pi
;
4672 mpls_label_t label
= 0;
4674 uint32_t num_labels
= 0;
4679 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4681 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4684 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4686 attr
.nexthop
= bgp_static
->igpnexthop
;
4687 attr
.med
= bgp_static
->igpmetric
;
4688 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4690 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4691 || (safi
== SAFI_ENCAP
)) {
4692 if (afi
== AFI_IP
) {
4693 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4694 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4697 if (afi
== AFI_L2VPN
) {
4698 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4700 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4701 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4702 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4703 sizeof(struct in6_addr
));
4704 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4705 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4706 struct bgp_encap_type_vxlan bet
;
4707 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4708 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4709 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4711 if (bgp_static
->router_mac
) {
4712 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4715 /* Apply route-map. */
4716 if (bgp_static
->rmap
.name
) {
4717 struct attr attr_tmp
= attr
;
4718 struct bgp_path_info rmap_path
;
4721 rmap_path
.peer
= bgp
->peer_self
;
4722 rmap_path
.attr
= &attr_tmp
;
4724 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4726 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4729 bgp
->peer_self
->rmap_type
= 0;
4731 if (ret
== RMAP_DENYMATCH
) {
4732 /* Free uninterned attribute. */
4733 bgp_attr_flush(&attr_tmp
);
4735 /* Unintern original. */
4736 aspath_unintern(&attr
.aspath
);
4737 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4742 attr_new
= bgp_attr_intern(&attr_tmp
);
4744 attr_new
= bgp_attr_intern(&attr
);
4747 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
4748 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4749 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4753 memset(&add
, 0, sizeof(union gw_addr
));
4754 if (attrhash_cmp(pi
->attr
, attr_new
)
4755 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4756 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4757 bgp_unlock_node(rn
);
4758 bgp_attr_unintern(&attr_new
);
4759 aspath_unintern(&attr
.aspath
);
4762 /* The attribute is changed. */
4763 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4765 /* Rewrite BGP route information. */
4766 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4767 bgp_path_info_restore(rn
, pi
);
4769 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4770 bgp_attr_unintern(&pi
->attr
);
4771 pi
->attr
= attr_new
;
4772 pi
->uptime
= bgp_clock();
4775 label
= decode_label(&pi
->extra
->label
[0]);
4778 /* Process change. */
4779 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4780 bgp_process(bgp
, rn
, afi
, safi
);
4782 if (SAFI_MPLS_VPN
== safi
4783 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4784 vpn_leak_to_vrf_update(bgp
, pi
);
4787 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4788 pi
->attr
, afi
, safi
, pi
->type
,
4789 pi
->sub_type
, &label
);
4791 bgp_unlock_node(rn
);
4792 aspath_unintern(&attr
.aspath
);
4798 /* Make new BGP info. */
4799 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4801 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4802 new->extra
= bgp_path_info_extra_new();
4804 new->extra
->label
[0] = bgp_static
->label
;
4805 new->extra
->num_labels
= num_labels
;
4808 label
= decode_label(&bgp_static
->label
);
4811 /* Aggregate address increment. */
4812 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4814 /* Register new BGP information. */
4815 bgp_path_info_add(rn
, new);
4816 /* route_node_get lock */
4817 bgp_unlock_node(rn
);
4819 /* Process change. */
4820 bgp_process(bgp
, rn
, afi
, safi
);
4822 if (SAFI_MPLS_VPN
== safi
4823 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4824 vpn_leak_to_vrf_update(bgp
, new);
4827 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4828 safi
, new->type
, new->sub_type
, &label
);
4831 /* Unintern original. */
4832 aspath_unintern(&attr
.aspath
);
4835 /* Configure static BGP network. When user don't run zebra, static
4836 route should be installed as valid. */
4837 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4838 const char *ip_str
, afi_t afi
, safi_t safi
,
4839 const char *rmap
, int backdoor
, uint32_t label_index
)
4841 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4844 struct bgp_static
*bgp_static
;
4845 struct bgp_node
*rn
;
4846 uint8_t need_update
= 0;
4848 /* Convert IP prefix string to struct prefix. */
4849 ret
= str2prefix(ip_str
, &p
);
4851 vty_out(vty
, "%% Malformed prefix\n");
4852 return CMD_WARNING_CONFIG_FAILED
;
4854 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4855 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4856 return CMD_WARNING_CONFIG_FAILED
;
4863 /* Set BGP static route configuration. */
4864 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4867 vty_out(vty
, "%% Can't find static route specified\n");
4868 return CMD_WARNING_CONFIG_FAILED
;
4871 bgp_static
= bgp_static_get_node_info(rn
);
4873 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4874 && (label_index
!= bgp_static
->label_index
)) {
4876 "%% label-index doesn't match static route\n");
4877 return CMD_WARNING_CONFIG_FAILED
;
4880 if ((rmap
&& bgp_static
->rmap
.name
)
4881 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4883 "%% route-map name doesn't match static route\n");
4884 return CMD_WARNING_CONFIG_FAILED
;
4887 /* Update BGP RIB. */
4888 if (!bgp_static
->backdoor
)
4889 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4891 /* Clear configuration. */
4892 bgp_static_free(bgp_static
);
4893 bgp_static_set_node_info(rn
, NULL
);
4894 bgp_unlock_node(rn
);
4895 bgp_unlock_node(rn
);
4898 /* Set BGP static route configuration. */
4899 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4901 bgp_static
= bgp_static_get_node_info(rn
);
4903 /* Configuration change. */
4904 /* Label index cannot be changed. */
4905 if (bgp_static
->label_index
!= label_index
) {
4906 vty_out(vty
, "%% cannot change label-index\n");
4907 return CMD_WARNING_CONFIG_FAILED
;
4910 /* Check previous routes are installed into BGP. */
4911 if (bgp_static
->valid
4912 && bgp_static
->backdoor
!= backdoor
)
4915 bgp_static
->backdoor
= backdoor
;
4918 if (bgp_static
->rmap
.name
)
4919 XFREE(MTYPE_ROUTE_MAP_NAME
,
4920 bgp_static
->rmap
.name
);
4921 bgp_static
->rmap
.name
=
4922 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4923 bgp_static
->rmap
.map
=
4924 route_map_lookup_by_name(rmap
);
4926 if (bgp_static
->rmap
.name
)
4927 XFREE(MTYPE_ROUTE_MAP_NAME
,
4928 bgp_static
->rmap
.name
);
4929 bgp_static
->rmap
.name
= NULL
;
4930 bgp_static
->rmap
.map
= NULL
;
4931 bgp_static
->valid
= 0;
4933 bgp_unlock_node(rn
);
4935 /* New configuration. */
4936 bgp_static
= bgp_static_new();
4937 bgp_static
->backdoor
= backdoor
;
4938 bgp_static
->valid
= 0;
4939 bgp_static
->igpmetric
= 0;
4940 bgp_static
->igpnexthop
.s_addr
= 0;
4941 bgp_static
->label_index
= label_index
;
4944 if (bgp_static
->rmap
.name
)
4945 XFREE(MTYPE_ROUTE_MAP_NAME
,
4946 bgp_static
->rmap
.name
);
4947 bgp_static
->rmap
.name
=
4948 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4949 bgp_static
->rmap
.map
=
4950 route_map_lookup_by_name(rmap
);
4952 bgp_static_set_node_info(rn
, bgp_static
);
4955 bgp_static
->valid
= 1;
4957 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4959 if (!bgp_static
->backdoor
)
4960 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4966 void bgp_static_add(struct bgp
*bgp
)
4970 struct bgp_node
*rn
;
4971 struct bgp_node
*rm
;
4972 struct bgp_table
*table
;
4973 struct bgp_static
*bgp_static
;
4975 FOREACH_AFI_SAFI (afi
, safi
)
4976 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4977 rn
= bgp_route_next(rn
)) {
4978 if (rn
->info
== NULL
)
4981 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4982 || (safi
== SAFI_EVPN
)) {
4985 for (rm
= bgp_table_top(table
); rm
;
4986 rm
= bgp_route_next(rm
)) {
4988 bgp_static_get_node_info(rm
);
4989 bgp_static_update_safi(bgp
, &rm
->p
,
4994 bgp_static_update(bgp
, &rn
->p
,
4995 bgp_static_get_node_info(rn
),
5001 /* Called from bgp_delete(). Delete all static routes from the BGP
5003 void bgp_static_delete(struct bgp
*bgp
)
5007 struct bgp_node
*rn
;
5008 struct bgp_node
*rm
;
5009 struct bgp_table
*table
;
5010 struct bgp_static
*bgp_static
;
5012 FOREACH_AFI_SAFI (afi
, safi
)
5013 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5014 rn
= bgp_route_next(rn
)) {
5015 if (rn
->info
== NULL
)
5018 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5019 || (safi
== SAFI_EVPN
)) {
5022 for (rm
= bgp_table_top(table
); rm
;
5023 rm
= bgp_route_next(rm
)) {
5025 bgp_static_get_node_info(rm
);
5026 bgp_static_withdraw_safi(
5027 bgp
, &rm
->p
, AFI_IP
, safi
,
5028 (struct prefix_rd
*)&rn
->p
);
5029 bgp_static_free(bgp_static
);
5030 bgp_static_set_node_info(rn
, NULL
);
5031 bgp_unlock_node(rn
);
5034 bgp_static
= bgp_static_get_node_info(rn
);
5035 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5036 bgp_static_free(bgp_static
);
5037 bgp_static_set_node_info(rn
, NULL
);
5038 bgp_unlock_node(rn
);
5043 void bgp_static_redo_import_check(struct bgp
*bgp
)
5047 struct bgp_node
*rn
;
5048 struct bgp_node
*rm
;
5049 struct bgp_table
*table
;
5050 struct bgp_static
*bgp_static
;
5052 /* Use this flag to force reprocessing of the route */
5053 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5054 FOREACH_AFI_SAFI (afi
, safi
) {
5055 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5056 rn
= bgp_route_next(rn
)) {
5057 if (rn
->info
== NULL
)
5060 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5061 || (safi
== SAFI_EVPN
)) {
5064 for (rm
= bgp_table_top(table
); rm
;
5065 rm
= bgp_route_next(rm
)) {
5067 bgp_static_get_node_info(rm
);
5068 bgp_static_update_safi(bgp
, &rm
->p
,
5073 bgp_static
= bgp_static_get_node_info(rn
);
5074 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5079 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5082 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5085 struct bgp_table
*table
;
5086 struct bgp_node
*rn
;
5087 struct bgp_path_info
*pi
;
5089 table
= bgp
->rib
[afi
][safi
];
5090 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5091 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
5092 if (pi
->peer
== bgp
->peer_self
5093 && ((pi
->type
== ZEBRA_ROUTE_BGP
5094 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5095 || (pi
->type
!= ZEBRA_ROUTE_BGP
5097 == BGP_ROUTE_REDISTRIBUTE
))) {
5098 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5100 bgp_unlink_nexthop(pi
);
5101 bgp_path_info_delete(rn
, pi
);
5102 bgp_process(bgp
, rn
, afi
, safi
);
5109 * Purge all networks and redistributed routes from routing table.
5110 * Invoked upon the instance going down.
5112 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5117 FOREACH_AFI_SAFI (afi
, safi
)
5118 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5123 * Currently this is used to set static routes for VPN and ENCAP.
5124 * I think it can probably be factored with bgp_static_set.
5126 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5127 const char *ip_str
, const char *rd_str
,
5128 const char *label_str
, const char *rmap_str
,
5129 int evpn_type
, const char *esi
, const char *gwip
,
5130 const char *ethtag
, const char *routermac
)
5132 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5135 struct prefix_rd prd
;
5136 struct bgp_node
*prn
;
5137 struct bgp_node
*rn
;
5138 struct bgp_table
*table
;
5139 struct bgp_static
*bgp_static
;
5140 mpls_label_t label
= MPLS_INVALID_LABEL
;
5141 struct prefix gw_ip
;
5143 /* validate ip prefix */
5144 ret
= str2prefix(ip_str
, &p
);
5146 vty_out(vty
, "%% Malformed prefix\n");
5147 return CMD_WARNING_CONFIG_FAILED
;
5150 if ((afi
== AFI_L2VPN
)
5151 && (bgp_build_evpn_prefix(evpn_type
,
5152 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5153 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5154 return CMD_WARNING_CONFIG_FAILED
;
5157 ret
= str2prefix_rd(rd_str
, &prd
);
5159 vty_out(vty
, "%% Malformed rd\n");
5160 return CMD_WARNING_CONFIG_FAILED
;
5164 unsigned long label_val
;
5165 label_val
= strtoul(label_str
, NULL
, 10);
5166 encode_label(label_val
, &label
);
5169 if (safi
== SAFI_EVPN
) {
5170 if (esi
&& str2esi(esi
, NULL
) == 0) {
5171 vty_out(vty
, "%% Malformed ESI\n");
5172 return CMD_WARNING_CONFIG_FAILED
;
5174 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5175 vty_out(vty
, "%% Malformed Router MAC\n");
5176 return CMD_WARNING_CONFIG_FAILED
;
5179 memset(&gw_ip
, 0, sizeof(struct prefix
));
5180 ret
= str2prefix(gwip
, &gw_ip
);
5182 vty_out(vty
, "%% Malformed GatewayIp\n");
5183 return CMD_WARNING_CONFIG_FAILED
;
5185 if ((gw_ip
.family
== AF_INET
5186 && is_evpn_prefix_ipaddr_v6(
5187 (struct prefix_evpn
*)&p
))
5188 || (gw_ip
.family
== AF_INET6
5189 && is_evpn_prefix_ipaddr_v4(
5190 (struct prefix_evpn
*)&p
))) {
5192 "%% GatewayIp family differs with IP prefix\n");
5193 return CMD_WARNING_CONFIG_FAILED
;
5197 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5198 if (prn
->info
== NULL
)
5199 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5201 bgp_unlock_node(prn
);
5204 rn
= bgp_node_get(table
, &p
);
5207 vty_out(vty
, "%% Same network configuration exists\n");
5208 bgp_unlock_node(rn
);
5210 /* New configuration. */
5211 bgp_static
= bgp_static_new();
5212 bgp_static
->backdoor
= 0;
5213 bgp_static
->valid
= 0;
5214 bgp_static
->igpmetric
= 0;
5215 bgp_static
->igpnexthop
.s_addr
= 0;
5216 bgp_static
->label
= label
;
5217 bgp_static
->prd
= prd
;
5220 if (bgp_static
->rmap
.name
)
5221 XFREE(MTYPE_ROUTE_MAP_NAME
,
5222 bgp_static
->rmap
.name
);
5223 bgp_static
->rmap
.name
=
5224 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5225 bgp_static
->rmap
.map
=
5226 route_map_lookup_by_name(rmap_str
);
5229 if (safi
== SAFI_EVPN
) {
5231 bgp_static
->eth_s_id
=
5233 sizeof(struct eth_segment_id
));
5234 str2esi(esi
, bgp_static
->eth_s_id
);
5237 bgp_static
->router_mac
=
5238 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5239 (void)prefix_str2mac(routermac
,
5240 bgp_static
->router_mac
);
5243 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5245 bgp_static_set_node_info(rn
, bgp_static
);
5247 bgp_static
->valid
= 1;
5248 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5254 /* Configure static BGP network. */
5255 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5256 const char *ip_str
, const char *rd_str
,
5257 const char *label_str
, int evpn_type
, const char *esi
,
5258 const char *gwip
, const char *ethtag
)
5260 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5263 struct prefix_rd prd
;
5264 struct bgp_node
*prn
;
5265 struct bgp_node
*rn
;
5266 struct bgp_table
*table
;
5267 struct bgp_static
*bgp_static
;
5268 mpls_label_t label
= MPLS_INVALID_LABEL
;
5270 /* Convert IP prefix string to struct prefix. */
5271 ret
= str2prefix(ip_str
, &p
);
5273 vty_out(vty
, "%% Malformed prefix\n");
5274 return CMD_WARNING_CONFIG_FAILED
;
5277 if ((afi
== AFI_L2VPN
)
5278 && (bgp_build_evpn_prefix(evpn_type
,
5279 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5280 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5281 return CMD_WARNING_CONFIG_FAILED
;
5283 ret
= str2prefix_rd(rd_str
, &prd
);
5285 vty_out(vty
, "%% Malformed rd\n");
5286 return CMD_WARNING_CONFIG_FAILED
;
5290 unsigned long label_val
;
5291 label_val
= strtoul(label_str
, NULL
, 10);
5292 encode_label(label_val
, &label
);
5295 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5296 if (prn
->info
== NULL
)
5297 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5299 bgp_unlock_node(prn
);
5302 rn
= bgp_node_lookup(table
, &p
);
5305 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5307 bgp_static
= bgp_static_get_node_info(rn
);
5308 bgp_static_free(bgp_static
);
5309 bgp_static_set_node_info(rn
, NULL
);
5310 bgp_unlock_node(rn
);
5311 bgp_unlock_node(rn
);
5313 vty_out(vty
, "%% Can't find the route\n");
5318 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5319 const char *rmap_name
)
5321 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5322 struct bgp_rmap
*rmap
;
5324 rmap
= &bgp
->table_map
[afi
][safi
];
5327 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5328 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5329 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5332 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5337 if (bgp_fibupd_safi(safi
))
5338 bgp_zebra_announce_table(bgp
, afi
, safi
);
5343 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5344 const char *rmap_name
)
5346 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5347 struct bgp_rmap
*rmap
;
5349 rmap
= &bgp
->table_map
[afi
][safi
];
5351 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5355 if (bgp_fibupd_safi(safi
))
5356 bgp_zebra_announce_table(bgp
, afi
, safi
);
5361 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5364 if (bgp
->table_map
[afi
][safi
].name
) {
5365 vty_out(vty
, " table-map %s\n",
5366 bgp
->table_map
[afi
][safi
].name
);
5370 DEFUN (bgp_table_map
,
5373 "BGP table to RIB route download filter\n"
5374 "Name of the route map\n")
5377 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5378 argv
[idx_word
]->arg
);
5380 DEFUN (no_bgp_table_map
,
5381 no_bgp_table_map_cmd
,
5382 "no table-map WORD",
5384 "BGP table to RIB route download filter\n"
5385 "Name of the route map\n")
5388 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5389 argv
[idx_word
]->arg
);
5395 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5396 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5397 backdoor$backdoor}]",
5399 "Specify a network to announce via BGP\n"
5404 "Route-map to modify the attributes\n"
5405 "Name of the route map\n"
5406 "Label index to associate with the prefix\n"
5407 "Label index value\n"
5408 "Specify a BGP backdoor route\n")
5410 char addr_prefix_str
[BUFSIZ
];
5415 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5418 vty_out(vty
, "%% Inconsistent address and mask\n");
5419 return CMD_WARNING_CONFIG_FAILED
;
5423 return bgp_static_set(
5424 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5425 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5426 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5429 DEFPY(ipv6_bgp_network
,
5430 ipv6_bgp_network_cmd
,
5431 "[no] network X:X::X:X/M$prefix \
5432 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5434 "Specify a network to announce via BGP\n"
5436 "Route-map to modify the attributes\n"
5437 "Name of the route map\n"
5438 "Label index to associate with the prefix\n"
5439 "Label index value\n")
5441 return bgp_static_set(
5442 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5443 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5446 /* Aggreagete address:
5448 advertise-map Set condition to advertise attribute
5449 as-set Generate AS set path information
5450 attribute-map Set attributes of aggregate
5451 route-map Set parameters of aggregate
5452 summary-only Filter more specific routes from updates
5453 suppress-map Conditionally filter more specific routes from updates
5456 struct bgp_aggregate
{
5457 /* Summary-only flag. */
5458 uint8_t summary_only
;
5460 /* AS set generation. */
5463 /* Route-map for aggregated route. */
5464 struct route_map
*map
;
5466 /* Suppress-count. */
5467 unsigned long count
;
5469 /* SAFI configuration. */
5473 static struct bgp_aggregate
*bgp_aggregate_new(void)
5475 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5478 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5480 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5483 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5484 struct aspath
*aspath
,
5485 struct community
*comm
,
5486 struct ecommunity
*ecomm
,
5487 struct lcommunity
*lcomm
)
5489 static struct aspath
*ae
= NULL
;
5492 ae
= aspath_empty();
5497 if (origin
!= pi
->attr
->origin
)
5500 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5503 if (!community_cmp(pi
->attr
->community
, comm
))
5506 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5509 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5512 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5518 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5519 struct prefix
*p
, uint8_t origin
,
5520 struct aspath
*aspath
,
5521 struct community
*community
,
5522 struct ecommunity
*ecommunity
,
5523 struct lcommunity
*lcommunity
,
5524 uint8_t atomic_aggregate
,
5525 struct bgp_aggregate
*aggregate
)
5527 struct bgp_node
*rn
;
5528 struct bgp_table
*table
;
5529 struct bgp_path_info
*pi
, *new;
5531 table
= bgp
->rib
[afi
][safi
];
5533 rn
= bgp_node_get(table
, p
);
5535 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
5536 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5537 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5540 if (aggregate
->count
> 0) {
5542 * If the aggregate information has not changed
5543 * no need to re-install it again.
5545 if (bgp_aggregate_info_same(rn
->info
, origin
, aspath
, community
,
5546 ecommunity
, lcommunity
)) {
5547 bgp_unlock_node(rn
);
5550 aspath_free(aspath
);
5552 community_free(&community
);
5554 ecommunity_free(&ecommunity
);
5556 lcommunity_free(&lcommunity
);
5562 * Mark the old as unusable
5565 bgp_path_info_delete(rn
, pi
);
5567 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5569 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5570 community
, ecommunity
,
5575 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5577 bgp_path_info_add(rn
, new);
5578 bgp_process(bgp
, rn
, afi
, safi
);
5580 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
5581 if (pi
->peer
== bgp
->peer_self
5582 && pi
->type
== ZEBRA_ROUTE_BGP
5583 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5586 /* Withdraw static BGP route from routing table. */
5588 bgp_path_info_delete(rn
, pi
);
5589 bgp_process(bgp
, rn
, afi
, safi
);
5593 bgp_unlock_node(rn
);
5596 /* Update an aggregate as routes are added/removed from the BGP table */
5597 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5598 struct bgp_path_info
*pinew
, afi_t afi
,
5599 safi_t safi
, struct bgp_path_info
*del
,
5600 struct bgp_aggregate
*aggregate
)
5602 struct bgp_table
*table
;
5603 struct bgp_node
*top
;
5604 struct bgp_node
*rn
;
5606 struct aspath
*aspath
= NULL
;
5607 struct aspath
*asmerge
= NULL
;
5608 struct community
*community
= NULL
;
5609 struct community
*commerge
= NULL
;
5610 struct ecommunity
*ecommunity
= NULL
;
5611 struct ecommunity
*ecommerge
= NULL
;
5612 struct lcommunity
*lcommunity
= NULL
;
5613 struct lcommunity
*lcommerge
= NULL
;
5614 struct bgp_path_info
*pi
;
5615 unsigned long match
= 0;
5616 uint8_t atomic_aggregate
= 0;
5618 /* ORIGIN attribute: If at least one route among routes that are
5619 aggregated has ORIGIN with the value INCOMPLETE, then the
5620 aggregated route must have the ORIGIN attribute with the value
5621 INCOMPLETE. Otherwise, if at least one route among routes that
5622 are aggregated has ORIGIN with the value EGP, then the aggregated
5623 route must have the origin attribute with the value EGP. In all
5624 other case the value of the ORIGIN attribute of the aggregated
5625 route is INTERNAL. */
5626 origin
= BGP_ORIGIN_IGP
;
5628 table
= bgp
->rib
[afi
][safi
];
5630 top
= bgp_node_get(table
, p
);
5631 for (rn
= bgp_node_get(table
, p
); rn
;
5632 rn
= bgp_route_next_until(rn
, top
)) {
5633 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5638 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
5639 if (BGP_PATH_HOLDDOWN(pi
))
5642 if (del
&& pi
== del
)
5646 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5647 atomic_aggregate
= 1;
5649 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5653 * summary-only aggregate route suppress
5654 * aggregated route announcements.
5656 if (aggregate
->summary_only
) {
5657 (bgp_path_info_extra_get(pi
))->suppress
++;
5658 bgp_path_info_set_flag(rn
, pi
,
5659 BGP_PATH_ATTR_CHANGED
);
5666 * If at least one route among routes that are
5667 * aggregated has ORIGIN with the value INCOMPLETE,
5668 * then the aggregated route MUST have the ORIGIN
5669 * attribute with the value INCOMPLETE. Otherwise, if
5670 * at least one route among routes that are aggregated
5671 * has ORIGIN with the value EGP, then the aggregated
5672 * route MUST have the ORIGIN attribute with the value
5675 if (origin
< pi
->attr
->origin
)
5676 origin
= pi
->attr
->origin
;
5678 if (!aggregate
->as_set
)
5682 * as-set aggregate route generate origin, as path,
5683 * and community aggregation.
5686 asmerge
= aspath_aggregate(aspath
,
5688 aspath_free(aspath
);
5691 aspath
= aspath_dup(pi
->attr
->aspath
);
5693 if (pi
->attr
->community
) {
5695 commerge
= community_merge(
5696 community
, pi
->attr
->community
);
5698 community_uniq_sort(commerge
);
5699 community_free(&commerge
);
5701 community
= community_dup(
5702 pi
->attr
->community
);
5705 if (pi
->attr
->ecommunity
) {
5707 ecommerge
= ecommunity_merge(
5709 pi
->attr
->ecommunity
);
5711 ecommunity_uniq_sort(ecommerge
);
5712 ecommunity_free(&ecommerge
);
5714 ecommunity
= ecommunity_dup(
5715 pi
->attr
->ecommunity
);
5718 if (pi
->attr
->lcommunity
) {
5720 lcommerge
= lcommunity_merge(
5722 pi
->attr
->lcommunity
);
5724 lcommunity_uniq_sort(lcommerge
);
5725 lcommunity_free(&lcommerge
);
5727 lcommunity
= lcommunity_dup(
5728 pi
->attr
->lcommunity
);
5732 bgp_process(bgp
, rn
, afi
, safi
);
5734 bgp_unlock_node(top
);
5739 if (aggregate
->summary_only
)
5740 (bgp_path_info_extra_get(pinew
))->suppress
++;
5742 if (origin
< pinew
->attr
->origin
)
5743 origin
= pinew
->attr
->origin
;
5745 if (aggregate
->as_set
) {
5747 asmerge
= aspath_aggregate(aspath
,
5748 pinew
->attr
->aspath
);
5749 aspath_free(aspath
);
5752 aspath
= aspath_dup(pinew
->attr
->aspath
);
5754 if (pinew
->attr
->community
) {
5756 commerge
= community_merge(
5758 pinew
->attr
->community
);
5760 community_uniq_sort(commerge
);
5761 community_free(&commerge
);
5763 community
= community_dup(
5764 pinew
->attr
->community
);
5767 if (pinew
->attr
->ecommunity
) {
5769 ecommerge
= ecommunity_merge(
5771 pinew
->attr
->ecommunity
);
5773 ecommunity_uniq_sort(ecommerge
);
5774 ecommunity_free(&ecommerge
);
5776 ecommunity
= ecommunity_dup(
5777 pinew
->attr
->ecommunity
);
5780 if (pinew
->attr
->lcommunity
) {
5782 lcommerge
= lcommunity_merge(
5784 pinew
->attr
->lcommunity
);
5786 lcommunity_uniq_sort(lcommerge
);
5787 lcommunity_free(&lcommerge
);
5789 lcommunity
= lcommunity_dup(
5790 pinew
->attr
->lcommunity
);
5795 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5796 ecommunity
, lcommunity
, atomic_aggregate
,
5799 if (aggregate
->count
== 0) {
5801 aspath_free(aspath
);
5803 community_free(&community
);
5805 ecommunity_free(&ecommunity
);
5807 lcommunity_free(&lcommunity
);
5811 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5812 safi_t safi
, struct bgp_aggregate
*aggregate
)
5814 struct bgp_table
*table
;
5815 struct bgp_node
*top
;
5816 struct bgp_node
*rn
;
5817 struct bgp_path_info
*pi
;
5818 unsigned long match
;
5820 table
= bgp
->rib
[afi
][safi
];
5822 /* If routes exists below this node, generate aggregate routes. */
5823 top
= bgp_node_get(table
, p
);
5824 for (rn
= bgp_node_get(table
, p
); rn
;
5825 rn
= bgp_route_next_until(rn
, top
)) {
5826 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5830 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
5831 if (BGP_PATH_HOLDDOWN(pi
))
5834 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5837 if (aggregate
->summary_only
&& pi
->extra
) {
5838 pi
->extra
->suppress
--;
5840 if (pi
->extra
->suppress
== 0) {
5841 bgp_path_info_set_flag(
5842 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5849 /* If this node was suppressed, process the change. */
5851 bgp_process(bgp
, rn
, afi
, safi
);
5853 bgp_unlock_node(top
);
5856 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5857 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
5859 struct bgp_node
*child
;
5860 struct bgp_node
*rn
;
5861 struct bgp_aggregate
*aggregate
;
5862 struct bgp_table
*table
;
5864 table
= bgp
->aggregate
[afi
][safi
];
5866 /* No aggregates configured. */
5867 if (bgp_table_top_nolock(table
) == NULL
)
5870 if (p
->prefixlen
== 0)
5873 if (BGP_PATH_HOLDDOWN(pi
))
5876 child
= bgp_node_get(table
, p
);
5878 /* Aggregate address configuration check. */
5879 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5880 aggregate
= bgp_aggregate_get_node_info(rn
);
5881 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5882 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5883 bgp_aggregate_route(bgp
, &rn
->p
, pi
, afi
, safi
, NULL
,
5887 bgp_unlock_node(child
);
5890 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5891 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
5893 struct bgp_node
*child
;
5894 struct bgp_node
*rn
;
5895 struct bgp_aggregate
*aggregate
;
5896 struct bgp_table
*table
;
5898 table
= bgp
->aggregate
[afi
][safi
];
5900 /* No aggregates configured. */
5901 if (bgp_table_top_nolock(table
) == NULL
)
5904 if (p
->prefixlen
== 0)
5907 child
= bgp_node_get(table
, p
);
5909 /* Aggregate address configuration check. */
5910 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5911 aggregate
= bgp_aggregate_get_node_info(rn
);
5912 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5913 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5914 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5918 bgp_unlock_node(child
);
5921 /* Aggregate route attribute. */
5922 #define AGGREGATE_SUMMARY_ONLY 1
5923 #define AGGREGATE_AS_SET 1
5925 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5926 afi_t afi
, safi_t safi
)
5928 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5931 struct bgp_node
*rn
;
5932 struct bgp_aggregate
*aggregate
;
5934 /* Convert string to prefix structure. */
5935 ret
= str2prefix(prefix_str
, &p
);
5937 vty_out(vty
, "Malformed prefix\n");
5938 return CMD_WARNING_CONFIG_FAILED
;
5942 /* Old configuration check. */
5943 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5946 "%% There is no aggregate-address configuration.\n");
5947 return CMD_WARNING_CONFIG_FAILED
;
5950 aggregate
= bgp_aggregate_get_node_info(rn
);
5951 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5952 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
5953 NULL
, NULL
, 0, aggregate
);
5955 /* Unlock aggregate address configuration. */
5956 bgp_aggregate_set_node_info(rn
, NULL
);
5957 bgp_aggregate_free(aggregate
);
5958 bgp_unlock_node(rn
);
5959 bgp_unlock_node(rn
);
5964 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5965 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5967 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5970 struct bgp_node
*rn
;
5971 struct bgp_aggregate
*aggregate
;
5973 /* Convert string to prefix structure. */
5974 ret
= str2prefix(prefix_str
, &p
);
5976 vty_out(vty
, "Malformed prefix\n");
5977 return CMD_WARNING_CONFIG_FAILED
;
5981 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5982 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5983 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5985 return CMD_WARNING_CONFIG_FAILED
;
5988 /* Old configuration check. */
5989 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5992 vty_out(vty
, "There is already same aggregate network.\n");
5993 /* try to remove the old entry */
5994 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5996 vty_out(vty
, "Error deleting aggregate.\n");
5997 bgp_unlock_node(rn
);
5998 return CMD_WARNING_CONFIG_FAILED
;
6002 /* Make aggregate address structure. */
6003 aggregate
= bgp_aggregate_new();
6004 aggregate
->summary_only
= summary_only
;
6005 aggregate
->as_set
= as_set
;
6006 aggregate
->safi
= safi
;
6007 bgp_aggregate_set_node_info(rn
, aggregate
);
6009 /* Aggregate address insert into BGP routing table. */
6010 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
6015 DEFUN (aggregate_address
,
6016 aggregate_address_cmd
,
6017 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6018 "Configure BGP aggregate entries\n"
6019 "Aggregate prefix\n"
6020 "Generate AS set path information\n"
6021 "Filter more specific routes from updates\n"
6022 "Filter more specific routes from updates\n"
6023 "Generate AS set path information\n")
6026 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6027 char *prefix
= argv
[idx
]->arg
;
6029 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6031 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6032 ? AGGREGATE_SUMMARY_ONLY
6035 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6036 summary_only
, as_set
);
6039 DEFUN (aggregate_address_mask
,
6040 aggregate_address_mask_cmd
,
6041 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6042 "Configure BGP aggregate entries\n"
6043 "Aggregate address\n"
6045 "Generate AS set path information\n"
6046 "Filter more specific routes from updates\n"
6047 "Filter more specific routes from updates\n"
6048 "Generate AS set path information\n")
6051 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6052 char *prefix
= argv
[idx
]->arg
;
6053 char *mask
= argv
[idx
+ 1]->arg
;
6055 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6057 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6058 ? AGGREGATE_SUMMARY_ONLY
6061 char prefix_str
[BUFSIZ
];
6062 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6065 vty_out(vty
, "%% Inconsistent address and mask\n");
6066 return CMD_WARNING_CONFIG_FAILED
;
6069 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6070 summary_only
, as_set
);
6073 DEFUN (no_aggregate_address
,
6074 no_aggregate_address_cmd
,
6075 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6077 "Configure BGP aggregate entries\n"
6078 "Aggregate prefix\n"
6079 "Generate AS set path information\n"
6080 "Filter more specific routes from updates\n"
6081 "Filter more specific routes from updates\n"
6082 "Generate AS set path information\n")
6085 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6086 char *prefix
= argv
[idx
]->arg
;
6087 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6090 DEFUN (no_aggregate_address_mask
,
6091 no_aggregate_address_mask_cmd
,
6092 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6094 "Configure BGP aggregate entries\n"
6095 "Aggregate address\n"
6097 "Generate AS set path information\n"
6098 "Filter more specific routes from updates\n"
6099 "Filter more specific routes from updates\n"
6100 "Generate AS set path information\n")
6103 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6104 char *prefix
= argv
[idx
]->arg
;
6105 char *mask
= argv
[idx
+ 1]->arg
;
6107 char prefix_str
[BUFSIZ
];
6108 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6111 vty_out(vty
, "%% Inconsistent address and mask\n");
6112 return CMD_WARNING_CONFIG_FAILED
;
6115 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6118 DEFUN (ipv6_aggregate_address
,
6119 ipv6_aggregate_address_cmd
,
6120 "aggregate-address X:X::X:X/M [summary-only]",
6121 "Configure BGP aggregate entries\n"
6122 "Aggregate prefix\n"
6123 "Filter more specific routes from updates\n")
6126 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6127 char *prefix
= argv
[idx
]->arg
;
6128 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6129 ? AGGREGATE_SUMMARY_ONLY
6131 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6135 DEFUN (no_ipv6_aggregate_address
,
6136 no_ipv6_aggregate_address_cmd
,
6137 "no aggregate-address X:X::X:X/M [summary-only]",
6139 "Configure BGP aggregate entries\n"
6140 "Aggregate prefix\n"
6141 "Filter more specific routes from updates\n")
6144 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6145 char *prefix
= argv
[idx
]->arg
;
6146 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6149 /* Redistribute route treatment. */
6150 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6151 const union g_addr
*nexthop
, ifindex_t ifindex
,
6152 enum nexthop_types_t nhtype
, uint32_t metric
,
6153 uint8_t type
, unsigned short instance
,
6156 struct bgp_path_info
*new;
6157 struct bgp_path_info
*bpi
;
6158 struct bgp_path_info rmap_path
;
6159 struct bgp_node
*bn
;
6161 struct attr
*new_attr
;
6164 struct bgp_redist
*red
;
6166 /* Make default attribute. */
6167 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6170 case NEXTHOP_TYPE_IFINDEX
:
6172 case NEXTHOP_TYPE_IPV4
:
6173 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6174 attr
.nexthop
= nexthop
->ipv4
;
6176 case NEXTHOP_TYPE_IPV6
:
6177 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6178 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6179 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6181 case NEXTHOP_TYPE_BLACKHOLE
:
6182 switch (p
->family
) {
6184 attr
.nexthop
.s_addr
= INADDR_ANY
;
6187 memset(&attr
.mp_nexthop_global
, 0,
6188 sizeof(attr
.mp_nexthop_global
));
6189 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6194 attr
.nh_ifindex
= ifindex
;
6197 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6200 afi
= family2afi(p
->family
);
6202 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6204 struct attr attr_new
;
6206 /* Copy attribute for modification. */
6207 bgp_attr_dup(&attr_new
, &attr
);
6209 if (red
->redist_metric_flag
)
6210 attr_new
.med
= red
->redist_metric
;
6212 /* Apply route-map. */
6213 if (red
->rmap
.name
) {
6214 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6215 rmap_path
.peer
= bgp
->peer_self
;
6216 rmap_path
.attr
= &attr_new
;
6218 SET_FLAG(bgp
->peer_self
->rmap_type
,
6219 PEER_RMAP_TYPE_REDISTRIBUTE
);
6221 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6224 bgp
->peer_self
->rmap_type
= 0;
6226 if (ret
== RMAP_DENYMATCH
) {
6227 /* Free uninterned attribute. */
6228 bgp_attr_flush(&attr_new
);
6230 /* Unintern original. */
6231 aspath_unintern(&attr
.aspath
);
6232 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6237 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6238 bgp_attr_add_gshut_community(&attr_new
);
6240 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6241 SAFI_UNICAST
, p
, NULL
);
6243 new_attr
= bgp_attr_intern(&attr_new
);
6245 for (bpi
= bn
->info
; bpi
; bpi
= bpi
->next
)
6246 if (bpi
->peer
== bgp
->peer_self
6247 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6251 /* Ensure the (source route) type is updated. */
6253 if (attrhash_cmp(bpi
->attr
, new_attr
)
6254 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6255 bgp_attr_unintern(&new_attr
);
6256 aspath_unintern(&attr
.aspath
);
6257 bgp_unlock_node(bn
);
6260 /* The attribute is changed. */
6261 bgp_path_info_set_flag(bn
, bpi
,
6262 BGP_PATH_ATTR_CHANGED
);
6264 /* Rewrite BGP route information. */
6265 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6266 bgp_path_info_restore(bn
, bpi
);
6268 bgp_aggregate_decrement(
6269 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6270 bgp_attr_unintern(&bpi
->attr
);
6271 bpi
->attr
= new_attr
;
6272 bpi
->uptime
= bgp_clock();
6274 /* Process change. */
6275 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6277 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6278 bgp_unlock_node(bn
);
6279 aspath_unintern(&attr
.aspath
);
6281 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6283 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6285 vpn_leak_from_vrf_update(
6286 bgp_get_default(), bgp
, bpi
);
6292 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6293 bgp
->peer_self
, new_attr
, bn
);
6294 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6296 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6297 bgp_path_info_add(bn
, new);
6298 bgp_unlock_node(bn
);
6299 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6301 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6302 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6304 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6308 /* Unintern original. */
6309 aspath_unintern(&attr
.aspath
);
6312 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6313 unsigned short instance
)
6316 struct bgp_node
*rn
;
6317 struct bgp_path_info
*pi
;
6318 struct bgp_redist
*red
;
6320 afi
= family2afi(p
->family
);
6322 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6324 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6325 SAFI_UNICAST
, p
, NULL
);
6327 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
6328 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6332 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6333 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6335 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6338 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6339 bgp_path_info_delete(rn
, pi
);
6340 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6342 bgp_unlock_node(rn
);
6346 /* Withdraw specified route type's route. */
6347 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6348 unsigned short instance
)
6350 struct bgp_node
*rn
;
6351 struct bgp_path_info
*pi
;
6352 struct bgp_table
*table
;
6354 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6356 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6357 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
6358 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6359 && pi
->instance
== instance
)
6363 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6364 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6366 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6369 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6371 bgp_path_info_delete(rn
, pi
);
6372 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6377 /* Static function to display route. */
6378 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6385 if (p
->family
== AF_INET
) {
6389 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6392 json_object_string_add(json
, "prefix",
6393 inet_ntop(p
->family
,
6396 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6397 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6398 json_object_string_add(json
, "network", buf2
);
6400 } else if (p
->family
== AF_ETHERNET
) {
6401 prefix2str(p
, buf
, PREFIX_STRLEN
);
6402 len
= vty_out(vty
, "%s", buf
);
6403 } else if (p
->family
== AF_EVPN
) {
6407 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6410 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6411 } else if (p
->family
== AF_FLOWSPEC
) {
6412 route_vty_out_flowspec(vty
, p
, NULL
,
6414 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6415 NLRI_STRING_FORMAT_MIN
, json
);
6420 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6423 json_object_string_add(json
, "prefix",
6424 inet_ntop(p
->family
,
6427 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6428 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6429 json_object_string_add(json
, "network", buf2
);
6436 vty_out(vty
, "\n%*s", 20, " ");
6438 vty_out(vty
, "%*s", len
, " ");
6442 enum bgp_display_type
{
6446 /* Print the short form route status for a bgp_path_info */
6447 static void route_vty_short_status_out(struct vty
*vty
,
6448 struct bgp_path_info
*path
,
6449 json_object
*json_path
)
6453 /* Route status display. */
6454 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6455 json_object_boolean_true_add(json_path
, "removed");
6457 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6458 json_object_boolean_true_add(json_path
, "stale");
6460 if (path
->extra
&& path
->extra
->suppress
)
6461 json_object_boolean_true_add(json_path
, "suppressed");
6463 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6464 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6465 json_object_boolean_true_add(json_path
, "valid");
6468 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6469 json_object_boolean_true_add(json_path
, "history");
6471 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6472 json_object_boolean_true_add(json_path
, "damped");
6474 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6475 json_object_boolean_true_add(json_path
, "bestpath");
6477 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6478 json_object_boolean_true_add(json_path
, "multipath");
6480 /* Internal route. */
6481 if ((path
->peer
->as
)
6482 && (path
->peer
->as
== path
->peer
->local_as
))
6483 json_object_string_add(json_path
, "pathFrom",
6486 json_object_string_add(json_path
, "pathFrom",
6492 /* Route status display. */
6493 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6495 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6497 else if (path
->extra
&& path
->extra
->suppress
)
6499 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6500 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6506 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6508 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6510 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6512 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6517 /* Internal route. */
6518 if (path
->peer
&& (path
->peer
->as
)
6519 && (path
->peer
->as
== path
->peer
->local_as
))
6525 /* called from terminal list command */
6526 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6527 struct bgp_path_info
*path
, int display
, safi_t safi
,
6528 json_object
*json_paths
)
6531 json_object
*json_path
= NULL
;
6532 json_object
*json_nexthops
= NULL
;
6533 json_object
*json_nexthop_global
= NULL
;
6534 json_object
*json_nexthop_ll
= NULL
;
6535 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6537 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6538 bool nexthop_othervrf
= false;
6539 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6540 const char *nexthop_vrfname
= "Default";
6543 json_path
= json_object_new_object();
6545 /* short status lead text */
6546 route_vty_short_status_out(vty
, path
, json_path
);
6549 /* print prefix and mask */
6551 route_vty_out_route(p
, vty
, json_path
);
6553 vty_out(vty
, "%*s", 17, " ");
6555 route_vty_out_route(p
, vty
, json_path
);
6558 /* Print attribute */
6562 json_object_array_add(json_paths
, json_path
);
6570 * If vrf id of nexthop is different from that of prefix,
6571 * set up printable string to append
6573 if (path
->extra
&& path
->extra
->bgp_orig
) {
6574 const char *self
= "";
6579 nexthop_othervrf
= true;
6580 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6582 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6583 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6584 "@%s%s", VRFID_NONE_STR
, self
);
6586 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6587 path
->extra
->bgp_orig
->vrf_id
, self
);
6589 if (path
->extra
->bgp_orig
->inst_type
6590 != BGP_INSTANCE_TYPE_DEFAULT
)
6592 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6594 const char *self
= "";
6599 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6603 * For ENCAP and EVPN routes, nexthop address family is not
6604 * neccessarily the same as the prefix address family.
6605 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6606 * EVPN routes are also exchanged with a MP nexthop. Currently,
6608 * is only IPv4, the value will be present in either
6610 * attr->mp_nexthop_global_in
6612 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6615 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6619 sprintf(nexthop
, "%s",
6620 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6624 sprintf(nexthop
, "%s",
6625 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6629 sprintf(nexthop
, "?");
6634 json_nexthop_global
= json_object_new_object();
6636 json_object_string_add(json_nexthop_global
, "afi",
6637 (af
== AF_INET
) ? "ip" : "ipv6");
6638 json_object_string_add(json_nexthop_global
,
6639 (af
== AF_INET
) ? "ip" : "ipv6",
6641 json_object_boolean_true_add(json_nexthop_global
,
6644 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6645 } else if (safi
== SAFI_EVPN
) {
6647 json_nexthop_global
= json_object_new_object();
6649 json_object_string_add(json_nexthop_global
, "ip",
6650 inet_ntoa(attr
->nexthop
));
6651 json_object_string_add(json_nexthop_global
, "afi",
6653 json_object_boolean_true_add(json_nexthop_global
,
6656 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6658 } else if (safi
== SAFI_FLOWSPEC
) {
6659 if (attr
->nexthop
.s_addr
!= 0) {
6661 json_nexthop_global
= json_object_new_object();
6662 json_object_string_add(
6663 json_nexthop_global
, "ip",
6664 inet_ntoa(attr
->nexthop
));
6665 json_object_string_add(json_nexthop_global
,
6667 json_object_boolean_true_add(json_nexthop_global
,
6670 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6673 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6675 json_nexthop_global
= json_object_new_object();
6677 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6678 json_object_string_add(
6679 json_nexthop_global
, "ip",
6680 inet_ntoa(attr
->mp_nexthop_global_in
));
6682 json_object_string_add(
6683 json_nexthop_global
, "ip",
6684 inet_ntoa(attr
->nexthop
));
6686 json_object_string_add(json_nexthop_global
, "afi",
6688 json_object_boolean_true_add(json_nexthop_global
,
6693 snprintf(buf
, sizeof(buf
), "%s%s",
6694 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6695 vty_out(vty
, "%-16s", buf
);
6700 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6705 json_nexthop_global
= json_object_new_object();
6706 json_object_string_add(
6707 json_nexthop_global
, "ip",
6708 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6710 json_object_string_add(json_nexthop_global
, "afi",
6712 json_object_string_add(json_nexthop_global
, "scope",
6715 /* We display both LL & GL if both have been
6717 if ((attr
->mp_nexthop_len
== 32)
6718 || (path
->peer
->conf_if
)) {
6719 json_nexthop_ll
= json_object_new_object();
6720 json_object_string_add(
6721 json_nexthop_ll
, "ip",
6723 &attr
->mp_nexthop_local
, buf
,
6725 json_object_string_add(json_nexthop_ll
, "afi",
6727 json_object_string_add(json_nexthop_ll
, "scope",
6730 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6731 &attr
->mp_nexthop_local
)
6733 && !attr
->mp_nexthop_prefer_global
)
6734 json_object_boolean_true_add(
6735 json_nexthop_ll
, "used");
6737 json_object_boolean_true_add(
6738 json_nexthop_global
, "used");
6740 json_object_boolean_true_add(
6741 json_nexthop_global
, "used");
6743 /* Display LL if LL/Global both in table unless
6744 * prefer-global is set */
6745 if (((attr
->mp_nexthop_len
== 32)
6746 && !attr
->mp_nexthop_prefer_global
)
6747 || (path
->peer
->conf_if
)) {
6748 if (path
->peer
->conf_if
) {
6749 len
= vty_out(vty
, "%s",
6750 path
->peer
->conf_if
);
6751 len
= 16 - len
; /* len of IPv6
6757 vty_out(vty
, "\n%*s", 36, " ");
6759 vty_out(vty
, "%*s", len
, " ");
6765 &attr
->mp_nexthop_local
,
6771 vty_out(vty
, "\n%*s", 36, " ");
6773 vty_out(vty
, "%*s", len
, " ");
6779 &attr
->mp_nexthop_global
, buf
,
6785 vty_out(vty
, "\n%*s", 36, " ");
6787 vty_out(vty
, "%*s", len
, " ");
6793 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6795 json_object_int_add(json_path
, "med", attr
->med
);
6797 vty_out(vty
, "%10u", attr
->med
);
6798 else if (!json_paths
)
6802 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6804 json_object_int_add(json_path
, "localpref",
6807 vty_out(vty
, "%7u", attr
->local_pref
);
6808 else if (!json_paths
)
6812 json_object_int_add(json_path
, "weight", attr
->weight
);
6814 vty_out(vty
, "%7u ", attr
->weight
);
6818 json_object_string_add(
6819 json_path
, "peerId",
6820 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6826 json_object_string_add(json_path
, "aspath",
6829 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6834 json_object_string_add(json_path
, "origin",
6835 bgp_origin_long_str
[attr
->origin
]);
6837 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6841 json_object_boolean_true_add(json_path
,
6842 "announceNexthopSelf");
6843 if (nexthop_othervrf
) {
6844 json_object_string_add(json_path
, "nhVrfName",
6847 json_object_int_add(json_path
, "nhVrfId",
6848 ((nexthop_vrfid
== VRF_UNKNOWN
)
6850 : (int)nexthop_vrfid
));
6855 if (json_nexthop_global
|| json_nexthop_ll
) {
6856 json_nexthops
= json_object_new_array();
6858 if (json_nexthop_global
)
6859 json_object_array_add(json_nexthops
,
6860 json_nexthop_global
);
6862 if (json_nexthop_ll
)
6863 json_object_array_add(json_nexthops
,
6866 json_object_object_add(json_path
, "nexthops",
6870 json_object_array_add(json_paths
, json_path
);
6874 /* prints an additional line, indented, with VNC info, if
6876 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6877 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
6882 /* called from terminal list command */
6883 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6884 safi_t safi
, bool use_json
, json_object
*json_ar
)
6886 json_object
*json_status
= NULL
;
6887 json_object
*json_net
= NULL
;
6890 /* Route status display. */
6892 json_status
= json_object_new_object();
6893 json_net
= json_object_new_object();
6900 /* print prefix and mask */
6902 json_object_string_add(
6903 json_net
, "addrPrefix",
6904 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6905 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
6906 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6907 json_object_string_add(json_net
, "network", buf2
);
6909 route_vty_out_route(p
, vty
, NULL
);
6911 /* Print attribute */
6914 if (p
->family
== AF_INET
6915 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6916 || safi
== SAFI_EVPN
6917 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6918 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6919 || safi
== SAFI_EVPN
)
6920 json_object_string_add(
6921 json_net
, "nextHop",
6923 attr
->mp_nexthop_global_in
));
6925 json_object_string_add(
6926 json_net
, "nextHop",
6927 inet_ntoa(attr
->nexthop
));
6928 } else if (p
->family
== AF_INET6
6929 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6932 json_object_string_add(
6933 json_net
, "nextHopGlobal",
6935 &attr
->mp_nexthop_global
, buf
,
6940 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6941 json_object_int_add(json_net
, "metric",
6944 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6945 json_object_int_add(json_net
, "localPref",
6948 json_object_int_add(json_net
, "weight", attr
->weight
);
6952 json_object_string_add(json_net
, "asPath",
6956 json_object_string_add(json_net
, "bgpOriginCode",
6957 bgp_origin_str
[attr
->origin
]);
6959 if (p
->family
== AF_INET
6960 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6961 || safi
== SAFI_EVPN
6962 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6963 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6964 || safi
== SAFI_EVPN
)
6965 vty_out(vty
, "%-16s",
6967 attr
->mp_nexthop_global_in
));
6969 vty_out(vty
, "%-16s",
6970 inet_ntoa(attr
->nexthop
));
6971 } else if (p
->family
== AF_INET6
6972 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6979 &attr
->mp_nexthop_global
, buf
,
6983 vty_out(vty
, "\n%*s", 36, " ");
6985 vty_out(vty
, "%*s", len
, " ");
6988 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6989 vty_out(vty
, "%10u", attr
->med
);
6993 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6994 vty_out(vty
, "%7u", attr
->local_pref
);
6998 vty_out(vty
, "%7u ", attr
->weight
);
7002 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7005 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7009 json_object_boolean_true_add(json_status
, "*");
7010 json_object_boolean_true_add(json_status
, ">");
7011 json_object_object_add(json_net
, "appliedStatusSymbols",
7013 char buf_cut
[BUFSIZ
];
7014 json_object_object_add(
7016 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7022 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7023 struct bgp_path_info
*path
, int display
, safi_t safi
,
7026 json_object
*json_out
= NULL
;
7028 mpls_label_t label
= MPLS_INVALID_LABEL
;
7034 json_out
= json_object_new_object();
7036 /* short status lead text */
7037 route_vty_short_status_out(vty
, path
, json_out
);
7039 /* print prefix and mask */
7042 route_vty_out_route(p
, vty
, NULL
);
7044 vty_out(vty
, "%*s", 17, " ");
7047 /* Print attribute */
7050 if (((p
->family
== AF_INET
)
7051 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7052 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7053 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7054 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7055 || safi
== SAFI_EVPN
) {
7057 json_object_string_add(
7058 json_out
, "mpNexthopGlobalIn",
7060 attr
->mp_nexthop_global_in
));
7062 vty_out(vty
, "%-16s",
7064 attr
->mp_nexthop_global_in
));
7067 json_object_string_add(
7068 json_out
, "nexthop",
7069 inet_ntoa(attr
->nexthop
));
7071 vty_out(vty
, "%-16s",
7072 inet_ntoa(attr
->nexthop
));
7074 } else if (((p
->family
== AF_INET6
)
7075 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7076 || (safi
== SAFI_EVPN
7077 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7078 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7082 if (attr
->mp_nexthop_len
7083 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7085 json_object_string_add(
7086 json_out
, "mpNexthopGlobalIn",
7089 &attr
->mp_nexthop_global
,
7090 buf_a
, sizeof(buf_a
)));
7095 &attr
->mp_nexthop_global
,
7096 buf_a
, sizeof(buf_a
)));
7097 } else if (attr
->mp_nexthop_len
7098 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7101 &attr
->mp_nexthop_global
,
7102 buf_a
, sizeof(buf_a
));
7104 &attr
->mp_nexthop_local
,
7105 buf_b
, sizeof(buf_b
));
7106 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7107 json_object_string_add(
7109 "mpNexthopGlobalLocal", buf_c
);
7111 vty_out(vty
, "%s(%s)",
7114 &attr
->mp_nexthop_global
,
7115 buf_a
, sizeof(buf_a
)),
7118 &attr
->mp_nexthop_local
,
7119 buf_b
, sizeof(buf_b
)));
7124 label
= decode_label(&path
->extra
->label
[0]);
7126 if (bgp_is_valid_label(&label
)) {
7128 json_object_int_add(json_out
, "notag", label
);
7129 json_object_array_add(json
, json_out
);
7131 vty_out(vty
, "notag/%d", label
);
7137 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7138 struct bgp_path_info
*path
, int display
,
7139 json_object
*json_paths
)
7143 json_object
*json_path
= NULL
;
7146 json_path
= json_object_new_object();
7151 /* short status lead text */
7152 route_vty_short_status_out(vty
, path
, json_path
);
7154 /* print prefix and mask */
7156 route_vty_out_route(p
, vty
, NULL
);
7158 vty_out(vty
, "%*s", 17, " ");
7160 /* Print attribute */
7164 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7168 vty_out(vty
, "%-16s",
7169 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7173 vty_out(vty
, "%s(%s)",
7174 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7176 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7183 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7185 vty_out(vty
, "%s", str
);
7186 XFREE(MTYPE_TMP
, str
);
7188 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7190 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7191 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7194 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7197 if (attr
->ecommunity
) {
7199 struct ecommunity_val
*routermac
= ecommunity_lookup(
7200 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7201 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7203 mac
= ecom_mac2str((char *)routermac
->val
);
7205 vty_out(vty
, "/%s", (char *)mac
);
7206 XFREE(MTYPE_TMP
, mac
);
7214 /* dampening route */
7215 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7216 struct bgp_path_info
*path
, int display
,
7217 safi_t safi
, bool use_json
, json_object
*json
)
7221 char timebuf
[BGP_UPTIME_LEN
];
7223 /* short status lead text */
7224 route_vty_short_status_out(vty
, path
, json
);
7226 /* print prefix and mask */
7229 route_vty_out_route(p
, vty
, NULL
);
7231 vty_out(vty
, "%*s", 17, " ");
7234 len
= vty_out(vty
, "%s", path
->peer
->host
);
7238 vty_out(vty
, "\n%*s", 34, " ");
7241 json_object_int_add(json
, "peerHost", len
);
7243 vty_out(vty
, "%*s", len
, " ");
7247 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7251 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7252 BGP_UPTIME_LEN
, use_json
,
7255 /* Print attribute */
7261 json_object_string_add(json
, "asPath",
7264 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7269 json_object_string_add(json
, "origin",
7270 bgp_origin_str
[attr
->origin
]);
7272 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7279 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7280 struct bgp_path_info
*path
, int display
,
7281 safi_t safi
, bool use_json
, json_object
*json
)
7284 struct bgp_damp_info
*bdi
;
7285 char timebuf
[BGP_UPTIME_LEN
];
7291 bdi
= path
->extra
->damp_info
;
7293 /* short status lead text */
7294 route_vty_short_status_out(vty
, path
, json
);
7296 /* print prefix and mask */
7299 route_vty_out_route(p
, vty
, NULL
);
7301 vty_out(vty
, "%*s", 17, " ");
7304 len
= vty_out(vty
, "%s", path
->peer
->host
);
7308 vty_out(vty
, "\n%*s", 33, " ");
7311 json_object_int_add(json
, "peerHost", len
);
7313 vty_out(vty
, "%*s", len
, " ");
7316 len
= vty_out(vty
, "%d", bdi
->flap
);
7323 json_object_int_add(json
, "bdiFlap", len
);
7325 vty_out(vty
, "%*s", len
, " ");
7329 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7332 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7333 BGP_UPTIME_LEN
, 0, NULL
));
7335 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7336 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7338 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7339 BGP_UPTIME_LEN
, use_json
, json
);
7342 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7347 vty_out(vty
, "%*s ", 8, " ");
7350 /* Print attribute */
7356 json_object_string_add(json
, "asPath",
7359 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7364 json_object_string_add(json
, "origin",
7365 bgp_origin_str
[attr
->origin
]);
7367 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7373 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7374 int *first
, const char *header
,
7375 json_object
*json_adv_to
)
7377 char buf1
[INET6_ADDRSTRLEN
];
7378 json_object
*json_peer
= NULL
;
7381 /* 'advertised-to' is a dictionary of peers we have advertised
7383 * prefix too. The key is the peer's IP or swpX, the value is
7385 * hostname if we know it and "" if not.
7387 json_peer
= json_object_new_object();
7390 json_object_string_add(json_peer
, "hostname",
7394 json_object_object_add(json_adv_to
, peer
->conf_if
,
7397 json_object_object_add(
7399 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7403 vty_out(vty
, "%s", header
);
7408 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7410 vty_out(vty
, " %s(%s)", peer
->hostname
,
7413 vty_out(vty
, " %s(%s)", peer
->hostname
,
7414 sockunion2str(&peer
->su
, buf1
,
7418 vty_out(vty
, " %s", peer
->conf_if
);
7421 sockunion2str(&peer
->su
, buf1
,
7427 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7428 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7429 json_object
*json_paths
)
7431 char buf
[INET6_ADDRSTRLEN
];
7433 char buf2
[EVPN_ROUTE_STRLEN
];
7435 int sockunion_vty_out(struct vty
*, union sockunion
*);
7437 json_object
*json_bestpath
= NULL
;
7438 json_object
*json_cluster_list
= NULL
;
7439 json_object
*json_cluster_list_list
= NULL
;
7440 json_object
*json_ext_community
= NULL
;
7441 json_object
*json_last_update
= NULL
;
7442 json_object
*json_pmsi
= NULL
;
7443 json_object
*json_nexthop_global
= NULL
;
7444 json_object
*json_nexthop_ll
= NULL
;
7445 json_object
*json_nexthops
= NULL
;
7446 json_object
*json_path
= NULL
;
7447 json_object
*json_peer
= NULL
;
7448 json_object
*json_string
= NULL
;
7449 json_object
*json_adv_to
= NULL
;
7451 struct listnode
*node
, *nnode
;
7453 int addpath_capable
;
7455 unsigned int first_as
;
7457 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7460 json_path
= json_object_new_object();
7461 json_peer
= json_object_new_object();
7462 json_nexthop_global
= json_object_new_object();
7465 if (!json_paths
&& safi
== SAFI_EVPN
) {
7468 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7469 vty_out(vty
, " Route %s", buf2
);
7471 if (path
->extra
&& path
->extra
->num_labels
) {
7472 bgp_evpn_label2str(path
->extra
->label
,
7473 path
->extra
->num_labels
, tag_buf
,
7475 vty_out(vty
, " VNI %s", tag_buf
);
7478 if (path
->extra
&& path
->extra
->parent
) {
7479 struct bgp_path_info
*parent_ri
;
7480 struct bgp_node
*rn
, *prn
;
7482 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7483 rn
= parent_ri
->net
;
7484 if (rn
&& rn
->prn
) {
7486 vty_out(vty
, " Imported from %s:%s\n",
7488 (struct prefix_rd
*)&prn
->p
,
7489 buf1
, sizeof(buf1
)),
7498 /* Line1 display AS-path, Aggregator */
7501 if (!attr
->aspath
->json
)
7502 aspath_str_update(attr
->aspath
, true);
7503 json_object_lock(attr
->aspath
->json
);
7504 json_object_object_add(json_path
, "aspath",
7505 attr
->aspath
->json
);
7507 if (attr
->aspath
->segments
)
7508 aspath_print_vty(vty
, " %s",
7511 vty_out(vty
, " Local");
7515 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7517 json_object_boolean_true_add(json_path
,
7520 vty_out(vty
, ", (removed)");
7523 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7525 json_object_boolean_true_add(json_path
,
7528 vty_out(vty
, ", (stale)");
7531 if (CHECK_FLAG(attr
->flag
,
7532 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7534 json_object_int_add(json_path
, "aggregatorAs",
7535 attr
->aggregator_as
);
7536 json_object_string_add(
7537 json_path
, "aggregatorId",
7538 inet_ntoa(attr
->aggregator_addr
));
7540 vty_out(vty
, ", (aggregated by %u %s)",
7541 attr
->aggregator_as
,
7542 inet_ntoa(attr
->aggregator_addr
));
7546 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7547 PEER_FLAG_REFLECTOR_CLIENT
)) {
7549 json_object_boolean_true_add(
7550 json_path
, "rxedFromRrClient");
7552 vty_out(vty
, ", (Received from a RR-client)");
7555 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7556 PEER_FLAG_RSERVER_CLIENT
)) {
7558 json_object_boolean_true_add(
7559 json_path
, "rxedFromRsClient");
7561 vty_out(vty
, ", (Received from a RS-client)");
7564 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7566 json_object_boolean_true_add(
7567 json_path
, "dampeningHistoryEntry");
7569 vty_out(vty
, ", (history entry)");
7570 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
7572 json_object_boolean_true_add(
7573 json_path
, "dampeningSuppressed");
7575 vty_out(vty
, ", (suppressed due to dampening)");
7581 /* Line2 display Next-hop, Neighbor, Router-id */
7582 /* Display the nexthop */
7583 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7584 || p
->family
== AF_EVPN
)
7585 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7586 || safi
== SAFI_EVPN
7587 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7588 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7589 || safi
== SAFI_EVPN
) {
7591 json_object_string_add(
7592 json_nexthop_global
, "ip",
7594 attr
->mp_nexthop_global_in
));
7598 attr
->mp_nexthop_global_in
));
7601 json_object_string_add(
7602 json_nexthop_global
, "ip",
7603 inet_ntoa(attr
->nexthop
));
7606 inet_ntoa(attr
->nexthop
));
7610 json_object_string_add(json_nexthop_global
,
7614 json_object_string_add(
7615 json_nexthop_global
, "ip",
7617 &attr
->mp_nexthop_global
, buf
,
7619 json_object_string_add(json_nexthop_global
,
7621 json_object_string_add(json_nexthop_global
,
7626 &attr
->mp_nexthop_global
, buf
,
7631 /* Display the IGP cost or 'inaccessible' */
7632 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
7634 json_object_boolean_false_add(
7635 json_nexthop_global
, "accessible");
7637 vty_out(vty
, " (inaccessible)");
7639 if (path
->extra
&& path
->extra
->igpmetric
) {
7641 json_object_int_add(
7642 json_nexthop_global
, "metric",
7643 path
->extra
->igpmetric
);
7645 vty_out(vty
, " (metric %u)",
7646 path
->extra
->igpmetric
);
7649 /* IGP cost is 0, display this only for json */
7652 json_object_int_add(json_nexthop_global
,
7657 json_object_boolean_true_add(
7658 json_nexthop_global
, "accessible");
7661 /* Display peer "from" output */
7662 /* This path was originated locally */
7663 if (path
->peer
== bgp
->peer_self
) {
7665 if (safi
== SAFI_EVPN
7666 || (p
->family
== AF_INET
7667 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7669 json_object_string_add(
7670 json_peer
, "peerId", "0.0.0.0");
7672 vty_out(vty
, " from 0.0.0.0 ");
7675 json_object_string_add(json_peer
,
7678 vty_out(vty
, " from :: ");
7682 json_object_string_add(
7683 json_peer
, "routerId",
7684 inet_ntoa(bgp
->router_id
));
7686 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7689 /* We RXed this path from one of our peers */
7693 json_object_string_add(
7694 json_peer
, "peerId",
7695 sockunion2str(&path
->peer
->su
, buf
,
7697 json_object_string_add(
7698 json_peer
, "routerId",
7700 &path
->peer
->remote_id
, buf1
,
7703 if (path
->peer
->hostname
)
7704 json_object_string_add(
7705 json_peer
, "hostname",
7706 path
->peer
->hostname
);
7708 if (path
->peer
->domainname
)
7709 json_object_string_add(
7710 json_peer
, "domainname",
7711 path
->peer
->domainname
);
7713 if (path
->peer
->conf_if
)
7714 json_object_string_add(
7715 json_peer
, "interface",
7716 path
->peer
->conf_if
);
7718 if (path
->peer
->conf_if
) {
7719 if (path
->peer
->hostname
7722 BGP_FLAG_SHOW_HOSTNAME
))
7723 vty_out(vty
, " from %s(%s)",
7724 path
->peer
->hostname
,
7725 path
->peer
->conf_if
);
7727 vty_out(vty
, " from %s",
7728 path
->peer
->conf_if
);
7730 if (path
->peer
->hostname
7733 BGP_FLAG_SHOW_HOSTNAME
))
7734 vty_out(vty
, " from %s(%s)",
7735 path
->peer
->hostname
,
7738 vty_out(vty
, " from %s",
7746 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7747 vty_out(vty
, " (%s)",
7748 inet_ntoa(attr
->originator_id
));
7750 vty_out(vty
, " (%s)",
7753 &path
->peer
->remote_id
,
7754 buf1
, sizeof(buf1
)));
7759 * Note when vrfid of nexthop is different from that of prefix
7761 if (path
->extra
&& path
->extra
->bgp_orig
) {
7762 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7767 if (path
->extra
->bgp_orig
->inst_type
7768 == BGP_INSTANCE_TYPE_DEFAULT
)
7772 vn
= path
->extra
->bgp_orig
->name
;
7774 json_object_string_add(json_path
, "nhVrfName",
7777 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7778 json_object_int_add(json_path
,
7781 json_object_int_add(json_path
,
7782 "nhVrfId", (int)nexthop_vrfid
);
7785 if (nexthop_vrfid
== VRF_UNKNOWN
)
7786 vty_out(vty
, " vrf ?");
7788 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7794 json_object_boolean_true_add(json_path
,
7795 "announceNexthopSelf");
7797 vty_out(vty
, " announce-nh-self");
7804 /* display the link-local nexthop */
7805 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7807 json_nexthop_ll
= json_object_new_object();
7808 json_object_string_add(
7809 json_nexthop_ll
, "ip",
7811 &attr
->mp_nexthop_local
, buf
,
7813 json_object_string_add(json_nexthop_ll
, "afi",
7815 json_object_string_add(json_nexthop_ll
, "scope",
7818 json_object_boolean_true_add(json_nexthop_ll
,
7821 if (!attr
->mp_nexthop_prefer_global
)
7822 json_object_boolean_true_add(
7823 json_nexthop_ll
, "used");
7825 json_object_boolean_true_add(
7826 json_nexthop_global
, "used");
7828 vty_out(vty
, " (%s) %s\n",
7830 &attr
->mp_nexthop_local
, buf
,
7832 attr
->mp_nexthop_prefer_global
7837 /* If we do not have a link-local nexthop then we must flag the
7841 json_object_boolean_true_add(
7842 json_nexthop_global
, "used");
7845 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7846 * Int/Ext/Local, Atomic, best */
7848 json_object_string_add(
7849 json_path
, "origin",
7850 bgp_origin_long_str
[attr
->origin
]);
7852 vty_out(vty
, " Origin %s",
7853 bgp_origin_long_str
[attr
->origin
]);
7855 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7857 json_object_int_add(json_path
, "med",
7860 vty_out(vty
, ", metric %u", attr
->med
);
7863 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7865 json_object_int_add(json_path
, "localpref",
7868 vty_out(vty
, ", localpref %u",
7872 if (attr
->weight
!= 0) {
7874 json_object_int_add(json_path
, "weight",
7877 vty_out(vty
, ", weight %u", attr
->weight
);
7880 if (attr
->tag
!= 0) {
7882 json_object_int_add(json_path
, "tag",
7885 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7889 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
7891 json_object_boolean_false_add(json_path
,
7894 vty_out(vty
, ", invalid");
7895 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7897 json_object_boolean_true_add(json_path
,
7900 vty_out(vty
, ", valid");
7903 if (path
->peer
!= bgp
->peer_self
) {
7904 if (path
->peer
->as
== path
->peer
->local_as
) {
7905 if (CHECK_FLAG(bgp
->config
,
7906 BGP_CONFIG_CONFEDERATION
)) {
7908 json_object_string_add(
7913 ", confed-internal");
7916 json_object_string_add(
7920 vty_out(vty
, ", internal");
7923 if (bgp_confederation_peers_check(
7924 bgp
, path
->peer
->as
)) {
7926 json_object_string_add(
7931 ", confed-external");
7934 json_object_string_add(
7938 vty_out(vty
, ", external");
7941 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7943 json_object_boolean_true_add(json_path
,
7945 json_object_boolean_true_add(json_path
,
7948 vty_out(vty
, ", aggregated, local");
7950 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
7952 json_object_boolean_true_add(json_path
,
7955 vty_out(vty
, ", sourced");
7958 json_object_boolean_true_add(json_path
,
7960 json_object_boolean_true_add(json_path
,
7963 vty_out(vty
, ", sourced, local");
7967 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7969 json_object_boolean_true_add(json_path
,
7972 vty_out(vty
, ", atomic-aggregate");
7975 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
7976 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
7977 && bgp_path_info_mpath_count(path
))) {
7979 json_object_boolean_true_add(json_path
,
7982 vty_out(vty
, ", multipath");
7985 // Mark the bestpath(s)
7986 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
7987 first_as
= aspath_get_first_as(attr
->aspath
);
7992 json_object_new_object();
7993 json_object_int_add(json_bestpath
,
7994 "bestpathFromAs", first_as
);
7997 vty_out(vty
, ", bestpath-from-AS %u",
8001 ", bestpath-from-AS Local");
8005 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8009 json_object_new_object();
8010 json_object_boolean_true_add(json_bestpath
,
8013 vty_out(vty
, ", best");
8017 json_object_object_add(json_path
, "bestpath",
8023 /* Line 4 display Community */
8024 if (attr
->community
) {
8026 if (!attr
->community
->json
)
8027 community_str(attr
->community
, true);
8028 json_object_lock(attr
->community
->json
);
8029 json_object_object_add(json_path
, "community",
8030 attr
->community
->json
);
8032 vty_out(vty
, " Community: %s\n",
8033 attr
->community
->str
);
8037 /* Line 5 display Extended-community */
8038 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8040 json_ext_community
= json_object_new_object();
8041 json_object_string_add(json_ext_community
,
8043 attr
->ecommunity
->str
);
8044 json_object_object_add(json_path
,
8045 "extendedCommunity",
8046 json_ext_community
);
8048 vty_out(vty
, " Extended Community: %s\n",
8049 attr
->ecommunity
->str
);
8053 /* Line 6 display Large community */
8054 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8056 if (!attr
->lcommunity
->json
)
8057 lcommunity_str(attr
->lcommunity
, true);
8058 json_object_lock(attr
->lcommunity
->json
);
8059 json_object_object_add(json_path
,
8061 attr
->lcommunity
->json
);
8063 vty_out(vty
, " Large Community: %s\n",
8064 attr
->lcommunity
->str
);
8068 /* Line 7 display Originator, Cluster-id */
8069 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8070 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8072 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8074 json_object_string_add(
8075 json_path
, "originatorId",
8076 inet_ntoa(attr
->originator_id
));
8078 vty_out(vty
, " Originator: %s",
8079 inet_ntoa(attr
->originator_id
));
8082 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8087 json_object_new_object();
8088 json_cluster_list_list
=
8089 json_object_new_array();
8092 i
< attr
->cluster
->length
/ 4;
8094 json_string
= json_object_new_string(
8098 json_object_array_add(
8099 json_cluster_list_list
,
8103 /* struct cluster_list does not have
8105 * aspath and community do. Add this
8108 json_object_string_add(json_cluster_list,
8109 "string", attr->cluster->str);
8111 json_object_object_add(
8112 json_cluster_list
, "list",
8113 json_cluster_list_list
);
8114 json_object_object_add(
8115 json_path
, "clusterList",
8118 vty_out(vty
, ", Cluster list: ");
8121 i
< attr
->cluster
->length
/ 4;
8135 if (path
->extra
&& path
->extra
->damp_info
)
8136 bgp_damp_info_vty(vty
, path
, json_path
);
8139 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8140 && safi
!= SAFI_EVPN
) {
8141 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8144 json_object_int_add(json_path
, "remoteLabel",
8147 vty_out(vty
, " Remote label: %d\n", label
);
8151 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8153 json_object_int_add(json_path
, "labelIndex",
8156 vty_out(vty
, " Label Index: %d\n",
8160 /* Line 8 display Addpath IDs */
8161 if (path
->addpath_rx_id
|| path
->addpath_tx_id
) {
8163 json_object_int_add(json_path
, "addpathRxId",
8164 path
->addpath_rx_id
);
8165 json_object_int_add(json_path
, "addpathTxId",
8166 path
->addpath_tx_id
);
8168 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8169 path
->addpath_rx_id
,
8170 path
->addpath_tx_id
);
8174 /* If we used addpath to TX a non-bestpath we need to display
8175 * "Advertised to" on a path-by-path basis */
8176 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8179 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8181 bgp_addpath_encode_tx(peer
, afi
, safi
);
8182 has_adj
= bgp_adj_out_lookup(
8183 peer
, path
->net
, path
->addpath_tx_id
);
8185 if ((addpath_capable
&& has_adj
)
8186 || (!addpath_capable
&& has_adj
8187 && CHECK_FLAG(path
->flags
,
8188 BGP_PATH_SELECTED
))) {
8189 if (json_path
&& !json_adv_to
)
8191 json_object_new_object();
8193 route_vty_out_advertised_to(
8202 json_object_object_add(json_path
,
8213 /* Line 9 display Uptime */
8214 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8216 json_last_update
= json_object_new_object();
8217 json_object_int_add(json_last_update
, "epoch", tbuf
);
8218 json_object_string_add(json_last_update
, "string",
8220 json_object_object_add(json_path
, "lastUpdate",
8223 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8225 /* Line 10 display PMSI tunnel attribute, if present */
8226 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8227 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8228 attr
->pmsi_tnl_type
,
8229 PMSI_TNLTYPE_STR_DEFAULT
);
8232 json_pmsi
= json_object_new_object();
8233 json_object_string_add(json_pmsi
,
8235 json_object_object_add(json_path
, "pmsi",
8238 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8244 /* We've constructed the json object for this path, add it to the json
8248 if (json_nexthop_global
|| json_nexthop_ll
) {
8249 json_nexthops
= json_object_new_array();
8251 if (json_nexthop_global
)
8252 json_object_array_add(json_nexthops
,
8253 json_nexthop_global
);
8255 if (json_nexthop_ll
)
8256 json_object_array_add(json_nexthops
,
8259 json_object_object_add(json_path
, "nexthops",
8263 json_object_object_add(json_path
, "peer", json_peer
);
8264 json_object_array_add(json_paths
, json_path
);
8269 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8270 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8271 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8273 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8274 const char *prefix_list_str
, afi_t afi
,
8275 safi_t safi
, enum bgp_show_type type
);
8276 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8277 const char *filter
, afi_t afi
, safi_t safi
,
8278 enum bgp_show_type type
);
8279 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8280 const char *rmap_str
, afi_t afi
, safi_t safi
,
8281 enum bgp_show_type type
);
8282 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8283 const char *com
, int exact
, afi_t afi
,
8285 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8286 const char *prefix
, afi_t afi
, safi_t safi
,
8287 enum bgp_show_type type
);
8288 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8289 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8290 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8291 const char *comstr
, int exact
, afi_t afi
,
8292 safi_t safi
, bool use_json
);
8295 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8296 struct bgp_table
*table
, enum bgp_show_type type
,
8297 void *output_arg
, bool use_json
, char *rd
,
8298 int is_last
, unsigned long *output_cum
,
8299 unsigned long *total_cum
,
8300 unsigned long *json_header_depth
)
8302 struct bgp_path_info
*pi
;
8303 struct bgp_node
*rn
;
8306 unsigned long output_count
= 0;
8307 unsigned long total_count
= 0;
8310 json_object
*json_paths
= NULL
;
8313 if (output_cum
&& *output_cum
!= 0)
8316 if (use_json
&& !*json_header_depth
) {
8318 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8319 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8320 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8321 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8324 table
->version
, inet_ntoa(bgp
->router_id
));
8325 *json_header_depth
= 2;
8327 vty_out(vty
, " \"routeDistinguishers\" : {");
8328 ++*json_header_depth
;
8332 if (use_json
&& rd
) {
8333 vty_out(vty
, " \"%s\" : { ", rd
);
8336 /* Start processing of routes. */
8337 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8338 if (rn
->info
== NULL
)
8343 json_paths
= json_object_new_array();
8347 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
8349 if (type
== bgp_show_type_flap_statistics
8350 || type
== bgp_show_type_flap_neighbor
8351 || type
== bgp_show_type_dampend_paths
8352 || type
== bgp_show_type_damp_neighbor
) {
8353 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8356 if (type
== bgp_show_type_regexp
) {
8357 regex_t
*regex
= output_arg
;
8359 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8363 if (type
== bgp_show_type_prefix_list
) {
8364 struct prefix_list
*plist
= output_arg
;
8366 if (prefix_list_apply(plist
, &rn
->p
)
8370 if (type
== bgp_show_type_filter_list
) {
8371 struct as_list
*as_list
= output_arg
;
8373 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8374 != AS_FILTER_PERMIT
)
8377 if (type
== bgp_show_type_route_map
) {
8378 struct route_map
*rmap
= output_arg
;
8379 struct bgp_path_info path
;
8380 struct attr dummy_attr
;
8383 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8385 path
.peer
= pi
->peer
;
8386 path
.attr
= &dummy_attr
;
8388 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8390 if (ret
== RMAP_DENYMATCH
)
8393 if (type
== bgp_show_type_neighbor
8394 || type
== bgp_show_type_flap_neighbor
8395 || type
== bgp_show_type_damp_neighbor
) {
8396 union sockunion
*su
= output_arg
;
8398 if (pi
->peer
== NULL
8399 || pi
->peer
->su_remote
== NULL
8400 || !sockunion_same(pi
->peer
->su_remote
, su
))
8403 if (type
== bgp_show_type_cidr_only
) {
8404 uint32_t destination
;
8406 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8407 if (IN_CLASSC(destination
)
8408 && rn
->p
.prefixlen
== 24)
8410 if (IN_CLASSB(destination
)
8411 && rn
->p
.prefixlen
== 16)
8413 if (IN_CLASSA(destination
)
8414 && rn
->p
.prefixlen
== 8)
8417 if (type
== bgp_show_type_prefix_longer
) {
8419 if (!prefix_match(p
, &rn
->p
))
8422 if (type
== bgp_show_type_community_all
) {
8423 if (!pi
->attr
->community
)
8426 if (type
== bgp_show_type_community
) {
8427 struct community
*com
= output_arg
;
8429 if (!pi
->attr
->community
8430 || !community_match(pi
->attr
->community
,
8434 if (type
== bgp_show_type_community_exact
) {
8435 struct community
*com
= output_arg
;
8437 if (!pi
->attr
->community
8438 || !community_cmp(pi
->attr
->community
, com
))
8441 if (type
== bgp_show_type_community_list
) {
8442 struct community_list
*list
= output_arg
;
8444 if (!community_list_match(pi
->attr
->community
,
8448 if (type
== bgp_show_type_community_list_exact
) {
8449 struct community_list
*list
= output_arg
;
8451 if (!community_list_exact_match(
8452 pi
->attr
->community
, list
))
8455 if (type
== bgp_show_type_lcommunity
) {
8456 struct lcommunity
*lcom
= output_arg
;
8458 if (!pi
->attr
->lcommunity
8459 || !lcommunity_match(pi
->attr
->lcommunity
,
8463 if (type
== bgp_show_type_lcommunity_list
) {
8464 struct community_list
*list
= output_arg
;
8466 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8470 if (type
== bgp_show_type_lcommunity_all
) {
8471 if (!pi
->attr
->lcommunity
)
8474 if (type
== bgp_show_type_dampend_paths
8475 || type
== bgp_show_type_damp_neighbor
) {
8476 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8477 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8481 if (!use_json
&& header
) {
8482 vty_out(vty
, "BGP table version is %" PRIu64
8483 ", local router ID is %s, vrf id ",
8485 inet_ntoa(bgp
->router_id
));
8486 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8487 vty_out(vty
, "%s", VRFID_NONE_STR
);
8489 vty_out(vty
, "%u", bgp
->vrf_id
);
8491 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8492 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8493 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8494 if (type
== bgp_show_type_dampend_paths
8495 || type
== bgp_show_type_damp_neighbor
)
8496 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8497 else if (type
== bgp_show_type_flap_statistics
8498 || type
== bgp_show_type_flap_neighbor
)
8499 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8501 vty_out(vty
, BGP_SHOW_HEADER
);
8504 if (rd
!= NULL
&& !display
&& !output_count
) {
8507 "Route Distinguisher: %s\n",
8510 if (type
== bgp_show_type_dampend_paths
8511 || type
== bgp_show_type_damp_neighbor
)
8512 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
8513 safi
, use_json
, json_paths
);
8514 else if (type
== bgp_show_type_flap_statistics
8515 || type
== bgp_show_type_flap_neighbor
)
8516 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
8517 safi
, use_json
, json_paths
);
8519 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
8531 if (p
->family
== AF_FLOWSPEC
) {
8532 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
8534 bgp_fs_nlri_get_string((unsigned char *)
8535 p
->u
.prefix_flowspec
.ptr
,
8536 p
->u
.prefix_flowspec
8539 NLRI_STRING_FORMAT_MIN
,
8542 vty_out(vty
, "\"%s/%d\": ",
8544 p
->u
.prefix_flowspec
.prefixlen
);
8546 vty_out(vty
, ",\"%s/%d\": ",
8548 p
->u
.prefix_flowspec
.prefixlen
);
8550 prefix2str(p
, buf2
, sizeof(buf2
));
8552 vty_out(vty
, "\"%s\": ", buf2
);
8554 vty_out(vty
, ",\"%s\": ", buf2
);
8557 json_object_to_json_string(json_paths
));
8558 json_object_free(json_paths
);
8565 output_count
+= *output_cum
;
8566 *output_cum
= output_count
;
8569 total_count
+= *total_cum
;
8570 *total_cum
= total_count
;
8574 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8578 for (i
= 0; i
< *json_header_depth
; ++i
)
8579 vty_out(vty
, " } ");
8583 /* No route is displayed */
8584 if (output_count
== 0) {
8585 if (type
== bgp_show_type_normal
)
8587 "No BGP prefixes displayed, %ld exist\n",
8591 "\nDisplayed %ld routes and %ld total paths\n",
8592 output_count
, total_count
);
8599 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8600 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8601 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8603 struct bgp_node
*rn
, *next
;
8604 unsigned long output_cum
= 0;
8605 unsigned long total_cum
= 0;
8606 unsigned long json_header_depth
= 0;
8609 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8611 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8612 next
= bgp_route_next(rn
);
8613 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8615 if (rn
->info
!= NULL
) {
8616 struct prefix_rd prd
;
8617 char rd
[RD_ADDRSTRLEN
];
8619 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8620 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8621 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8622 output_arg
, use_json
, rd
, next
== NULL
,
8623 &output_cum
, &total_cum
,
8624 &json_header_depth
);
8630 if (output_cum
== 0)
8631 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8635 "\nDisplayed %ld routes and %ld total paths\n",
8636 output_cum
, total_cum
);
8640 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8641 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8643 struct bgp_table
*table
;
8644 unsigned long json_header_depth
= 0;
8647 bgp
= bgp_get_default();
8652 vty_out(vty
, "No BGP process is configured\n");
8654 vty_out(vty
, "{}\n");
8658 table
= bgp
->rib
[afi
][safi
];
8659 /* use MPLS and ENCAP specific shows until they are merged */
8660 if (safi
== SAFI_MPLS_VPN
) {
8661 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8662 output_arg
, use_json
);
8665 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8666 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8667 output_arg
, use_json
,
8670 /* labeled-unicast routes live in the unicast table */
8671 else if (safi
== SAFI_LABELED_UNICAST
)
8672 safi
= SAFI_UNICAST
;
8674 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8675 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8678 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8679 safi_t safi
, bool use_json
)
8681 struct listnode
*node
, *nnode
;
8684 bool route_output
= false;
8687 vty_out(vty
, "{\n");
8689 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8690 route_output
= true;
8693 vty_out(vty
, ",\n");
8697 vty_out(vty
, "\"%s\":",
8698 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8702 vty_out(vty
, "\nInstance %s:\n",
8703 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8707 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8712 vty_out(vty
, "}\n");
8713 else if (!route_output
)
8714 vty_out(vty
, "%% BGP instance not found\n");
8717 /* Header of detailed BGP route information */
8718 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8719 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8720 afi_t afi
, safi_t safi
, json_object
*json
)
8722 struct bgp_path_info
*pi
;
8725 struct listnode
*node
, *nnode
;
8726 char buf1
[RD_ADDRSTRLEN
];
8727 char buf2
[INET6_ADDRSTRLEN
];
8728 char buf3
[EVPN_ROUTE_STRLEN
];
8729 char prefix_str
[BUFSIZ
];
8734 int route_filter_translated_v4
= 0;
8735 int route_filter_v4
= 0;
8736 int route_filter_translated_v6
= 0;
8737 int route_filter_v6
= 0;
8740 int accept_own_nexthop
= 0;
8743 int no_advertise
= 0;
8747 int has_valid_label
= 0;
8748 mpls_label_t label
= 0;
8749 json_object
*json_adv_to
= NULL
;
8752 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8754 if (has_valid_label
)
8755 label
= label_pton(&rn
->local_label
);
8758 if (has_valid_label
)
8759 json_object_int_add(json
, "localLabel", label
);
8761 json_object_string_add(
8763 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8765 if (safi
== SAFI_EVPN
)
8766 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8767 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8770 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8771 buf3
, sizeof(buf3
)));
8773 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8774 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8775 ? prefix_rd2str(prd
, buf1
,
8778 safi
== SAFI_MPLS_VPN
? ":" : "",
8779 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8783 if (has_valid_label
)
8784 vty_out(vty
, "Local label: %d\n", label
);
8785 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8786 vty_out(vty
, "not allocated\n");
8789 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
8791 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
8793 if (pi
->extra
&& pi
->extra
->suppress
)
8796 if (pi
->attr
->community
== NULL
)
8799 no_advertise
+= community_include(
8800 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
8801 no_export
+= community_include(pi
->attr
->community
,
8802 COMMUNITY_NO_EXPORT
);
8803 local_as
+= community_include(pi
->attr
->community
,
8804 COMMUNITY_LOCAL_AS
);
8805 accept_own
+= community_include(pi
->attr
->community
,
8806 COMMUNITY_ACCEPT_OWN
);
8807 route_filter_translated_v4
+= community_include(
8808 pi
->attr
->community
,
8809 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
8810 route_filter_translated_v6
+= community_include(
8811 pi
->attr
->community
,
8812 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
8813 route_filter_v4
+= community_include(
8814 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
8815 route_filter_v6
+= community_include(
8816 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
8817 llgr_stale
+= community_include(pi
->attr
->community
,
8818 COMMUNITY_LLGR_STALE
);
8819 no_llgr
+= community_include(pi
->attr
->community
,
8821 accept_own_nexthop
+=
8822 community_include(pi
->attr
->community
,
8823 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
8824 blackhole
+= community_include(pi
->attr
->community
,
8825 COMMUNITY_BLACKHOLE
);
8826 no_peer
+= community_include(pi
->attr
->community
,
8832 vty_out(vty
, "Paths: (%d available", count
);
8834 vty_out(vty
, ", best #%d", best
);
8835 if (safi
== SAFI_UNICAST
)
8836 vty_out(vty
, ", table %s",
8838 == BGP_INSTANCE_TYPE_DEFAULT
)
8842 vty_out(vty
, ", no best path");
8846 ", accept own local route exported and imported in different VRF");
8847 else if (route_filter_translated_v4
)
8849 ", mark translated RTs for VPNv4 route filtering");
8850 else if (route_filter_v4
)
8852 ", attach RT as-is for VPNv4 route filtering");
8853 else if (route_filter_translated_v6
)
8855 ", mark translated RTs for VPNv6 route filtering");
8856 else if (route_filter_v6
)
8858 ", attach RT as-is for VPNv6 route filtering");
8859 else if (llgr_stale
)
8861 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
8864 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
8865 else if (accept_own_nexthop
)
8867 ", accept local nexthop");
8869 vty_out(vty
, ", inform peer to blackhole prefix");
8871 vty_out(vty
, ", not advertised to EBGP peer");
8872 else if (no_advertise
)
8873 vty_out(vty
, ", not advertised to any peer");
8875 vty_out(vty
, ", not advertised outside local AS");
8878 ", inform EBGP peer not to advertise to their EBGP peers");
8882 ", Advertisements suppressed by an aggregate.");
8883 vty_out(vty
, ")\n");
8886 /* If we are not using addpath then we can display Advertised to and
8888 * show what peers we advertised the bestpath to. If we are using
8890 * though then we must display Advertised to on a path-by-path basis. */
8891 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8892 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8893 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8894 if (json
&& !json_adv_to
)
8895 json_adv_to
= json_object_new_object();
8897 route_vty_out_advertised_to(
8899 " Advertised to non peer-group peers:\n ",
8906 json_object_object_add(json
, "advertisedTo",
8911 vty_out(vty
, " Not advertised to any peer");
8917 /* Display specified route of BGP table. */
8918 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8919 struct bgp_table
*rib
, const char *ip_str
,
8920 afi_t afi
, safi_t safi
,
8921 struct prefix_rd
*prd
, int prefix_check
,
8922 enum bgp_path_type pathtype
, bool use_json
)
8927 struct prefix match
;
8928 struct bgp_node
*rn
;
8929 struct bgp_node
*rm
;
8930 struct bgp_path_info
*pi
;
8931 struct bgp_table
*table
;
8932 json_object
*json
= NULL
;
8933 json_object
*json_paths
= NULL
;
8935 /* Check IP address argument. */
8936 ret
= str2prefix(ip_str
, &match
);
8938 vty_out(vty
, "address is malformed\n");
8942 match
.family
= afi2family(afi
);
8945 json
= json_object_new_object();
8946 json_paths
= json_object_new_array();
8949 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8950 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8951 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8954 if ((table
= rn
->info
) == NULL
)
8959 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8963 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8964 bgp_unlock_node(rm
);
8968 for (pi
= rm
->info
; pi
; pi
= pi
->next
) {
8970 route_vty_out_detail_header(
8972 (struct prefix_rd
*)&rn
->p
,
8973 AFI_IP
, safi
, json
);
8978 if (pathtype
== BGP_PATH_SHOW_ALL
8979 || (pathtype
== BGP_PATH_SHOW_BESTPATH
8980 && CHECK_FLAG(pi
->flags
,
8982 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
8983 && (CHECK_FLAG(pi
->flags
,
8985 || CHECK_FLAG(pi
->flags
,
8986 BGP_PATH_SELECTED
))))
8987 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8992 bgp_unlock_node(rm
);
8994 } else if (safi
== SAFI_FLOWSPEC
) {
8995 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
8996 &match
, prefix_check
,
9003 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9005 || rn
->p
.prefixlen
== match
.prefixlen
) {
9006 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
9008 route_vty_out_detail_header(
9009 vty
, bgp
, rn
, NULL
, afi
,
9015 if (pathtype
== BGP_PATH_SHOW_ALL
9017 == BGP_PATH_SHOW_BESTPATH
9022 == BGP_PATH_SHOW_MULTIPATH
9028 BGP_PATH_SELECTED
))))
9029 route_vty_out_detail(
9030 vty
, bgp
, &rn
->p
, pi
,
9031 afi
, safi
, json_paths
);
9035 bgp_unlock_node(rn
);
9041 json_object_object_add(json
, "paths", json_paths
);
9043 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9044 json
, JSON_C_TO_STRING_PRETTY
));
9045 json_object_free(json
);
9048 vty_out(vty
, "%% Network not in table\n");
9056 /* Display specified route of Main RIB */
9057 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9058 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9059 int prefix_check
, enum bgp_path_type pathtype
,
9063 bgp
= bgp_get_default();
9066 vty_out(vty
, "No BGP process is configured\n");
9068 vty_out(vty
, "{}\n");
9073 /* labeled-unicast routes live in the unicast table */
9074 if (safi
== SAFI_LABELED_UNICAST
)
9075 safi
= SAFI_UNICAST
;
9077 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9078 afi
, safi
, prd
, prefix_check
, pathtype
,
9082 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9083 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9086 struct lcommunity
*lcom
;
9092 b
= buffer_new(1024);
9093 for (i
= 0; i
< argc
; i
++) {
9095 buffer_putc(b
, ' ');
9097 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9099 buffer_putstr(b
, argv
[i
]->arg
);
9103 buffer_putc(b
, '\0');
9105 str
= buffer_getstr(b
);
9108 lcom
= lcommunity_str2com(str
);
9109 XFREE(MTYPE_TMP
, str
);
9111 vty_out(vty
, "%% Large-community malformed\n");
9115 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9119 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9120 const char *lcom
, afi_t afi
, safi_t safi
,
9123 struct community_list
*list
;
9125 list
= community_list_lookup(bgp_clist
, lcom
,
9126 LARGE_COMMUNITY_LIST_MASTER
);
9128 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9133 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9137 DEFUN (show_ip_bgp_large_community_list
,
9138 show_ip_bgp_large_community_list_cmd
,
9139 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9143 BGP_INSTANCE_HELP_STR
9145 BGP_SAFI_WITH_LABEL_HELP_STR
9146 "Display routes matching the large-community-list\n"
9147 "large-community-list number\n"
9148 "large-community-list name\n"
9152 afi_t afi
= AFI_IP6
;
9153 safi_t safi
= SAFI_UNICAST
;
9156 if (argv_find(argv
, argc
, "ip", &idx
))
9158 if (argv_find(argv
, argc
, "view", &idx
)
9159 || argv_find(argv
, argc
, "vrf", &idx
))
9160 vrf
= argv
[++idx
]->arg
;
9161 if (argv_find(argv
, argc
, "ipv4", &idx
)
9162 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9163 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9164 if (argv_find(argv
, argc
, "unicast", &idx
)
9165 || argv_find(argv
, argc
, "multicast", &idx
))
9166 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9169 bool uj
= use_json(argc
, argv
);
9171 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9173 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9177 argv_find(argv
, argc
, "large-community-list", &idx
);
9178 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9181 DEFUN (show_ip_bgp_large_community
,
9182 show_ip_bgp_large_community_cmd
,
9183 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9187 BGP_INSTANCE_HELP_STR
9189 BGP_SAFI_WITH_LABEL_HELP_STR
9190 "Display routes matching the large-communities\n"
9191 "List of large-community numbers\n"
9195 afi_t afi
= AFI_IP6
;
9196 safi_t safi
= SAFI_UNICAST
;
9199 if (argv_find(argv
, argc
, "ip", &idx
))
9201 if (argv_find(argv
, argc
, "view", &idx
)
9202 || argv_find(argv
, argc
, "vrf", &idx
))
9203 vrf
= argv
[++idx
]->arg
;
9204 if (argv_find(argv
, argc
, "ipv4", &idx
)
9205 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9206 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9207 if (argv_find(argv
, argc
, "unicast", &idx
)
9208 || argv_find(argv
, argc
, "multicast", &idx
))
9209 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9212 bool uj
= use_json(argc
, argv
);
9214 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9216 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9220 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9221 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9223 return bgp_show(vty
, bgp
, afi
, safi
,
9224 bgp_show_type_lcommunity_all
, NULL
, uj
);
9227 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9231 /* BGP route print out function without JSON */
9234 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9235 <dampening <parameters>\
9240 |community-list <(1-500)|WORD> [exact-match]\
9241 |A.B.C.D/M longer-prefixes\
9242 |X:X::X:X/M longer-prefixes\
9247 BGP_INSTANCE_HELP_STR
9249 BGP_SAFI_WITH_LABEL_HELP_STR
9250 "Display detailed information about dampening\n"
9251 "Display detail of configured dampening parameters\n"
9252 "Display routes matching the route-map\n"
9253 "A route-map to match on\n"
9254 "Display routes conforming to the prefix-list\n"
9255 "Prefix-list name\n"
9256 "Display routes conforming to the filter-list\n"
9257 "Regular expression access list name\n"
9258 "BGP RIB advertisement statistics\n"
9259 "Display routes matching the community-list\n"
9260 "community-list number\n"
9261 "community-list name\n"
9262 "Exact match of the communities\n"
9264 "Display route and more specific routes\n"
9266 "Display route and more specific routes\n")
9268 afi_t afi
= AFI_IP6
;
9269 safi_t safi
= SAFI_UNICAST
;
9270 int exact_match
= 0;
9271 struct bgp
*bgp
= NULL
;
9274 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9279 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9280 if (argv_find(argv
, argc
, "parameters", &idx
))
9281 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9284 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9285 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9286 safi
, bgp_show_type_prefix_list
);
9288 if (argv_find(argv
, argc
, "filter-list", &idx
))
9289 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9290 safi
, bgp_show_type_filter_list
);
9292 if (argv_find(argv
, argc
, "statistics", &idx
))
9293 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9295 if (argv_find(argv
, argc
, "route-map", &idx
))
9296 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9297 safi
, bgp_show_type_route_map
);
9299 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9300 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9301 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9303 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9304 exact_match
, afi
, safi
);
9307 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9308 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9309 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9311 bgp_show_type_prefix_longer
);
9316 /* BGP route print out function with JSON */
9317 DEFUN (show_ip_bgp_json
,
9318 show_ip_bgp_json_cmd
,
9319 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9321 |dampening <flap-statistics|dampened-paths>\
9322 |community [AA:NN|local-AS|no-advertise|no-export\
9323 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9324 |accept-own|accept-own-nexthop|route-filter-v6\
9325 |route-filter-v4|route-filter-translated-v6\
9326 |route-filter-translated-v4] [exact-match]\
9331 BGP_INSTANCE_HELP_STR
9333 BGP_SAFI_WITH_LABEL_HELP_STR
9334 "Display only routes with non-natural netmasks\n"
9335 "Display detailed information about dampening\n"
9336 "Display flap statistics of routes\n"
9337 "Display paths suppressed due to dampening\n"
9338 "Display routes matching the communities\n"
9340 "Do not send outside local AS (well-known community)\n"
9341 "Do not advertise to any peer (well-known community)\n"
9342 "Do not export to next AS (well-known community)\n"
9343 "Graceful shutdown (well-known community)\n"
9344 "Do not export to any peer (well-known community)\n"
9345 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9346 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9347 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9348 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9349 "Should accept VPN route with local nexthop (well-known community)\n"
9350 "RT VPNv6 route filtering (well-known community)\n"
9351 "RT VPNv4 route filtering (well-known community)\n"
9352 "RT translated VPNv6 route filtering (well-known community)\n"
9353 "RT translated VPNv4 route filtering (well-known community)\n"
9354 "Exact match of the communities\n"
9357 afi_t afi
= AFI_IP6
;
9358 safi_t safi
= SAFI_UNICAST
;
9359 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9360 struct bgp
*bgp
= NULL
;
9362 int exact_match
= 0;
9363 bool uj
= use_json(argc
, argv
);
9368 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9373 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9374 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9377 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9378 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9379 return bgp_show(vty
, bgp
, afi
, safi
,
9380 bgp_show_type_dampend_paths
, NULL
, uj
);
9381 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9382 return bgp_show(vty
, bgp
, afi
, safi
,
9383 bgp_show_type_flap_statistics
, NULL
,
9387 if (argv_find(argv
, argc
, "community", &idx
)) {
9388 char *maybecomm
= idx
+ 1 < argc
? argv
[idx
+ 1]->text
: NULL
;
9389 char *community
= NULL
;
9391 if (maybecomm
&& !strmatch(maybecomm
, "json")
9392 && !strmatch(maybecomm
, "exact-match"))
9393 community
= maybecomm
;
9395 if (argv_find(argv
, argc
, "exact-match", &idx
))
9399 return bgp_show_community(vty
, bgp
, community
,
9400 exact_match
, afi
, safi
, uj
);
9402 return (bgp_show(vty
, bgp
, afi
, safi
,
9403 bgp_show_type_community_all
, NULL
,
9407 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9410 DEFUN (show_ip_bgp_route
,
9411 show_ip_bgp_route_cmd
,
9412 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9413 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9417 BGP_INSTANCE_HELP_STR
9419 BGP_SAFI_WITH_LABEL_HELP_STR
9420 "Network in the BGP routing table to display\n"
9422 "Network in the BGP routing table to display\n"
9424 "Display only the bestpath\n"
9425 "Display only multipaths\n"
9428 int prefix_check
= 0;
9430 afi_t afi
= AFI_IP6
;
9431 safi_t safi
= SAFI_UNICAST
;
9432 char *prefix
= NULL
;
9433 struct bgp
*bgp
= NULL
;
9434 enum bgp_path_type path_type
;
9435 bool uj
= use_json(argc
, argv
);
9439 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9446 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9450 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9451 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9452 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9454 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9455 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9458 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9459 && afi
!= AFI_IP6
) {
9461 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9464 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9467 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9471 prefix
= argv
[idx
]->arg
;
9473 /* [<bestpath|multipath>] */
9474 if (argv_find(argv
, argc
, "bestpath", &idx
))
9475 path_type
= BGP_PATH_SHOW_BESTPATH
;
9476 else if (argv_find(argv
, argc
, "multipath", &idx
))
9477 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9479 path_type
= BGP_PATH_SHOW_ALL
;
9481 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9485 DEFUN (show_ip_bgp_regexp
,
9486 show_ip_bgp_regexp_cmd
,
9487 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9491 BGP_INSTANCE_HELP_STR
9493 BGP_SAFI_WITH_LABEL_HELP_STR
9494 "Display routes matching the AS path regular expression\n"
9495 "A regular-expression to match the BGP AS paths\n")
9497 afi_t afi
= AFI_IP6
;
9498 safi_t safi
= SAFI_UNICAST
;
9499 struct bgp
*bgp
= NULL
;
9502 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9507 // get index of regex
9508 argv_find(argv
, argc
, "regexp", &idx
);
9511 char *regstr
= argv_concat(argv
, argc
, idx
);
9512 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9513 bgp_show_type_regexp
);
9514 XFREE(MTYPE_TMP
, regstr
);
9518 DEFUN (show_ip_bgp_instance_all
,
9519 show_ip_bgp_instance_all_cmd
,
9520 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9524 BGP_INSTANCE_ALL_HELP_STR
9526 BGP_SAFI_WITH_LABEL_HELP_STR
9530 safi_t safi
= SAFI_UNICAST
;
9531 struct bgp
*bgp
= NULL
;
9533 bool uj
= use_json(argc
, argv
);
9538 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9543 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9547 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9548 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9553 regex
= bgp_regcomp(regstr
);
9555 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9559 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9560 bgp_regex_free(regex
);
9564 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9565 const char *prefix_list_str
, afi_t afi
,
9566 safi_t safi
, enum bgp_show_type type
)
9568 struct prefix_list
*plist
;
9570 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9571 if (plist
== NULL
) {
9572 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9577 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9580 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9581 const char *filter
, afi_t afi
, safi_t safi
,
9582 enum bgp_show_type type
)
9584 struct as_list
*as_list
;
9586 as_list
= as_list_lookup(filter
);
9587 if (as_list
== NULL
) {
9588 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9593 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9596 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9597 const char *rmap_str
, afi_t afi
, safi_t safi
,
9598 enum bgp_show_type type
)
9600 struct route_map
*rmap
;
9602 rmap
= route_map_lookup_by_name(rmap_str
);
9604 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9608 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9611 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9612 const char *comstr
, int exact
, afi_t afi
,
9613 safi_t safi
, bool use_json
)
9615 struct community
*com
;
9618 com
= community_str2com(comstr
);
9620 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9624 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9625 (exact
? bgp_show_type_community_exact
9626 : bgp_show_type_community
),
9628 community_free(&com
);
9633 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9634 const char *com
, int exact
, afi_t afi
,
9637 struct community_list
*list
;
9639 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9641 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9645 return bgp_show(vty
, bgp
, afi
, safi
,
9646 (exact
? bgp_show_type_community_list_exact
9647 : bgp_show_type_community_list
),
9651 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9652 const char *prefix
, afi_t afi
, safi_t safi
,
9653 enum bgp_show_type type
)
9660 ret
= str2prefix(prefix
, p
);
9662 vty_out(vty
, "%% Malformed Prefix\n");
9666 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9671 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9672 const char *ip_str
, bool use_json
)
9678 /* Get peer sockunion. */
9679 ret
= str2sockunion(ip_str
, &su
);
9681 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9683 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9687 json_object
*json_no
= NULL
;
9688 json_no
= json_object_new_object();
9689 json_object_string_add(
9691 "malformedAddressOrName",
9693 vty_out(vty
, "%s\n",
9694 json_object_to_json_string_ext(
9696 JSON_C_TO_STRING_PRETTY
));
9697 json_object_free(json_no
);
9700 "%% Malformed address or name: %s\n",
9708 /* Peer structure lookup. */
9709 peer
= peer_lookup(bgp
, &su
);
9712 json_object
*json_no
= NULL
;
9713 json_no
= json_object_new_object();
9714 json_object_string_add(json_no
, "warning",
9715 "No such neighbor in this view/vrf");
9716 vty_out(vty
, "%s\n",
9717 json_object_to_json_string_ext(
9718 json_no
, JSON_C_TO_STRING_PRETTY
));
9719 json_object_free(json_no
);
9721 vty_out(vty
, "No such neighbor in this view/vrf\n");
9729 BGP_STATS_MAXBITLEN
= 0,
9733 BGP_STATS_UNAGGREGATEABLE
,
9734 BGP_STATS_MAX_AGGREGATEABLE
,
9735 BGP_STATS_AGGREGATES
,
9737 BGP_STATS_ASPATH_COUNT
,
9738 BGP_STATS_ASPATH_MAXHOPS
,
9739 BGP_STATS_ASPATH_TOTHOPS
,
9740 BGP_STATS_ASPATH_MAXSIZE
,
9741 BGP_STATS_ASPATH_TOTSIZE
,
9742 BGP_STATS_ASN_HIGHEST
,
9746 static const char *table_stats_strs
[] = {
9747 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9748 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9749 [BGP_STATS_RIB
] = "Total Advertisements",
9750 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9751 [BGP_STATS_MAX_AGGREGATEABLE
] =
9752 "Maximum aggregateable prefixes",
9753 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9754 [BGP_STATS_SPACE
] = "Address space advertised",
9755 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9756 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9757 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9758 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9759 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9760 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9761 [BGP_STATS_MAX
] = NULL
,
9764 struct bgp_table_stats
{
9765 struct bgp_table
*table
;
9766 unsigned long long counts
[BGP_STATS_MAX
];
9771 #define TALLY_SIGFIG 100000
9772 static unsigned long
9773 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9775 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9776 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9777 unsigned long ret
= newtot
/ count
;
9779 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9786 static int bgp_table_stats_walker(struct thread
*t
)
9788 struct bgp_node
*rn
;
9789 struct bgp_node
*top
;
9790 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9791 unsigned int space
= 0;
9793 if (!(top
= bgp_table_top(ts
->table
)))
9796 switch (top
->p
.family
) {
9798 space
= IPV4_MAX_BITLEN
;
9801 space
= IPV6_MAX_BITLEN
;
9805 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9807 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9808 struct bgp_path_info
*pi
;
9809 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9810 unsigned int pinum
= 0;
9818 ts
->counts
[BGP_STATS_PREFIXES
]++;
9819 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9822 ts
->counts
[BGP_STATS_AVGPLEN
]
9823 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9824 ts
->counts
[BGP_STATS_AVGPLEN
],
9828 /* check if the prefix is included by any other announcements */
9829 while (prn
&& !prn
->info
)
9830 prn
= bgp_node_parent_nolock(prn
);
9832 if (prn
== NULL
|| prn
== top
) {
9833 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9834 /* announced address space */
9837 pow(2.0, space
- rn
->p
.prefixlen
);
9838 } else if (prn
->info
)
9839 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9841 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
9843 ts
->counts
[BGP_STATS_RIB
]++;
9846 && (CHECK_FLAG(pi
->attr
->flag
,
9848 BGP_ATTR_ATOMIC_AGGREGATE
))))
9849 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9852 if (pi
->attr
&& pi
->attr
->aspath
) {
9854 aspath_count_hops(pi
->attr
->aspath
);
9856 aspath_size(pi
->attr
->aspath
);
9857 as_t highest
= aspath_highest(pi
->attr
->aspath
);
9859 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9861 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9862 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9865 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9866 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9869 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9870 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9872 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9873 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9874 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9876 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9877 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9878 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9881 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9882 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9890 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9893 struct bgp_table_stats ts
;
9896 if (!bgp
->rib
[afi
][safi
]) {
9897 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9902 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9904 /* labeled-unicast routes live in the unicast table */
9905 if (safi
== SAFI_LABELED_UNICAST
)
9906 safi
= SAFI_UNICAST
;
9908 memset(&ts
, 0, sizeof(ts
));
9909 ts
.table
= bgp
->rib
[afi
][safi
];
9910 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9912 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9913 if (!table_stats_strs
[i
])
9918 case BGP_STATS_ASPATH_AVGHOPS
:
9919 case BGP_STATS_ASPATH_AVGSIZE
:
9920 case BGP_STATS_AVGPLEN
:
9921 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9922 vty_out (vty
, "%12.2f",
9923 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9926 case BGP_STATS_ASPATH_TOTHOPS
:
9927 case BGP_STATS_ASPATH_TOTSIZE
:
9928 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9929 vty_out(vty
, "%12.2f",
9931 ? (float)ts
.counts
[i
]
9933 [BGP_STATS_ASPATH_COUNT
]
9936 case BGP_STATS_TOTPLEN
:
9937 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9938 vty_out(vty
, "%12.2f",
9940 ? (float)ts
.counts
[i
]
9942 [BGP_STATS_PREFIXES
]
9945 case BGP_STATS_SPACE
:
9946 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9947 vty_out(vty
, "%12g\n", ts
.total_space
);
9949 if (afi
== AFI_IP6
) {
9950 vty_out(vty
, "%30s: ", "/32 equivalent ");
9951 vty_out(vty
, "%12g\n",
9952 ts
.total_space
* pow(2.0, -128 + 32));
9953 vty_out(vty
, "%30s: ", "/48 equivalent ");
9954 vty_out(vty
, "%12g\n",
9955 ts
.total_space
* pow(2.0, -128 + 48));
9957 vty_out(vty
, "%30s: ", "% announced ");
9958 vty_out(vty
, "%12.2f\n",
9959 ts
.total_space
* 100. * pow(2.0, -32));
9960 vty_out(vty
, "%30s: ", "/8 equivalent ");
9961 vty_out(vty
, "%12.2f\n",
9962 ts
.total_space
* pow(2.0, -32 + 8));
9963 vty_out(vty
, "%30s: ", "/24 equivalent ");
9964 vty_out(vty
, "%12.2f\n",
9965 ts
.total_space
* pow(2.0, -32 + 24));
9969 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9970 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9987 PCOUNT_PFCNT
, /* the figure we display to users */
9991 static const char *pcount_strs
[] = {
9992 [PCOUNT_ADJ_IN
] = "Adj-in",
9993 [PCOUNT_DAMPED
] = "Damped",
9994 [PCOUNT_REMOVED
] = "Removed",
9995 [PCOUNT_HISTORY
] = "History",
9996 [PCOUNT_STALE
] = "Stale",
9997 [PCOUNT_VALID
] = "Valid",
9998 [PCOUNT_ALL
] = "All RIB",
9999 [PCOUNT_COUNTED
] = "PfxCt counted",
10000 [PCOUNT_PFCNT
] = "Useable",
10001 [PCOUNT_MAX
] = NULL
,
10004 struct peer_pcounts
{
10005 unsigned int count
[PCOUNT_MAX
];
10006 const struct peer
*peer
;
10007 const struct bgp_table
*table
;
10010 static int bgp_peer_count_walker(struct thread
*t
)
10012 struct bgp_node
*rn
;
10013 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10014 const struct peer
*peer
= pc
->peer
;
10016 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10017 struct bgp_adj_in
*ain
;
10018 struct bgp_path_info
*pi
;
10020 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10021 if (ain
->peer
== peer
)
10022 pc
->count
[PCOUNT_ADJ_IN
]++;
10024 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
10025 if (pi
->peer
!= peer
)
10028 pc
->count
[PCOUNT_ALL
]++;
10030 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10031 pc
->count
[PCOUNT_DAMPED
]++;
10032 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10033 pc
->count
[PCOUNT_HISTORY
]++;
10034 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10035 pc
->count
[PCOUNT_REMOVED
]++;
10036 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10037 pc
->count
[PCOUNT_STALE
]++;
10038 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10039 pc
->count
[PCOUNT_VALID
]++;
10040 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10041 pc
->count
[PCOUNT_PFCNT
]++;
10043 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10044 pc
->count
[PCOUNT_COUNTED
]++;
10045 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10047 EC_LIB_DEVELOPMENT
,
10048 "Attempting to count but flags say it is unusable");
10050 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10052 EC_LIB_DEVELOPMENT
,
10053 "Not counted but flags say we should");
10060 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10061 safi_t safi
, bool use_json
)
10063 struct peer_pcounts pcounts
= {.peer
= peer
};
10065 json_object
*json
= NULL
;
10066 json_object
*json_loop
= NULL
;
10069 json
= json_object_new_object();
10070 json_loop
= json_object_new_object();
10073 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10074 || !peer
->bgp
->rib
[afi
][safi
]) {
10076 json_object_string_add(
10078 "No such neighbor or address family");
10079 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10080 json_object_free(json
);
10082 vty_out(vty
, "%% No such neighbor or address family\n");
10084 return CMD_WARNING
;
10087 memset(&pcounts
, 0, sizeof(pcounts
));
10088 pcounts
.peer
= peer
;
10089 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10091 /* in-place call via thread subsystem so as to record execution time
10092 * stats for the thread-walk (i.e. ensure this can't be blamed on
10093 * on just vty_read()).
10095 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10098 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10099 json_object_string_add(json
, "multiProtocol",
10100 afi_safi_print(afi
, safi
));
10101 json_object_int_add(json
, "pfxCounter",
10102 peer
->pcount
[afi
][safi
]);
10104 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10105 json_object_int_add(json_loop
, pcount_strs
[i
],
10108 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10110 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10111 json_object_string_add(json
, "pfxctDriftFor",
10113 json_object_string_add(
10114 json
, "recommended",
10115 "Please report this bug, with the above command output");
10117 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10118 json
, JSON_C_TO_STRING_PRETTY
));
10119 json_object_free(json
);
10123 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10124 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10125 peer
->hostname
, peer
->host
,
10126 afi_safi_print(afi
, safi
));
10128 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10129 afi_safi_print(afi
, safi
));
10132 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10133 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10135 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10136 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10139 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10140 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10142 "Please report this bug, with the above command output\n");
10146 return CMD_SUCCESS
;
10149 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10150 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10151 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10152 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10156 BGP_INSTANCE_HELP_STR
10159 "Detailed information on TCP and BGP neighbor connections\n"
10160 "Neighbor to display information about\n"
10161 "Neighbor to display information about\n"
10162 "Neighbor on BGP configured interface\n"
10163 "Display detailed prefix count information\n"
10166 afi_t afi
= AFI_IP6
;
10167 safi_t safi
= SAFI_UNICAST
;
10170 struct bgp
*bgp
= NULL
;
10171 bool uj
= use_json(argc
, argv
);
10176 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10179 return CMD_WARNING
;
10181 argv_find(argv
, argc
, "neighbors", &idx
);
10182 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10184 return CMD_WARNING
;
10186 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10189 #ifdef KEEP_OLD_VPN_COMMANDS
10190 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10191 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10192 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10197 "Display information about all VPNv4 NLRIs\n"
10198 "Detailed information on TCP and BGP neighbor connections\n"
10199 "Neighbor to display information about\n"
10200 "Neighbor to display information about\n"
10201 "Neighbor on BGP configured interface\n"
10202 "Display detailed prefix count information\n"
10207 bool uj
= use_json(argc
, argv
);
10209 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10211 return CMD_WARNING
;
10213 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10216 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10217 show_ip_bgp_vpn_all_route_prefix_cmd
,
10218 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10223 "Display information about all VPNv4 NLRIs\n"
10224 "Network in the BGP routing table to display\n"
10225 "Network in the BGP routing table to display\n"
10229 char *network
= NULL
;
10230 struct bgp
*bgp
= bgp_get_default();
10232 vty_out(vty
, "Can't find default instance\n");
10233 return CMD_WARNING
;
10236 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10237 network
= argv
[idx
]->arg
;
10238 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10239 network
= argv
[idx
]->arg
;
10241 vty_out(vty
, "Unable to figure out Network\n");
10242 return CMD_WARNING
;
10245 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10246 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10248 #endif /* KEEP_OLD_VPN_COMMANDS */
10250 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10251 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10252 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10258 "Display information about all EVPN NLRIs\n"
10259 "Network in the BGP routing table to display\n"
10260 "Network in the BGP routing table to display\n"
10264 char *network
= NULL
;
10266 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10267 network
= argv
[idx
]->arg
;
10268 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10269 network
= argv
[idx
]->arg
;
10271 vty_out(vty
, "Unable to figure out Network\n");
10272 return CMD_WARNING
;
10274 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10275 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10278 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10279 safi_t safi
, enum bgp_show_adj_route_type type
,
10280 const char *rmap_name
, bool use_json
,
10283 struct bgp_table
*table
;
10284 struct bgp_adj_in
*ain
;
10285 struct bgp_adj_out
*adj
;
10286 unsigned long output_count
;
10287 unsigned long filtered_count
;
10288 struct bgp_node
*rn
;
10294 struct update_subgroup
*subgrp
;
10295 json_object
*json_scode
= NULL
;
10296 json_object
*json_ocode
= NULL
;
10297 json_object
*json_ar
= NULL
;
10298 struct peer_af
*paf
;
10299 bool route_filtered
;
10302 json_scode
= json_object_new_object();
10303 json_ocode
= json_object_new_object();
10304 json_ar
= json_object_new_object();
10306 json_object_string_add(json_scode
, "suppressed", "s");
10307 json_object_string_add(json_scode
, "damped", "d");
10308 json_object_string_add(json_scode
, "history", "h");
10309 json_object_string_add(json_scode
, "valid", "*");
10310 json_object_string_add(json_scode
, "best", ">");
10311 json_object_string_add(json_scode
, "multipath", "=");
10312 json_object_string_add(json_scode
, "internal", "i");
10313 json_object_string_add(json_scode
, "ribFailure", "r");
10314 json_object_string_add(json_scode
, "stale", "S");
10315 json_object_string_add(json_scode
, "removed", "R");
10317 json_object_string_add(json_ocode
, "igp", "i");
10318 json_object_string_add(json_ocode
, "egp", "e");
10319 json_object_string_add(json_ocode
, "incomplete", "?");
10326 json_object_string_add(json
, "alert", "no BGP");
10327 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10328 json_object_free(json
);
10330 vty_out(vty
, "%% No bgp\n");
10334 table
= bgp
->rib
[afi
][safi
];
10336 output_count
= filtered_count
= 0;
10337 subgrp
= peer_subgroup(peer
, afi
, safi
);
10339 if (type
== bgp_show_adj_route_advertised
&& subgrp
10340 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10342 json_object_int_add(json
, "bgpTableVersion",
10344 json_object_string_add(json
, "bgpLocalRouterId",
10345 inet_ntoa(bgp
->router_id
));
10346 json_object_object_add(json
, "bgpStatusCodes",
10348 json_object_object_add(json
, "bgpOriginCodes",
10350 json_object_string_add(
10351 json
, "bgpOriginatingDefaultNetwork",
10352 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10354 vty_out(vty
, "BGP table version is %" PRIu64
10355 ", local router ID is %s, vrf id ",
10356 table
->version
, inet_ntoa(bgp
->router_id
));
10357 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10358 vty_out(vty
, "%s", VRFID_NONE_STR
);
10360 vty_out(vty
, "%u", bgp
->vrf_id
);
10361 vty_out(vty
, "\n");
10362 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10363 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10364 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10366 vty_out(vty
, "Originating default network %s\n\n",
10367 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10372 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10373 if (type
== bgp_show_adj_route_received
10374 || type
== bgp_show_adj_route_filtered
) {
10375 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10376 if (ain
->peer
!= peer
|| !ain
->attr
)
10381 json_object_int_add(
10382 json
, "bgpTableVersion",
10384 json_object_string_add(
10386 "bgpLocalRouterId",
10389 json_object_object_add(
10390 json
, "bgpStatusCodes",
10392 json_object_object_add(
10393 json
, "bgpOriginCodes",
10397 "BGP table version is 0, local router ID is %s, vrf id ",
10400 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10406 vty_out(vty
, "\n");
10408 BGP_SHOW_SCODE_HEADER
);
10410 BGP_SHOW_NCODE_HEADER
);
10412 BGP_SHOW_OCODE_HEADER
);
10418 vty_out(vty
, BGP_SHOW_HEADER
);
10422 bgp_attr_dup(&attr
, ain
->attr
);
10423 route_filtered
= false;
10425 /* Filter prefix using distribute list,
10426 * filter list or prefix list
10428 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10429 safi
)) == FILTER_DENY
)
10430 route_filtered
= true;
10432 /* Filter prefix using route-map */
10433 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10434 afi
, safi
, rmap_name
);
10436 if (type
== bgp_show_adj_route_filtered
&&
10437 !route_filtered
&& ret
!= RMAP_DENY
) {
10438 bgp_attr_undup(&attr
, ain
->attr
);
10442 if (type
== bgp_show_adj_route_received
&&
10443 (route_filtered
|| ret
== RMAP_DENY
))
10446 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10447 use_json
, json_ar
);
10448 bgp_attr_undup(&attr
, ain
->attr
);
10451 } else if (type
== bgp_show_adj_route_advertised
) {
10452 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10453 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10454 if (paf
->peer
!= peer
|| !adj
->attr
)
10459 json_object_int_add(
10463 json_object_string_add(
10465 "bgpLocalRouterId",
10468 json_object_object_add(
10472 json_object_object_add(
10478 "BGP table version is %" PRIu64
10479 ", local router ID is %s, vrf id ",
10492 vty_out(vty
, "\n");
10494 BGP_SHOW_SCODE_HEADER
);
10496 BGP_SHOW_NCODE_HEADER
);
10498 BGP_SHOW_OCODE_HEADER
);
10509 bgp_attr_dup(&attr
, adj
->attr
);
10510 ret
= bgp_output_modifier(
10511 peer
, &rn
->p
, &attr
, afi
, safi
,
10514 if (ret
!= RMAP_DENY
) {
10515 route_vty_out_tmp(vty
, &rn
->p
,
10524 bgp_attr_undup(&attr
, adj
->attr
);
10530 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10531 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10532 json_object_int_add(json
, "filteredPrefixCounter",
10535 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10536 json
, JSON_C_TO_STRING_PRETTY
));
10537 json_object_free(json
);
10538 } else if (output_count
> 0) {
10539 if (filtered_count
> 0)
10541 "\nTotal number of prefixes %ld (%ld filtered)\n",
10542 output_count
, filtered_count
);
10544 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10549 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10550 safi_t safi
, enum bgp_show_adj_route_type type
,
10551 const char *rmap_name
, bool use_json
)
10553 json_object
*json
= NULL
;
10556 json
= json_object_new_object();
10558 /* labeled-unicast routes live in the unicast table */
10559 if (safi
== SAFI_LABELED_UNICAST
)
10560 safi
= SAFI_UNICAST
;
10562 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10564 json_object_string_add(
10566 "No such neighbor or address family");
10567 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10568 json_object_free(json
);
10570 vty_out(vty
, "%% No such neighbor or address family\n");
10572 return CMD_WARNING
;
10575 if ((type
== bgp_show_adj_route_received
10576 || type
== bgp_show_adj_route_filtered
)
10577 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10578 PEER_FLAG_SOFT_RECONFIG
)) {
10580 json_object_string_add(
10582 "Inbound soft reconfiguration not enabled");
10583 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10584 json_object_free(json
);
10587 "%% Inbound soft reconfiguration not enabled\n");
10589 return CMD_WARNING
;
10592 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10594 return CMD_SUCCESS
;
10597 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10598 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10599 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10600 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10604 BGP_INSTANCE_HELP_STR
10606 BGP_SAFI_WITH_LABEL_HELP_STR
10607 "Detailed information on TCP and BGP neighbor connections\n"
10608 "Neighbor to display information about\n"
10609 "Neighbor to display information about\n"
10610 "Neighbor on BGP configured interface\n"
10611 "Display the routes advertised to a BGP neighbor\n"
10612 "Display the received routes from neighbor\n"
10613 "Display the filtered routes received from neighbor\n"
10614 "Route-map to modify the attributes\n"
10615 "Name of the route map\n"
10618 afi_t afi
= AFI_IP6
;
10619 safi_t safi
= SAFI_UNICAST
;
10620 char *rmap_name
= NULL
;
10621 char *peerstr
= NULL
;
10622 struct bgp
*bgp
= NULL
;
10624 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10626 bool uj
= use_json(argc
, argv
);
10631 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10634 return CMD_WARNING
;
10636 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10637 argv_find(argv
, argc
, "neighbors", &idx
);
10638 peerstr
= argv
[++idx
]->arg
;
10640 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10642 return CMD_WARNING
;
10644 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10645 type
= bgp_show_adj_route_advertised
;
10646 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10647 type
= bgp_show_adj_route_received
;
10648 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10649 type
= bgp_show_adj_route_filtered
;
10651 if (argv_find(argv
, argc
, "route-map", &idx
))
10652 rmap_name
= argv
[++idx
]->arg
;
10654 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10657 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10658 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10659 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10665 "Address Family modifier\n"
10666 "Detailed information on TCP and BGP neighbor connections\n"
10667 "Neighbor to display information about\n"
10668 "Neighbor to display information about\n"
10669 "Neighbor on BGP configured interface\n"
10670 "Display information received from a BGP neighbor\n"
10671 "Display the prefixlist filter\n"
10674 afi_t afi
= AFI_IP6
;
10675 safi_t safi
= SAFI_UNICAST
;
10676 char *peerstr
= NULL
;
10679 union sockunion su
;
10685 /* show [ip] bgp */
10686 if (argv_find(argv
, argc
, "ip", &idx
))
10688 /* [<ipv4|ipv6> [unicast]] */
10689 if (argv_find(argv
, argc
, "ipv4", &idx
))
10691 if (argv_find(argv
, argc
, "ipv6", &idx
))
10693 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10694 argv_find(argv
, argc
, "neighbors", &idx
);
10695 peerstr
= argv
[++idx
]->arg
;
10697 bool uj
= use_json(argc
, argv
);
10699 ret
= str2sockunion(peerstr
, &su
);
10701 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10704 vty_out(vty
, "{}\n");
10707 "%% Malformed address or name: %s\n",
10709 return CMD_WARNING
;
10712 peer
= peer_lookup(NULL
, &su
);
10715 vty_out(vty
, "{}\n");
10717 vty_out(vty
, "No peer\n");
10718 return CMD_WARNING
;
10722 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10723 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10726 vty_out(vty
, "Address Family: %s\n",
10727 afi_safi_print(afi
, safi
));
10728 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10731 vty_out(vty
, "{}\n");
10733 vty_out(vty
, "No functional output\n");
10736 return CMD_SUCCESS
;
10739 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10740 afi_t afi
, safi_t safi
,
10741 enum bgp_show_type type
, bool use_json
)
10743 /* labeled-unicast routes live in the unicast table */
10744 if (safi
== SAFI_LABELED_UNICAST
)
10745 safi
= SAFI_UNICAST
;
10747 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10749 json_object
*json_no
= NULL
;
10750 json_no
= json_object_new_object();
10751 json_object_string_add(
10752 json_no
, "warning",
10753 "No such neighbor or address family");
10754 vty_out(vty
, "%s\n",
10755 json_object_to_json_string(json_no
));
10756 json_object_free(json_no
);
10758 vty_out(vty
, "%% No such neighbor or address family\n");
10759 return CMD_WARNING
;
10762 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10765 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10766 show_ip_bgp_flowspec_routes_detailed_cmd
,
10767 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10771 BGP_INSTANCE_HELP_STR
10774 "Detailed information on flowspec entries\n"
10777 afi_t afi
= AFI_IP
;
10778 safi_t safi
= SAFI_UNICAST
;
10779 struct bgp
*bgp
= NULL
;
10781 bool uj
= use_json(argc
, argv
);
10786 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10789 return CMD_WARNING
;
10791 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
10794 DEFUN (show_ip_bgp_neighbor_routes
,
10795 show_ip_bgp_neighbor_routes_cmd
,
10796 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10797 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10801 BGP_INSTANCE_HELP_STR
10803 BGP_SAFI_WITH_LABEL_HELP_STR
10804 "Detailed information on TCP and BGP neighbor connections\n"
10805 "Neighbor to display information about\n"
10806 "Neighbor to display information about\n"
10807 "Neighbor on BGP configured interface\n"
10808 "Display flap statistics of the routes learned from neighbor\n"
10809 "Display the dampened routes received from neighbor\n"
10810 "Display routes learned from neighbor\n"
10813 char *peerstr
= NULL
;
10814 struct bgp
*bgp
= NULL
;
10815 afi_t afi
= AFI_IP6
;
10816 safi_t safi
= SAFI_UNICAST
;
10818 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10820 bool uj
= use_json(argc
, argv
);
10825 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10828 return CMD_WARNING
;
10830 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10831 argv_find(argv
, argc
, "neighbors", &idx
);
10832 peerstr
= argv
[++idx
]->arg
;
10834 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10836 return CMD_WARNING
;
10838 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10839 sh_type
= bgp_show_type_flap_neighbor
;
10840 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10841 sh_type
= bgp_show_type_damp_neighbor
;
10842 else if (argv_find(argv
, argc
, "routes", &idx
))
10843 sh_type
= bgp_show_type_neighbor
;
10845 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10848 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10850 struct bgp_distance
{
10851 /* Distance value for the IP source prefix. */
10854 /* Name of the access-list to be matched. */
10858 DEFUN (show_bgp_afi_vpn_rd_route
,
10859 show_bgp_afi_vpn_rd_route_cmd
,
10860 "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]",
10864 "Address Family modifier\n"
10865 "Display information for a route distinguisher\n"
10866 "Route Distinguisher\n"
10867 "Network in the BGP routing table to display\n"
10868 "Network in the BGP routing table to display\n"
10872 struct prefix_rd prd
;
10873 afi_t afi
= AFI_MAX
;
10876 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10877 vty_out(vty
, "%% Malformed Address Family\n");
10878 return CMD_WARNING
;
10881 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10883 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10884 return CMD_WARNING
;
10887 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10888 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10891 static struct bgp_distance
*bgp_distance_new(void)
10893 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10896 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10898 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10901 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10902 const char *ip_str
, const char *access_list_str
)
10909 struct bgp_node
*rn
;
10910 struct bgp_distance
*bdistance
;
10912 afi
= bgp_node_afi(vty
);
10913 safi
= bgp_node_safi(vty
);
10915 ret
= str2prefix(ip_str
, &p
);
10917 vty_out(vty
, "Malformed prefix\n");
10918 return CMD_WARNING_CONFIG_FAILED
;
10921 distance
= atoi(distance_str
);
10923 /* Get BGP distance node. */
10924 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10925 bdistance
= bgp_distance_get_node(rn
);
10927 bgp_unlock_node(rn
);
10929 bdistance
= bgp_distance_new();
10930 bgp_distance_set_node_info(rn
, bdistance
);
10933 /* Set distance value. */
10934 bdistance
->distance
= distance
;
10936 /* Reset access-list configuration. */
10937 if (bdistance
->access_list
) {
10938 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10939 bdistance
->access_list
= NULL
;
10941 if (access_list_str
)
10942 bdistance
->access_list
=
10943 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10945 return CMD_SUCCESS
;
10948 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10949 const char *ip_str
, const char *access_list_str
)
10956 struct bgp_node
*rn
;
10957 struct bgp_distance
*bdistance
;
10959 afi
= bgp_node_afi(vty
);
10960 safi
= bgp_node_safi(vty
);
10962 ret
= str2prefix(ip_str
, &p
);
10964 vty_out(vty
, "Malformed prefix\n");
10965 return CMD_WARNING_CONFIG_FAILED
;
10968 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10969 (struct prefix
*)&p
);
10971 vty_out(vty
, "Can't find specified prefix\n");
10972 return CMD_WARNING_CONFIG_FAILED
;
10975 bdistance
= bgp_distance_get_node(rn
);
10976 distance
= atoi(distance_str
);
10978 if (bdistance
->distance
!= distance
) {
10979 vty_out(vty
, "Distance does not match configured\n");
10980 return CMD_WARNING_CONFIG_FAILED
;
10983 if (bdistance
->access_list
)
10984 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10985 bgp_distance_free(bdistance
);
10988 bgp_unlock_node(rn
);
10989 bgp_unlock_node(rn
);
10991 return CMD_SUCCESS
;
10994 /* Apply BGP information to distance method. */
10995 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
10996 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
10998 struct bgp_node
*rn
;
11001 struct bgp_distance
*bdistance
;
11002 struct access_list
*alist
;
11003 struct bgp_static
*bgp_static
;
11008 peer
= pinfo
->peer
;
11010 /* Check source address. */
11011 sockunion2hostprefix(&peer
->su
, &q
);
11012 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11014 bdistance
= bgp_distance_get_node(rn
);
11015 bgp_unlock_node(rn
);
11017 if (bdistance
->access_list
) {
11018 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11020 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11021 return bdistance
->distance
;
11023 return bdistance
->distance
;
11026 /* Backdoor check. */
11027 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11029 bgp_static
= bgp_static_get_node_info(rn
);
11030 bgp_unlock_node(rn
);
11032 if (bgp_static
->backdoor
) {
11033 if (bgp
->distance_local
[afi
][safi
])
11034 return bgp
->distance_local
[afi
][safi
];
11036 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11040 if (peer
->sort
== BGP_PEER_EBGP
) {
11041 if (bgp
->distance_ebgp
[afi
][safi
])
11042 return bgp
->distance_ebgp
[afi
][safi
];
11043 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11045 if (bgp
->distance_ibgp
[afi
][safi
])
11046 return bgp
->distance_ibgp
[afi
][safi
];
11047 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11051 DEFUN (bgp_distance
,
11053 "distance bgp (1-255) (1-255) (1-255)",
11054 "Define an administrative distance\n"
11056 "Distance for routes external to the AS\n"
11057 "Distance for routes internal to the AS\n"
11058 "Distance for local routes\n")
11060 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11061 int idx_number
= 2;
11062 int idx_number_2
= 3;
11063 int idx_number_3
= 4;
11067 afi
= bgp_node_afi(vty
);
11068 safi
= bgp_node_safi(vty
);
11070 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11071 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11072 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11073 return CMD_SUCCESS
;
11076 DEFUN (no_bgp_distance
,
11077 no_bgp_distance_cmd
,
11078 "no distance bgp [(1-255) (1-255) (1-255)]",
11080 "Define an administrative distance\n"
11082 "Distance for routes external to the AS\n"
11083 "Distance for routes internal to the AS\n"
11084 "Distance for local routes\n")
11086 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11090 afi
= bgp_node_afi(vty
);
11091 safi
= bgp_node_safi(vty
);
11093 bgp
->distance_ebgp
[afi
][safi
] = 0;
11094 bgp
->distance_ibgp
[afi
][safi
] = 0;
11095 bgp
->distance_local
[afi
][safi
] = 0;
11096 return CMD_SUCCESS
;
11100 DEFUN (bgp_distance_source
,
11101 bgp_distance_source_cmd
,
11102 "distance (1-255) A.B.C.D/M",
11103 "Define an administrative distance\n"
11104 "Administrative distance\n"
11105 "IP source prefix\n")
11107 int idx_number
= 1;
11108 int idx_ipv4_prefixlen
= 2;
11109 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11110 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11111 return CMD_SUCCESS
;
11114 DEFUN (no_bgp_distance_source
,
11115 no_bgp_distance_source_cmd
,
11116 "no distance (1-255) A.B.C.D/M",
11118 "Define an administrative distance\n"
11119 "Administrative distance\n"
11120 "IP source prefix\n")
11122 int idx_number
= 2;
11123 int idx_ipv4_prefixlen
= 3;
11124 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11125 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11126 return CMD_SUCCESS
;
11129 DEFUN (bgp_distance_source_access_list
,
11130 bgp_distance_source_access_list_cmd
,
11131 "distance (1-255) A.B.C.D/M WORD",
11132 "Define an administrative distance\n"
11133 "Administrative distance\n"
11134 "IP source prefix\n"
11135 "Access list name\n")
11137 int idx_number
= 1;
11138 int idx_ipv4_prefixlen
= 2;
11140 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11141 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11142 return CMD_SUCCESS
;
11145 DEFUN (no_bgp_distance_source_access_list
,
11146 no_bgp_distance_source_access_list_cmd
,
11147 "no distance (1-255) A.B.C.D/M WORD",
11149 "Define an administrative distance\n"
11150 "Administrative distance\n"
11151 "IP source prefix\n"
11152 "Access list name\n")
11154 int idx_number
= 2;
11155 int idx_ipv4_prefixlen
= 3;
11157 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11158 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11159 return CMD_SUCCESS
;
11162 DEFUN (ipv6_bgp_distance_source
,
11163 ipv6_bgp_distance_source_cmd
,
11164 "distance (1-255) X:X::X:X/M",
11165 "Define an administrative distance\n"
11166 "Administrative distance\n"
11167 "IP source prefix\n")
11169 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11170 return CMD_SUCCESS
;
11173 DEFUN (no_ipv6_bgp_distance_source
,
11174 no_ipv6_bgp_distance_source_cmd
,
11175 "no distance (1-255) X:X::X:X/M",
11177 "Define an administrative distance\n"
11178 "Administrative distance\n"
11179 "IP source prefix\n")
11181 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11182 return CMD_SUCCESS
;
11185 DEFUN (ipv6_bgp_distance_source_access_list
,
11186 ipv6_bgp_distance_source_access_list_cmd
,
11187 "distance (1-255) X:X::X:X/M WORD",
11188 "Define an administrative distance\n"
11189 "Administrative distance\n"
11190 "IP source prefix\n"
11191 "Access list name\n")
11193 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11194 return CMD_SUCCESS
;
11197 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11198 no_ipv6_bgp_distance_source_access_list_cmd
,
11199 "no distance (1-255) X:X::X:X/M WORD",
11201 "Define an administrative distance\n"
11202 "Administrative distance\n"
11203 "IP source prefix\n"
11204 "Access list name\n")
11206 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11207 return CMD_SUCCESS
;
11210 DEFUN (bgp_damp_set
,
11212 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11213 "BGP Specific commands\n"
11214 "Enable route-flap dampening\n"
11215 "Half-life time for the penalty\n"
11216 "Value to start reusing a route\n"
11217 "Value to start suppressing a route\n"
11218 "Maximum duration to suppress a stable route\n")
11220 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11221 int idx_half_life
= 2;
11223 int idx_suppress
= 4;
11224 int idx_max_suppress
= 5;
11225 int half
= DEFAULT_HALF_LIFE
* 60;
11226 int reuse
= DEFAULT_REUSE
;
11227 int suppress
= DEFAULT_SUPPRESS
;
11228 int max
= 4 * half
;
11231 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11232 reuse
= atoi(argv
[idx_reuse
]->arg
);
11233 suppress
= atoi(argv
[idx_suppress
]->arg
);
11234 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11235 } else if (argc
== 3) {
11236 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11240 if (suppress
< reuse
) {
11242 "Suppress value cannot be less than reuse value \n");
11246 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11247 reuse
, suppress
, max
);
11250 DEFUN (bgp_damp_unset
,
11251 bgp_damp_unset_cmd
,
11252 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11254 "BGP Specific commands\n"
11255 "Enable route-flap dampening\n"
11256 "Half-life time for the penalty\n"
11257 "Value to start reusing a route\n"
11258 "Value to start suppressing a route\n"
11259 "Maximum duration to suppress a stable route\n")
11261 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11262 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11265 /* Display specified route of BGP table. */
11266 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11267 const char *ip_str
, afi_t afi
, safi_t safi
,
11268 struct prefix_rd
*prd
, int prefix_check
)
11271 struct prefix match
;
11272 struct bgp_node
*rn
;
11273 struct bgp_node
*rm
;
11274 struct bgp_path_info
*pi
;
11275 struct bgp_path_info
*pi_temp
;
11277 struct bgp_table
*table
;
11279 /* BGP structure lookup. */
11281 bgp
= bgp_lookup_by_name(view_name
);
11283 vty_out(vty
, "%% Can't find BGP instance %s\n",
11285 return CMD_WARNING
;
11288 bgp
= bgp_get_default();
11290 vty_out(vty
, "%% No BGP process is configured\n");
11291 return CMD_WARNING
;
11295 /* Check IP address argument. */
11296 ret
= str2prefix(ip_str
, &match
);
11298 vty_out(vty
, "%% address is malformed\n");
11299 return CMD_WARNING
;
11302 match
.family
= afi2family(afi
);
11304 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11305 || (safi
== SAFI_EVPN
)) {
11306 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11307 rn
= bgp_route_next(rn
)) {
11308 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11310 if ((table
= rn
->info
) == NULL
)
11312 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11316 || rm
->p
.prefixlen
== match
.prefixlen
) {
11319 if (pi
->extra
&& pi
->extra
->damp_info
) {
11320 pi_temp
= pi
->next
;
11321 bgp_damp_info_free(
11322 pi
->extra
->damp_info
,
11330 bgp_unlock_node(rm
);
11333 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11336 || rn
->p
.prefixlen
== match
.prefixlen
) {
11339 if (pi
->extra
&& pi
->extra
->damp_info
) {
11340 pi_temp
= pi
->next
;
11341 bgp_damp_info_free(
11342 pi
->extra
->damp_info
,
11350 bgp_unlock_node(rn
);
11354 return CMD_SUCCESS
;
11357 DEFUN (clear_ip_bgp_dampening
,
11358 clear_ip_bgp_dampening_cmd
,
11359 "clear ip bgp dampening",
11363 "Clear route flap dampening information\n")
11365 bgp_damp_info_clean();
11366 return CMD_SUCCESS
;
11369 DEFUN (clear_ip_bgp_dampening_prefix
,
11370 clear_ip_bgp_dampening_prefix_cmd
,
11371 "clear ip bgp dampening A.B.C.D/M",
11375 "Clear route flap dampening information\n"
11378 int idx_ipv4_prefixlen
= 4;
11379 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11380 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11383 DEFUN (clear_ip_bgp_dampening_address
,
11384 clear_ip_bgp_dampening_address_cmd
,
11385 "clear ip bgp dampening A.B.C.D",
11389 "Clear route flap dampening information\n"
11390 "Network to clear damping information\n")
11393 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11394 SAFI_UNICAST
, NULL
, 0);
11397 DEFUN (clear_ip_bgp_dampening_address_mask
,
11398 clear_ip_bgp_dampening_address_mask_cmd
,
11399 "clear ip bgp dampening A.B.C.D A.B.C.D",
11403 "Clear route flap dampening information\n"
11404 "Network to clear damping information\n"
11408 int idx_ipv4_2
= 5;
11410 char prefix_str
[BUFSIZ
];
11412 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11415 vty_out(vty
, "%% Inconsistent address and mask\n");
11416 return CMD_WARNING
;
11419 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11423 static void show_bgp_peerhash_entry(struct hash_backet
*backet
, void *arg
)
11425 struct vty
*vty
= arg
;
11426 struct peer
*peer
= backet
->data
;
11427 char buf
[SU_ADDRSTRLEN
];
11429 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
11430 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
11433 DEFUN (show_bgp_peerhash
,
11434 show_bgp_peerhash_cmd
,
11435 "show bgp peerhash",
11438 "Display information about the BGP peerhash\n")
11440 struct list
*instances
= bm
->bgp
;
11441 struct listnode
*node
;
11444 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
11445 vty_out(vty
, "BGP: %s\n", bgp
->name
);
11446 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
11450 return CMD_SUCCESS
;
11453 /* also used for encap safi */
11454 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11455 afi_t afi
, safi_t safi
)
11457 struct bgp_node
*prn
;
11458 struct bgp_node
*rn
;
11459 struct bgp_table
*table
;
11461 struct prefix_rd
*prd
;
11462 struct bgp_static
*bgp_static
;
11463 mpls_label_t label
;
11464 char buf
[SU_ADDRSTRLEN
];
11465 char rdbuf
[RD_ADDRSTRLEN
];
11467 /* Network configuration. */
11468 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11469 prn
= bgp_route_next(prn
)) {
11470 if ((table
= prn
->info
) == NULL
)
11473 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11474 bgp_static
= bgp_static_get_node_info(rn
);
11475 if (bgp_static
== NULL
)
11479 prd
= (struct prefix_rd
*)&prn
->p
;
11481 /* "network" configuration display. */
11482 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11483 label
= decode_label(&bgp_static
->label
);
11485 vty_out(vty
, " network %s/%d rd %s",
11486 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11488 p
->prefixlen
, rdbuf
);
11489 if (safi
== SAFI_MPLS_VPN
)
11490 vty_out(vty
, " label %u", label
);
11492 if (bgp_static
->rmap
.name
)
11493 vty_out(vty
, " route-map %s",
11494 bgp_static
->rmap
.name
);
11496 if (bgp_static
->backdoor
)
11497 vty_out(vty
, " backdoor");
11499 vty_out(vty
, "\n");
11504 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11505 afi_t afi
, safi_t safi
)
11507 struct bgp_node
*prn
;
11508 struct bgp_node
*rn
;
11509 struct bgp_table
*table
;
11511 struct prefix_rd
*prd
;
11512 struct bgp_static
*bgp_static
;
11513 char buf
[PREFIX_STRLEN
* 2];
11514 char buf2
[SU_ADDRSTRLEN
];
11515 char rdbuf
[RD_ADDRSTRLEN
];
11517 /* Network configuration. */
11518 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11519 prn
= bgp_route_next(prn
)) {
11520 if ((table
= prn
->info
) == NULL
)
11523 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11524 bgp_static
= bgp_static_get_node_info(rn
);
11525 if (bgp_static
== NULL
)
11528 char *macrouter
= NULL
;
11531 if (bgp_static
->router_mac
)
11532 macrouter
= prefix_mac2str(
11533 bgp_static
->router_mac
, NULL
, 0);
11534 if (bgp_static
->eth_s_id
)
11535 esi
= esi2str(bgp_static
->eth_s_id
);
11537 prd
= (struct prefix_rd
*)&prn
->p
;
11539 /* "network" configuration display. */
11540 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11541 if (p
->u
.prefix_evpn
.route_type
== 5) {
11542 char local_buf
[PREFIX_STRLEN
];
11543 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11544 struct prefix_evpn
*)p
)
11548 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11549 local_buf
, PREFIX_STRLEN
);
11550 sprintf(buf
, "%s/%u", local_buf
,
11551 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11553 prefix2str(p
, buf
, sizeof(buf
));
11556 if (bgp_static
->gatewayIp
.family
== AF_INET
11557 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11558 inet_ntop(bgp_static
->gatewayIp
.family
,
11559 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11562 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11564 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11565 decode_label(&bgp_static
->label
), esi
, buf2
,
11569 XFREE(MTYPE_TMP
, macrouter
);
11571 XFREE(MTYPE_TMP
, esi
);
11576 /* Configuration of static route announcement and aggregate
11578 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11581 struct bgp_node
*rn
;
11583 struct bgp_static
*bgp_static
;
11584 struct bgp_aggregate
*bgp_aggregate
;
11585 char buf
[SU_ADDRSTRLEN
];
11587 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11588 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11592 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11593 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11597 /* Network configuration. */
11598 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11599 rn
= bgp_route_next(rn
)) {
11600 bgp_static
= bgp_static_get_node_info(rn
);
11601 if (bgp_static
== NULL
)
11606 /* "network" configuration display. */
11607 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11608 uint32_t destination
;
11609 struct in_addr netmask
;
11611 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11612 masklen2ip(p
->prefixlen
, &netmask
);
11613 vty_out(vty
, " network %s",
11614 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11617 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11618 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11619 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11620 || p
->u
.prefix4
.s_addr
== 0) {
11621 /* Natural mask is not display. */
11623 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11625 vty_out(vty
, " network %s/%d",
11626 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11631 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11632 vty_out(vty
, " label-index %u",
11633 bgp_static
->label_index
);
11635 if (bgp_static
->rmap
.name
)
11636 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11638 if (bgp_static
->backdoor
)
11639 vty_out(vty
, " backdoor");
11641 vty_out(vty
, "\n");
11644 /* Aggregate-address configuration. */
11645 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11646 rn
= bgp_route_next(rn
)) {
11647 bgp_aggregate
= bgp_aggregate_get_node_info(rn
);
11648 if (bgp_aggregate
== NULL
)
11653 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11654 struct in_addr netmask
;
11656 masklen2ip(p
->prefixlen
, &netmask
);
11657 vty_out(vty
, " aggregate-address %s %s",
11658 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11660 inet_ntoa(netmask
));
11662 vty_out(vty
, " aggregate-address %s/%d",
11663 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11668 if (bgp_aggregate
->as_set
)
11669 vty_out(vty
, " as-set");
11671 if (bgp_aggregate
->summary_only
)
11672 vty_out(vty
, " summary-only");
11674 vty_out(vty
, "\n");
11678 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11681 struct bgp_node
*rn
;
11682 struct bgp_distance
*bdistance
;
11684 /* Distance configuration. */
11685 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11686 && bgp
->distance_local
[afi
][safi
]
11687 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11688 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11689 || bgp
->distance_local
[afi
][safi
]
11690 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11691 vty_out(vty
, " distance bgp %d %d %d\n",
11692 bgp
->distance_ebgp
[afi
][safi
],
11693 bgp
->distance_ibgp
[afi
][safi
],
11694 bgp
->distance_local
[afi
][safi
]);
11697 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11698 rn
= bgp_route_next(rn
)) {
11699 bdistance
= bgp_distance_get_node(rn
);
11700 if (bdistance
!= NULL
) {
11701 char buf
[PREFIX_STRLEN
];
11703 vty_out(vty
, " distance %d %s %s\n",
11704 bdistance
->distance
,
11705 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11706 bdistance
->access_list
? bdistance
->access_list
11712 /* Allocate routing table structure and install commands. */
11713 void bgp_route_init(void)
11718 /* Init BGP distance table. */
11719 FOREACH_AFI_SAFI (afi
, safi
)
11720 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11722 /* IPv4 BGP commands. */
11723 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11724 install_element(BGP_NODE
, &bgp_network_cmd
);
11725 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11727 install_element(BGP_NODE
, &aggregate_address_cmd
);
11728 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11729 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11730 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11732 /* IPv4 unicast configuration. */
11733 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11734 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11735 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11737 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11738 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11739 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11740 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11742 /* IPv4 multicast configuration. */
11743 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11744 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11745 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11746 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11747 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11748 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11749 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11751 /* IPv4 labeled-unicast configuration. */
11752 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11753 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11754 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11755 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11756 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11758 install_element(VIEW_NODE
,
11759 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11760 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11761 install_element(VIEW_NODE
,
11762 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11763 #ifdef KEEP_OLD_VPN_COMMANDS
11764 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11765 #endif /* KEEP_OLD_VPN_COMMANDS */
11766 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11767 install_element(VIEW_NODE
,
11768 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11770 /* BGP dampening clear commands */
11771 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11772 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11774 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11775 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11778 install_element(ENABLE_NODE
,
11779 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11780 #ifdef KEEP_OLD_VPN_COMMANDS
11781 install_element(ENABLE_NODE
,
11782 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11783 #endif /* KEEP_OLD_VPN_COMMANDS */
11785 /* New config IPv6 BGP commands. */
11786 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11787 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11788 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11790 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11791 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11793 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11795 install_element(BGP_NODE
, &bgp_distance_cmd
);
11796 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11797 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11798 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11799 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11800 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11801 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11802 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11803 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11804 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11805 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11806 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11807 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11808 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11809 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11810 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11811 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11812 install_element(BGP_IPV4M_NODE
,
11813 &no_bgp_distance_source_access_list_cmd
);
11814 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11815 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11816 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11817 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11818 install_element(BGP_IPV6_NODE
,
11819 &ipv6_bgp_distance_source_access_list_cmd
);
11820 install_element(BGP_IPV6_NODE
,
11821 &no_ipv6_bgp_distance_source_access_list_cmd
);
11822 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11823 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11824 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11825 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11826 install_element(BGP_IPV6M_NODE
,
11827 &ipv6_bgp_distance_source_access_list_cmd
);
11828 install_element(BGP_IPV6M_NODE
,
11829 &no_ipv6_bgp_distance_source_access_list_cmd
);
11831 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11832 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11833 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11834 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11836 /* IPv4 Multicast Mode */
11837 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11838 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11840 /* Large Communities */
11841 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11842 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11844 /* show bgp ipv4 flowspec detailed */
11845 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11847 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
11850 void bgp_route_finish(void)
11855 FOREACH_AFI_SAFI (afi
, safi
) {
11856 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11857 bgp_distance_table
[afi
][safi
] = NULL
;