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"
42 #include "bgpd/bgpd.h"
43 #include "bgpd/bgp_table.h"
44 #include "bgpd/bgp_route.h"
45 #include "bgpd/bgp_attr.h"
46 #include "bgpd/bgp_debug.h"
47 #include "bgpd/bgp_errors.h"
48 #include "bgpd/bgp_aspath.h"
49 #include "bgpd/bgp_regex.h"
50 #include "bgpd/bgp_community.h"
51 #include "bgpd/bgp_ecommunity.h"
52 #include "bgpd/bgp_lcommunity.h"
53 #include "bgpd/bgp_clist.h"
54 #include "bgpd/bgp_packet.h"
55 #include "bgpd/bgp_filter.h"
56 #include "bgpd/bgp_fsm.h"
57 #include "bgpd/bgp_mplsvpn.h"
58 #include "bgpd/bgp_nexthop.h"
59 #include "bgpd/bgp_damp.h"
60 #include "bgpd/bgp_advertise.h"
61 #include "bgpd/bgp_zebra.h"
62 #include "bgpd/bgp_vty.h"
63 #include "bgpd/bgp_mpath.h"
64 #include "bgpd/bgp_nht.h"
65 #include "bgpd/bgp_updgrp.h"
66 #include "bgpd/bgp_label.h"
69 #include "bgpd/rfapi/rfapi_backend.h"
70 #include "bgpd/rfapi/vnc_import_bgp.h"
71 #include "bgpd/rfapi/vnc_export_bgp.h"
73 #include "bgpd/bgp_encap_types.h"
74 #include "bgpd/bgp_encap_tlv.h"
75 #include "bgpd/bgp_evpn.h"
76 #include "bgpd/bgp_evpn_vty.h"
77 #include "bgpd/bgp_flowspec.h"
78 #include "bgpd/bgp_flowspec_util.h"
79 #include "bgpd/bgp_pbr.h"
81 #ifndef VTYSH_EXTRACT_PL
82 #include "bgpd/bgp_route_clippy.c"
85 /* Extern from bgp_dump.c */
86 extern const char *bgp_origin_str
[];
87 extern const char *bgp_origin_long_str
[];
90 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
91 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
92 static const struct message bgp_pmsi_tnltype_str
[] = {
93 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
94 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
95 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
96 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
97 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
98 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
99 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
100 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
104 #define VRFID_NONE_STR "-"
106 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
107 safi_t safi
, struct prefix
*p
,
108 struct prefix_rd
*prd
)
111 struct bgp_node
*prn
= NULL
;
117 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
118 || (safi
== SAFI_EVPN
)) {
119 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
121 if (prn
->info
== NULL
)
122 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
124 bgp_unlock_node(prn
);
128 rn
= bgp_node_get(table
, p
);
130 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
131 || (safi
== SAFI_EVPN
))
137 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
138 safi_t safi
, struct prefix
*p
,
139 struct prefix_rd
*prd
)
142 struct bgp_node
*prn
= NULL
;
147 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
148 || (safi
== SAFI_EVPN
)) {
149 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
153 if (prn
->info
== NULL
) {
154 bgp_unlock_node(prn
);
161 rn
= bgp_node_lookup(table
, p
);
166 /* Allocate bgp_info_extra */
167 static struct bgp_info_extra
*bgp_info_extra_new(void)
169 struct bgp_info_extra
*new;
170 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
171 new->label
[0] = MPLS_INVALID_LABEL
;
176 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
178 struct bgp_info_extra
*e
;
180 if (!extra
|| !*extra
)
185 bgp_damp_info_free(e
->damp_info
, 0);
189 struct bgp_info
*bi
= (struct bgp_info
*)e
->parent
;
192 /* FIXME: since multiple e may have the same e->parent
193 * and e->parent->net is holding a refcount for each
194 * of them, we need to do some fudging here.
196 * WARNING: if bi->net->lock drops to 0, bi may be
197 * freed as well (because bi->net was holding the
198 * last reference to bi) => write after free!
202 bi
= bgp_info_lock(bi
);
203 refcount
= bi
->net
->lock
- 1;
204 bgp_unlock_node((struct bgp_node
*)bi
->net
);
209 bgp_info_unlock(e
->parent
);
214 bgp_unlock(e
->bgp_orig
);
216 if ((*extra
)->bgp_fs_pbr
)
217 list_delete_and_null(&((*extra
)->bgp_fs_pbr
));
218 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
223 /* Get bgp_info extra information for the given bgp_info, lazy allocated
226 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
229 ri
->extra
= bgp_info_extra_new();
233 /* Allocate new bgp info structure. */
234 struct bgp_info
*bgp_info_new(void)
236 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
239 /* Free bgp route information. */
240 static void bgp_info_free(struct bgp_info
*binfo
)
243 bgp_attr_unintern(&binfo
->attr
);
245 bgp_unlink_nexthop(binfo
);
246 bgp_info_extra_free(&binfo
->extra
);
247 bgp_info_mpath_free(&binfo
->mpath
);
249 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
251 XFREE(MTYPE_BGP_ROUTE
, binfo
);
254 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
260 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
262 assert(binfo
&& binfo
->lock
> 0);
265 if (binfo
->lock
== 0) {
267 zlog_debug ("%s: unlocked and freeing", __func__
);
268 zlog_backtrace (LOG_DEBUG
);
270 bgp_info_free(binfo
);
275 if (binfo
->lock
== 1)
277 zlog_debug ("%s: unlocked to 1", __func__
);
278 zlog_backtrace (LOG_DEBUG
);
285 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
287 struct bgp_info
*top
;
299 peer_lock(ri
->peer
); /* bgp_info peer reference */
302 /* Do the actual removal of info from RIB, for use by bgp_process
303 completion callback *only* */
304 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
307 ri
->next
->prev
= ri
->prev
;
309 ri
->prev
->next
= ri
->next
;
313 bgp_info_mpath_dequeue(ri
);
318 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
320 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
321 /* set of previous already took care of pcount */
322 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
325 /* undo the effects of a previous call to bgp_info_delete; typically
326 called when a route is deleted and then quickly re-added before the
327 deletion has been processed */
328 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
330 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
331 /* unset of previous already took care of pcount */
332 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
335 /* Adjust pcount as required */
336 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
338 struct bgp_table
*table
;
340 assert(rn
&& bgp_node_table(rn
));
341 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
343 table
= bgp_node_table(rn
);
345 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
348 if (!BGP_INFO_COUNTABLE(ri
)
349 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
351 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
353 /* slight hack, but more robust against errors. */
354 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
355 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
358 "%s: Asked to decrement 0 prefix count for peer %s",
359 __func__
, ri
->peer
->host
);
360 zlog_backtrace(LOG_WARNING
);
361 zlog_warn("%s: Please report to Quagga bugzilla",
364 } else if (BGP_INFO_COUNTABLE(ri
)
365 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
366 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
367 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
371 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
373 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
376 /* Set/unset bgp_info flags, adjusting any other state as needed.
377 * This is here primarily to keep prefix-count in check.
379 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, uint32_t flag
)
381 SET_FLAG(ri
->flags
, flag
);
383 /* early bath if we know it's not a flag that changes countability state
385 if (!CHECK_FLAG(flag
,
386 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
389 bgp_pcount_adjust(rn
, ri
);
392 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
395 UNSET_FLAG(ri
->flags
, flag
);
397 /* early bath if we know it's not a flag that changes countability state
399 if (!CHECK_FLAG(flag
,
400 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
403 bgp_pcount_adjust(rn
, ri
);
406 /* Get MED value. If MED value is missing and "bgp bestpath
407 missing-as-worst" is specified, treat it as the worst value. */
408 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
410 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
413 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
420 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
422 if (ri
->addpath_rx_id
)
423 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
426 sprintf(buf
, "path %s", ri
->peer
->host
);
429 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
431 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
432 struct bgp_info
*exist
, int *paths_eq
,
433 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
434 char *pfx_buf
, afi_t afi
, safi_t safi
)
436 struct attr
*newattr
, *existattr
;
437 bgp_peer_sort_t new_sort
;
438 bgp_peer_sort_t exist_sort
;
444 uint32_t exist_weight
;
445 uint32_t newm
, existm
;
446 struct in_addr new_id
;
447 struct in_addr exist_id
;
450 int internal_as_route
;
453 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
454 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
456 uint32_t exist_mm_seq
;
463 zlog_debug("%s: new is NULL", pfx_buf
);
468 bgp_info_path_with_addpath_rx_str(new, new_buf
);
472 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
478 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
479 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
480 pfx_buf
, new_buf
, new->flags
, exist_buf
,
485 existattr
= exist
->attr
;
487 /* For EVPN routes, we cannot just go by local vs remote, we have to
488 * look at the MAC mobility sequence number, if present.
490 if (safi
== SAFI_EVPN
) {
491 /* This is an error condition described in RFC 7432 Section
493 * states that in this scenario "the PE MUST alert the operator"
495 * does not state what other action to take. In order to provide
497 * consistency in this scenario we are going to prefer the path
501 if (newattr
->sticky
!= existattr
->sticky
) {
503 prefix2str(&new->net
->p
, pfx_buf
,
505 * PREFIX2STR_BUFFER
);
506 bgp_info_path_with_addpath_rx_str(new, new_buf
);
507 bgp_info_path_with_addpath_rx_str(exist
,
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_INFO_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_INFO_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_INFO_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_INFO_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_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
1028 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
1033 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
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_warn("%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_warn("%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_info info
;
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(&info
, 0, sizeof(struct bgp_info
));
1198 /* Duplicate current value to new strucutre for modification. */
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
, &info
);
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_info info
;
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(&info
, 0, sizeof(struct bgp_info
));
1247 /* Route map apply. */
1248 /* Duplicate current value to new strucutre for modification. */
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
, &info
);
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_info
*ri
,
1380 struct update_subgroup
*subgrp
, struct prefix
*p
,
1383 struct bgp_filter
*filter
;
1386 struct peer
*onlypeer
;
1388 struct attr
*riattr
;
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 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1413 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1414 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1415 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1418 * direct and direct_ext type routes originate internally even
1419 * though they can have peer pointers that reference other
1422 prefix2str(p
, buf
, PREFIX_STRLEN
);
1423 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1429 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1430 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1431 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1432 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1434 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1439 /* With addpath we may be asked to TX all kinds of paths so make sure
1441 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1442 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1443 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1447 /* If this is not the bestpath then check to see if there is an enabled
1449 * feature that requires us to advertise it */
1450 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1451 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1456 /* Aggregate-address suppress check. */
1457 if (ri
->extra
&& ri
->extra
->suppress
)
1458 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1463 * If we are doing VRF 2 VRF leaking via the import
1464 * statement, we want to prevent the route going
1465 * off box as that the RT and RD created are localy
1466 * significant and globaly useless.
1468 if (safi
== SAFI_MPLS_VPN
&& ri
->extra
&& ri
->extra
->num_labels
1469 && ri
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1472 /* If it's labeled safi, make sure the route has a valid label. */
1473 if (safi
== SAFI_LABELED_UNICAST
) {
1474 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1475 if (!bgp_is_valid_label(&label
)) {
1476 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1477 zlog_debug("u%" PRIu64
":s%" PRIu64
1478 " %s/%d is filtered - no label (%p)",
1479 subgrp
->update_group
->id
, subgrp
->id
,
1480 inet_ntop(p
->family
, &p
->u
.prefix
,
1481 buf
, SU_ADDRSTRLEN
),
1482 p
->prefixlen
, &label
);
1487 /* Do not send back route to sender. */
1488 if (onlypeer
&& from
== onlypeer
) {
1492 /* Do not send the default route in the BGP table if the neighbor is
1493 * configured for default-originate */
1494 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1495 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1496 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1498 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1502 /* Transparency check. */
1503 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1504 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1509 /* If community is not disabled check the no-export and local. */
1510 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1511 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1513 "subgrpannouncecheck: community filter check fail");
1517 /* If the attribute has originator-id and it is same as remote
1519 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1520 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1521 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1523 "%s [Update:SEND] %s originator-id is same as "
1526 prefix2str(p
, buf
, sizeof(buf
)));
1530 /* ORF prefix-list filter check */
1531 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1532 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1533 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1534 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1535 if (peer
->orf_plist
[afi
][safi
]) {
1536 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1538 if (bgp_debug_update(NULL
, p
,
1539 subgrp
->update_group
, 0))
1541 "%s [Update:SEND] %s is filtered via ORF",
1549 /* Output filter check. */
1550 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1551 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1552 zlog_debug("%s [Update:SEND] %s is filtered",
1553 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1557 #ifdef BGP_SEND_ASPATH_CHECK
1558 /* AS path loop check. */
1559 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1560 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1562 "%s [Update:SEND] suppress announcement to peer AS %u "
1563 "that is part of AS path.",
1564 onlypeer
->host
, onlypeer
->as
);
1567 #endif /* BGP_SEND_ASPATH_CHECK */
1569 /* If we're a CONFED we need to loop check the CONFED ID too */
1570 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1571 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1572 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1574 "%s [Update:SEND] suppress announcement to peer AS %u"
1576 peer
->host
, bgp
->confed_id
);
1581 /* Route-Reflect check. */
1582 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1587 /* IBGP reflection check. */
1588 if (reflect
&& !samepeer_safe
) {
1589 /* A route from a Client peer. */
1590 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1591 PEER_FLAG_REFLECTOR_CLIENT
)) {
1592 /* Reflect to all the Non-Client peers and also to the
1593 Client peers other than the originator. Originator
1595 is already done. So there is noting to do. */
1596 /* no bgp client-to-client reflection check. */
1597 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1598 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1599 PEER_FLAG_REFLECTOR_CLIENT
))
1602 /* A route from a Non-client peer. Reflect to all other
1604 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1605 PEER_FLAG_REFLECTOR_CLIENT
))
1610 /* For modify attribute, copy it to temporary structure. */
1611 bgp_attr_dup(attr
, riattr
);
1613 /* If local-preference is not set. */
1614 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1615 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1616 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1617 attr
->local_pref
= bgp
->default_local_pref
;
1620 /* If originator-id is not set and the route is to be reflected,
1621 set the originator id */
1623 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1624 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1625 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1628 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1630 if (peer
->sort
== BGP_PEER_EBGP
1631 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1632 if (from
!= bgp
->peer_self
&& !transparent
1633 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1634 PEER_FLAG_MED_UNCHANGED
))
1636 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1639 /* Since the nexthop attribute can vary per peer, it is not explicitly
1641 * in announce check, only certain flags and length (or number of
1643 * -- for IPv6/MP_REACH) are set here in order to guide the update
1645 * code in setting the nexthop(s) on a per peer basis in
1647 * Typically, the source nexthop in the attribute is preserved but in
1649 * scenarios where we know it will always be overwritten, we reset the
1650 * nexthop to "0" in an attempt to achieve better Update packing. An
1651 * example of this is when a prefix from each of 2 IBGP peers needs to
1653 * announced to an EBGP peer (and they have the same attributes barring
1657 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1659 #define NEXTHOP_IS_V6 \
1660 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1661 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1662 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1663 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1665 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1667 * the peer (group) is configured to receive link-local nexthop
1669 * and it is available in the prefix OR we're not reflecting the route
1671 * the peer (group) to whom we're going to announce is on a shared
1673 * and this is either a self-originated route or the peer is EBGP.
1675 if (NEXTHOP_IS_V6
) {
1676 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1677 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1678 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1679 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1680 || (!reflect
&& peer
->shared_network
1681 && (from
== bgp
->peer_self
1682 || peer
->sort
== BGP_PEER_EBGP
))) {
1683 attr
->mp_nexthop_len
=
1684 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1687 /* Clear off link-local nexthop in source, whenever it is not
1689 * ensure more prefixes share the same attribute for
1692 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1693 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1694 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1697 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1698 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1700 /* Route map & unsuppress-map apply. */
1701 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1702 struct bgp_info info
;
1703 struct bgp_info_extra dummy_info_extra
;
1704 struct attr dummy_attr
;
1706 memset(&info
, 0, sizeof(struct bgp_info
));
1711 memcpy(&dummy_info_extra
, ri
->extra
,
1712 sizeof(struct bgp_info_extra
));
1713 info
.extra
= &dummy_info_extra
;
1716 /* don't confuse inbound and outbound setting */
1717 RESET_FLAG(attr
->rmap_change_flags
);
1720 * The route reflector is not allowed to modify the attributes
1721 * of the reflected IBGP routes unless explicitly allowed.
1723 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1724 && !bgp_flag_check(bgp
,
1725 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1726 bgp_attr_dup(&dummy_attr
, attr
);
1727 info
.attr
= &dummy_attr
;
1730 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1732 if (ri
->extra
&& ri
->extra
->suppress
)
1733 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1736 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1739 peer
->rmap_type
= 0;
1741 if (ret
== RMAP_DENYMATCH
) {
1742 bgp_attr_flush(attr
);
1747 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1748 if (peer
->sort
== BGP_PEER_IBGP
1749 || peer
->sort
== BGP_PEER_CONFED
) {
1750 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1751 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1753 bgp_attr_add_gshut_community(attr
);
1757 /* After route-map has been applied, we check to see if the nexthop to
1758 * be carried in the attribute (that is used for the announcement) can
1759 * be cleared off or not. We do this in all cases where we would be
1760 * setting the nexthop to "ourselves". For IPv6, we only need to
1762 * the global nexthop here; the link-local nexthop would have been
1764 * already, and if not, it is required by the update formation code.
1765 * Also see earlier comments in this function.
1768 * If route-map has performed some operation on the nexthop or the peer
1769 * configuration says to pass it unchanged, we cannot reset the nexthop
1770 * here, so only attempt to do it if these aren't true. Note that the
1771 * route-map handler itself might have cleared the nexthop, if for
1773 * it is configured as 'peer-address'.
1775 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1776 riattr
->rmap_change_flags
)
1778 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1779 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1780 /* We can reset the nexthop, if setting (or forcing) it to
1782 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1783 PEER_FLAG_NEXTHOP_SELF
)
1784 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1785 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1787 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1788 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1789 subgroup_announce_reset_nhop(
1790 (peer_cap_enhe(peer
, afi
, safi
)
1794 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1795 /* Can also reset the nexthop if announcing to EBGP, but
1797 * no peer in the subgroup is on a shared subnet.
1798 * Note: 3rd party nexthop currently implemented for
1801 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1803 subgroup_announce_reset_nhop(
1804 (peer_cap_enhe(peer
, afi
, safi
)
1808 } else if (CHECK_FLAG(ri
->flags
, BGP_INFO_ANNC_NH_SELF
)) {
1810 * This flag is used for leaked vpn-vrf routes
1812 int family
= p
->family
;
1814 if (peer_cap_enhe(peer
, afi
, safi
))
1817 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1819 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1820 __func__
, family2str(family
));
1821 subgroup_announce_reset_nhop(family
, attr
);
1824 /* If IPv6/MP and nexthop does not have any override and happens
1826 * be a link-local address, reset it so that we don't pass along
1828 * source's link-local IPv6 address to recipients who may not be
1830 * the same interface.
1832 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1833 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1834 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1841 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1842 struct bgp_maxpaths_cfg
*mpath_cfg
,
1843 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1845 struct bgp_info
*new_select
;
1846 struct bgp_info
*old_select
;
1847 struct bgp_info
*ri
;
1848 struct bgp_info
*ri1
;
1849 struct bgp_info
*ri2
;
1850 struct bgp_info
*nextri
= NULL
;
1851 int paths_eq
, do_mpath
, debug
;
1852 struct list mp_list
;
1853 char pfx_buf
[PREFIX2STR_BUFFER
];
1854 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1856 bgp_mp_list_init(&mp_list
);
1858 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1860 debug
= bgp_debug_bestpath(&rn
->p
);
1863 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1865 /* bgp deterministic-med */
1867 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1869 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1870 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1871 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1873 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1874 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1876 if (BGP_INFO_HOLDDOWN(ri1
))
1878 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1879 if (ri1
->peer
->status
!= Established
)
1884 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1885 if (CHECK_FLAG(ri2
->flags
,
1886 BGP_INFO_DMED_CHECK
))
1888 if (BGP_INFO_HOLDDOWN(ri2
))
1891 && ri2
->peer
!= bgp
->peer_self
1894 PEER_STATUS_NSF_WAIT
))
1895 if (ri2
->peer
->status
1899 if (aspath_cmp_left(ri1
->attr
->aspath
,
1901 || aspath_cmp_left_confed(
1903 ri2
->attr
->aspath
)) {
1904 if (bgp_info_cmp(bgp
, ri2
,
1910 bgp_info_unset_flag(
1912 BGP_INFO_DMED_SELECTED
);
1918 BGP_INFO_DMED_CHECK
);
1922 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1923 bgp_info_set_flag(rn
, new_select
,
1924 BGP_INFO_DMED_SELECTED
);
1927 bgp_info_path_with_addpath_rx_str(new_select
,
1929 zlog_debug("%s: %s is the bestpath from AS %u",
1931 aspath_get_first_as(
1932 new_select
->attr
->aspath
));
1937 /* Check old selected route and new selected route. */
1940 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1942 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1945 if (BGP_INFO_HOLDDOWN(ri
)) {
1946 /* reap REMOVED routes, if needs be
1947 * selected route must stay for a while longer though
1949 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1950 && (ri
!= old_select
))
1951 bgp_info_reap(rn
, ri
);
1954 zlog_debug("%s: ri %p in holddown", __func__
,
1960 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1961 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1962 if (ri
->peer
->status
!= Established
) {
1966 "%s: ri %p non self peer %s not estab state",
1967 __func__
, ri
, ri
->peer
->host
);
1972 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1973 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1974 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1976 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1980 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1982 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1983 debug
, pfx_buf
, afi
, safi
)) {
1988 /* Now that we know which path is the bestpath see if any of the other
1990 * qualify as multipaths
1994 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1996 sprintf(path_buf
, "NONE");
1998 "%s: After path selection, newbest is %s oldbest was %s",
2000 old_select
? old_select
->peer
->host
: "NONE");
2003 if (do_mpath
&& new_select
) {
2004 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
2008 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
2010 if (ri
== new_select
) {
2013 "%s: %s is the bestpath, add to the multipath list",
2015 bgp_mp_list_add(&mp_list
, ri
);
2019 if (BGP_INFO_HOLDDOWN(ri
))
2022 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
2023 && !CHECK_FLAG(ri
->peer
->sflags
,
2024 PEER_STATUS_NSF_WAIT
))
2025 if (ri
->peer
->status
!= Established
)
2028 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
2031 "%s: %s has the same nexthop as the bestpath, skip it",
2036 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
2037 debug
, pfx_buf
, afi
, safi
);
2042 "%s: %s is equivalent to the bestpath, add to the multipath list",
2044 bgp_mp_list_add(&mp_list
, ri
);
2049 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
2050 bgp_info_mpath_aggregate_update(new_select
, old_select
);
2051 bgp_mp_list_clear(&mp_list
);
2053 result
->old
= old_select
;
2054 result
->new = new_select
;
2060 * A new route/change in bestpath of an existing route. Evaluate the path
2061 * for advertisement to the subgroup.
2063 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2064 struct bgp_info
*selected
,
2065 struct bgp_node
*rn
,
2066 uint32_t addpath_tx_id
)
2069 struct peer
*onlypeer
;
2075 afi
= SUBGRP_AFI(subgrp
);
2076 safi
= SUBGRP_SAFI(subgrp
);
2077 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2080 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2081 char buf_prefix
[PREFIX_STRLEN
];
2082 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2083 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2087 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2088 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2089 PEER_STATUS_ORF_WAIT_REFRESH
))
2092 memset(&attr
, 0, sizeof(struct attr
));
2093 /* It's initialized in bgp_announce_check() */
2095 /* Announcement to the subgroup. If the route is filtered withdraw it.
2098 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2099 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2101 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2102 selected
->addpath_tx_id
);
2105 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2107 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2114 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2115 * This is called at the end of route processing.
2117 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2119 struct bgp_info
*ri
;
2121 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2122 if (BGP_INFO_HOLDDOWN(ri
))
2124 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2125 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2130 * Has the route changed from the RIB's perspective? This is invoked only
2131 * if the route selection returns the same best route as earlier - to
2132 * determine if we need to update zebra or not.
2134 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2136 struct bgp_info
*mpinfo
;
2138 /* If this is multipath, check all selected paths for any nexthop
2139 * change or attribute change. Some attribute changes (e.g., community)
2140 * aren't of relevance to the RIB, but we'll update zebra to ensure
2141 * we handle the case of BGP nexthop change. This is the behavior
2142 * when the best path has an attribute change anyway.
2144 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2145 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2149 * If this is multipath, check all selected paths for any nexthop change
2151 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2152 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2153 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2154 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2158 /* Nothing has changed from the RIB's perspective. */
2162 struct bgp_process_queue
{
2164 STAILQ_HEAD(, bgp_node
) pqueue
;
2165 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2167 unsigned int queued
;
2171 * old_select = The old best path
2172 * new_select = the new best path
2174 * if (!old_select && new_select)
2175 * We are sending new information on.
2177 * if (old_select && new_select) {
2178 * if (new_select != old_select)
2179 * We have a new best path send a change
2181 * We've received a update with new attributes that needs
2185 * if (old_select && !new_select)
2186 * We have no eligible route that we can announce or the rn
2189 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2190 afi_t afi
, safi_t safi
)
2192 struct bgp_info
*new_select
;
2193 struct bgp_info
*old_select
;
2194 struct bgp_info_pair old_and_new
;
2195 char pfx_buf
[PREFIX2STR_BUFFER
];
2198 /* Is it end of initial update? (after startup) */
2200 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2201 sizeof(bgp
->update_delay_zebra_resume_time
));
2203 bgp
->main_zebra_update_hold
= 0;
2204 FOREACH_AFI_SAFI (afi
, safi
) {
2205 if (bgp_fibupd_safi(safi
))
2206 bgp_zebra_announce_table(bgp
, afi
, safi
);
2208 bgp
->main_peers_update_hold
= 0;
2210 bgp_start_routeadv(bgp
);
2214 struct prefix
*p
= &rn
->p
;
2216 debug
= bgp_debug_bestpath(&rn
->p
);
2218 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2219 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2220 afi2str(afi
), safi2str(safi
));
2223 /* Best path selection. */
2224 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2226 old_select
= old_and_new
.old
;
2227 new_select
= old_and_new
.new;
2229 /* Do we need to allocate or free labels?
2230 * Right now, since we only deal with per-prefix labels, it is not
2231 * necessary to do this upon changes to best path except if the label
2234 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2237 || bgp_label_index_differs(new_select
, old_select
)
2238 || new_select
->sub_type
!= old_select
->sub_type
) {
2239 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2240 && new_select
->attr
->flag
2242 BGP_ATTR_PREFIX_SID
)
2243 && new_select
->attr
->label_index
2244 != BGP_INVALID_LABEL_INDEX
) {
2247 BGP_NODE_REGISTERED_FOR_LABEL
))
2248 bgp_unregister_for_label(rn
);
2249 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2251 bgp_set_valid_label(&rn
->local_label
);
2253 bgp_register_for_label(rn
, new_select
);
2255 } else if (CHECK_FLAG(rn
->flags
,
2256 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2257 bgp_unregister_for_label(rn
);
2259 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2260 bgp_unregister_for_label(rn
);
2264 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2266 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2267 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2268 old_select
, new_select
);
2271 /* If best route remains the same and this is not due to user-initiated
2272 * clear, see exactly what needs to be done.
2274 if (old_select
&& old_select
== new_select
2275 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2276 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2277 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2278 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2280 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2281 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2283 if (bgp_fibupd_safi(safi
)
2284 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2286 if (new_select
->type
== ZEBRA_ROUTE_BGP
2287 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2288 || new_select
->sub_type
2289 == BGP_ROUTE_IMPORTED
))
2291 bgp_zebra_announce(rn
, p
, old_select
,
2295 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2296 bgp_zebra_clear_route_change_flags(rn
);
2298 /* If there is a change of interest to peers, reannounce the
2300 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2301 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2302 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2304 /* unicast routes must also be annouced to
2305 * labeled-unicast update-groups */
2306 if (safi
== SAFI_UNICAST
)
2307 group_announce_route(bgp
, afi
,
2308 SAFI_LABELED_UNICAST
, rn
,
2311 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2312 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2315 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2319 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2321 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2323 /* bestpath has changed; bump version */
2324 if (old_select
|| new_select
) {
2325 bgp_bump_version(rn
);
2327 if (!bgp
->t_rmap_def_originate_eval
) {
2331 update_group_refresh_default_originate_route_map
,
2332 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2333 &bgp
->t_rmap_def_originate_eval
);
2338 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2341 zlog_debug("%s: setting SELECTED flag", __func__
);
2342 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2343 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2344 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2348 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2349 if (old_select
!= new_select
) {
2351 vnc_import_bgp_exterior_del_route(bgp
, p
,
2353 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2356 vnc_import_bgp_exterior_add_route(bgp
, p
,
2358 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2364 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2366 /* unicast routes must also be annouced to labeled-unicast update-groups
2368 if (safi
== SAFI_UNICAST
)
2369 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2373 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2374 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2375 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2376 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2377 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2378 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2380 /* if this is an evpn imported type-5 prefix,
2381 * we need to withdraw the route first to clear
2382 * the nh neigh and the RMAC entry.
2385 is_route_parent_evpn(old_select
))
2386 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2388 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2390 /* Withdraw the route from the kernel. */
2391 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2392 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2393 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2394 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2396 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2400 /* advertise/withdraw type-5 routes */
2401 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2402 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2403 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2405 /* apply the route-map */
2406 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2409 ret
= route_map_apply(
2410 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2411 &rn
->p
, RMAP_BGP
, new_select
);
2412 if (ret
== RMAP_MATCH
)
2413 bgp_evpn_advertise_type5_route(
2414 bgp
, &rn
->p
, new_select
->attr
,
2417 bgp_evpn_advertise_type5_route(bgp
,
2423 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2424 (!old_select
->extra
|| !old_select
->extra
->parent
))
2425 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2428 /* Clear any route change flags. */
2429 bgp_zebra_clear_route_change_flags(rn
);
2431 /* Reap old select bgp_info, if it has been removed */
2432 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2433 bgp_info_reap(rn
, old_select
);
2435 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2439 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2441 struct bgp_process_queue
*pqnode
= data
;
2442 struct bgp
*bgp
= pqnode
->bgp
;
2443 struct bgp_table
*table
;
2444 struct bgp_node
*rn
;
2447 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2448 bgp_process_main_one(bgp
, NULL
, 0, 0);
2449 /* should always have dedicated wq call */
2450 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2454 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2455 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2456 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2457 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2458 table
= bgp_node_table(rn
);
2459 /* note, new RNs may be added as part of processing */
2460 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2462 bgp_unlock_node(rn
);
2463 bgp_table_unlock(table
);
2469 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2471 struct bgp_process_queue
*pqnode
= data
;
2473 bgp_unlock(pqnode
->bgp
);
2475 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2478 void bgp_process_queue_init(void)
2480 if (!bm
->process_main_queue
)
2481 bm
->process_main_queue
=
2482 work_queue_new(bm
->master
, "process_main_queue");
2484 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2485 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2486 bm
->process_main_queue
->spec
.max_retries
= 0;
2487 bm
->process_main_queue
->spec
.hold
= 50;
2488 /* Use a higher yield value of 50ms for main queue processing */
2489 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2492 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2494 struct bgp_process_queue
*pqnode
;
2496 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2497 sizeof(struct bgp_process_queue
));
2499 /* unlocked in bgp_processq_del */
2500 pqnode
->bgp
= bgp_lock(bgp
);
2501 STAILQ_INIT(&pqnode
->pqueue
);
2506 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2508 #define ARBITRARY_PROCESS_QLEN 10000
2509 struct work_queue
*wq
= bm
->process_main_queue
;
2510 struct bgp_process_queue
*pqnode
;
2511 int pqnode_reuse
= 0;
2513 /* already scheduled for processing? */
2514 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2520 /* Add route nodes to an existing work queue item until reaching the
2521 limit only if is from the same BGP view and it's not an EOIU marker
2523 if (work_queue_item_count(wq
)) {
2524 struct work_queue_item
*item
= work_queue_last_item(wq
);
2525 pqnode
= item
->data
;
2527 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2528 || pqnode
->bgp
!= bgp
2529 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2530 pqnode
= bgp_processq_alloc(bgp
);
2534 pqnode
= bgp_processq_alloc(bgp
);
2535 /* all unlocked in bgp_process_wq */
2536 bgp_table_lock(bgp_node_table(rn
));
2538 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2541 /* can't be enqueued twice */
2542 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2543 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2547 work_queue_add(wq
, pqnode
);
2552 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2554 struct bgp_process_queue
*pqnode
;
2556 if (bm
->process_main_queue
== NULL
)
2559 pqnode
= bgp_processq_alloc(bgp
);
2561 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2562 work_queue_add(bm
->process_main_queue
, pqnode
);
2565 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2569 peer
= THREAD_ARG(thread
);
2570 peer
->t_pmax_restart
= NULL
;
2572 if (bgp_debug_neighbor_events(peer
))
2574 "%s Maximum-prefix restart timer expired, restore peering",
2577 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2578 zlog_debug("%s: %s peer_clear failed",
2579 __PRETTY_FUNCTION__
, peer
->host
);
2584 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2588 iana_safi_t pkt_safi
;
2590 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2593 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2594 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2595 PEER_STATUS_PREFIX_LIMIT
)
2600 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2602 afi_safi_print(afi
, safi
), peer
->host
,
2603 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2604 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2606 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2607 PEER_FLAG_MAX_PREFIX_WARNING
))
2610 /* Convert AFI, SAFI to values for packet. */
2611 pkt_afi
= afi_int2iana(afi
);
2612 pkt_safi
= safi_int2iana(safi
);
2616 ndata
[0] = (pkt_afi
>> 8);
2618 ndata
[2] = pkt_safi
;
2619 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2620 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2621 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2622 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2624 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2625 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2626 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2630 /* Dynamic peers will just close their connection. */
2631 if (peer_dynamic_neighbor(peer
))
2634 /* restart timer start */
2635 if (peer
->pmax_restart
[afi
][safi
]) {
2636 peer
->v_pmax_restart
=
2637 peer
->pmax_restart
[afi
][safi
] * 60;
2639 if (bgp_debug_neighbor_events(peer
))
2641 "%s Maximum-prefix restart timer started for %d secs",
2642 peer
->host
, peer
->v_pmax_restart
);
2644 BGP_TIMER_ON(peer
->t_pmax_restart
,
2645 bgp_maximum_prefix_restart_timer
,
2646 peer
->v_pmax_restart
);
2651 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2652 PEER_STATUS_PREFIX_LIMIT
);
2654 if (peer
->pcount
[afi
][safi
]
2655 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2656 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2657 PEER_STATUS_PREFIX_THRESHOLD
)
2662 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2663 afi_safi_print(afi
, safi
), peer
->host
,
2664 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2665 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2666 PEER_STATUS_PREFIX_THRESHOLD
);
2668 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2669 PEER_STATUS_PREFIX_THRESHOLD
);
2673 /* Unconditionally remove the route from the RIB, without taking
2674 * damping into consideration (eg, because the session went down)
2676 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2677 afi_t afi
, safi_t safi
)
2679 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2681 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2682 bgp_info_delete(rn
, ri
); /* keep historical info */
2684 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2687 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2688 struct peer
*peer
, afi_t afi
, safi_t safi
,
2689 struct prefix_rd
*prd
)
2691 /* apply dampening, if result is suppressed, we'll be retaining
2692 * the bgp_info in the RIB for historical reference.
2694 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2695 && peer
->sort
== BGP_PEER_EBGP
)
2696 if ((bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2697 == BGP_DAMP_SUPPRESSED
) {
2698 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2704 if (safi
== SAFI_MPLS_VPN
) {
2705 struct bgp_node
*prn
= NULL
;
2706 struct bgp_table
*table
= NULL
;
2708 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2709 (struct prefix
*)prd
);
2711 table
= (struct bgp_table
*)(prn
->info
);
2713 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2714 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2716 bgp_unlock_node(prn
);
2718 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2719 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2721 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2722 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2728 /* If this is an EVPN route, process for un-import. */
2729 if (safi
== SAFI_EVPN
)
2730 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2732 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2735 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2736 struct peer
*peer
, struct attr
*attr
,
2737 struct bgp_node
*rn
)
2739 struct bgp_info
*new;
2741 /* Make new BGP info. */
2742 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2744 new->instance
= instance
;
2745 new->sub_type
= sub_type
;
2748 new->uptime
= bgp_clock();
2750 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2754 static void overlay_index_update(struct attr
*attr
,
2755 struct eth_segment_id
*eth_s_id
,
2756 union gw_addr
*gw_ip
)
2761 if (eth_s_id
== NULL
) {
2762 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2763 sizeof(struct eth_segment_id
));
2765 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2766 sizeof(struct eth_segment_id
));
2768 if (gw_ip
== NULL
) {
2769 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2771 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2772 sizeof(union gw_addr
));
2776 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2777 struct eth_segment_id
*eth_s_id
,
2778 union gw_addr
*gw_ip
)
2780 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2781 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2784 if (afi
!= AFI_L2VPN
)
2787 memset(&temp
, 0, 16);
2788 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2789 info_gw_ip
= (union gw_addr
*)&temp
;
2790 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2793 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2794 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2797 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2799 info_gw_ip_remote
= gw_ip
;
2800 if (eth_s_id
== NULL
)
2801 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2803 info_eth_s_id_remote
= eth_s_id
;
2804 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2806 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2807 sizeof(struct eth_segment_id
));
2810 /* Check if received nexthop is valid or not. */
2811 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2816 /* Only validated for unicast and multicast currently. */
2817 /* Also valid for EVPN where the nexthop is an IP address. */
2818 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2821 /* If NEXT_HOP is present, validate it. */
2822 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2823 if (attr
->nexthop
.s_addr
== 0
2824 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2825 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2829 /* If MP_NEXTHOP is present, validate it. */
2830 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2831 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2832 * it is not an IPv6 link-local address.
2834 if (attr
->mp_nexthop_len
) {
2835 switch (attr
->mp_nexthop_len
) {
2836 case BGP_ATTR_NHLEN_IPV4
:
2837 case BGP_ATTR_NHLEN_VPNV4
:
2838 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2839 || IPV4_CLASS_DE(ntohl(
2840 attr
->mp_nexthop_global_in
.s_addr
))
2841 || bgp_nexthop_self(bgp
,
2842 attr
->mp_nexthop_global_in
));
2845 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2846 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2847 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2848 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2849 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2850 || IN6_IS_ADDR_MULTICAST(
2851 &attr
->mp_nexthop_global
));
2863 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2864 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2865 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2866 uint32_t num_labels
, int soft_reconfig
,
2867 struct bgp_route_evpn
*evpn
)
2870 int aspath_loop_count
= 0;
2871 struct bgp_node
*rn
;
2873 struct attr new_attr
;
2874 struct attr
*attr_new
;
2875 struct bgp_info
*ri
;
2876 struct bgp_info
*new;
2877 struct bgp_info_extra
*extra
;
2879 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2881 int do_loop_check
= 1;
2882 int has_valid_label
= 0;
2884 int vnc_implicit_withdraw
= 0;
2888 memset(&new_attr
, 0, sizeof(struct attr
));
2889 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2890 new_attr
.label
= MPLS_INVALID_LABEL
;
2893 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2894 /* TODO: Check to see if we can get rid of "is_valid_label" */
2895 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2896 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2898 has_valid_label
= bgp_is_valid_label(label
);
2900 /* When peer's soft reconfiguration enabled. Record input packet in
2903 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2904 && peer
!= bgp
->peer_self
)
2905 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2907 /* Check previously received route. */
2908 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2909 if (ri
->peer
== peer
&& ri
->type
== type
2910 && ri
->sub_type
== sub_type
2911 && ri
->addpath_rx_id
== addpath_id
)
2914 /* AS path local-as loop check. */
2915 if (peer
->change_local_as
) {
2916 if (peer
->allowas_in
[afi
][safi
])
2917 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2918 else if (!CHECK_FLAG(peer
->flags
,
2919 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2920 aspath_loop_count
= 1;
2922 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2923 > aspath_loop_count
) {
2924 reason
= "as-path contains our own AS;";
2929 /* If the peer is configured for "allowas-in origin" and the last ASN in
2931 * as-path is our ASN then we do not need to call aspath_loop_check
2933 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2934 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2937 /* AS path loop check. */
2938 if (do_loop_check
) {
2939 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2940 > peer
->allowas_in
[afi
][safi
]
2941 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2942 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2943 > peer
->allowas_in
[afi
][safi
])) {
2944 reason
= "as-path contains our own AS;";
2949 /* Route reflector originator ID check. */
2950 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2951 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2952 reason
= "originator is us;";
2956 /* Route reflector cluster ID check. */
2957 if (bgp_cluster_filter(peer
, attr
)) {
2958 reason
= "reflected from the same cluster;";
2962 /* Apply incoming filter. */
2963 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2968 bgp_attr_dup(&new_attr
, attr
);
2970 /* Apply incoming route-map.
2971 * NB: new_attr may now contain newly allocated values from route-map
2973 * commands, so we need bgp_attr_flush in the error paths, until we
2975 * the attr (which takes over the memory references) */
2976 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2978 reason
= "route-map;";
2979 bgp_attr_flush(&new_attr
);
2983 if (peer
->sort
== BGP_PEER_EBGP
) {
2985 /* If we receive the graceful-shutdown community from an eBGP
2986 * peer we must lower local-preference */
2987 if (new_attr
.community
2988 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2989 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2990 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2992 /* If graceful-shutdown is configured then add the GSHUT
2993 * community to all paths received from eBGP peers */
2994 } else if (bgp_flag_check(peer
->bgp
,
2995 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2996 bgp_attr_add_gshut_community(&new_attr
);
3000 /* next hop check. */
3001 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3002 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3003 reason
= "martian or self next-hop;";
3004 bgp_attr_flush(&new_attr
);
3008 attr_new
= bgp_attr_intern(&new_attr
);
3010 /* If the update is implicit withdraw. */
3012 ri
->uptime
= bgp_clock();
3013 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
3015 /* Same attribute comes in. */
3016 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
3017 && attrhash_cmp(ri
->attr
, attr_new
)
3018 && (!has_valid_label
3019 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
3020 num_labels
* sizeof(mpls_label_t
))
3022 && (overlay_index_equal(
3023 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3024 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3025 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3026 BGP_CONFIG_DAMPENING
)
3027 && peer
->sort
== BGP_PEER_EBGP
3028 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3029 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3030 bgp_debug_rdpfxpath2str(
3031 afi
, safi
, prd
, p
, label
,
3032 num_labels
, addpath_id
? 1 : 0,
3033 addpath_id
, pfx_buf
,
3035 zlog_debug("%s rcvd %s", peer
->host
,
3039 if (bgp_damp_update(ri
, rn
, afi
, safi
)
3040 != BGP_DAMP_SUPPRESSED
) {
3041 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
3043 bgp_process(bgp
, rn
, afi
, safi
);
3045 } else /* Duplicate - odd */
3047 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3048 if (!peer
->rcvd_attr_printed
) {
3050 "%s rcvd UPDATE w/ attr: %s",
3052 peer
->rcvd_attr_str
);
3053 peer
->rcvd_attr_printed
= 1;
3056 bgp_debug_rdpfxpath2str(
3057 afi
, safi
, prd
, p
, label
,
3058 num_labels
, addpath_id
? 1 : 0,
3059 addpath_id
, pfx_buf
,
3062 "%s rcvd %s...duplicate ignored",
3063 peer
->host
, pfx_buf
);
3066 /* graceful restart STALE flag unset. */
3067 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3068 bgp_info_unset_flag(rn
, ri
,
3070 bgp_process(bgp
, rn
, afi
, safi
);
3074 bgp_unlock_node(rn
);
3075 bgp_attr_unintern(&attr_new
);
3080 /* Withdraw/Announce before we fully processed the withdraw */
3081 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3082 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3083 bgp_debug_rdpfxpath2str(
3084 afi
, safi
, prd
, p
, label
, num_labels
,
3085 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3088 "%s rcvd %s, flapped quicker than processing",
3089 peer
->host
, pfx_buf
);
3092 bgp_info_restore(rn
, ri
);
3095 /* Received Logging. */
3096 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3097 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3098 num_labels
, addpath_id
? 1 : 0,
3099 addpath_id
, pfx_buf
,
3101 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3104 /* graceful restart STALE flag unset. */
3105 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3106 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3108 /* The attribute is changed. */
3109 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3111 /* implicit withdraw, decrement aggregate and pcount here.
3112 * only if update is accepted, they'll increment below.
3114 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3116 /* Update bgp route dampening information. */
3117 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3118 && peer
->sort
== BGP_PEER_EBGP
) {
3119 /* This is implicit withdraw so we should update
3122 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3123 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3126 if (safi
== SAFI_MPLS_VPN
) {
3127 struct bgp_node
*prn
= NULL
;
3128 struct bgp_table
*table
= NULL
;
3130 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3131 (struct prefix
*)prd
);
3133 table
= (struct bgp_table
*)(prn
->info
);
3135 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3136 bgp
, prd
, table
, p
, ri
);
3138 bgp_unlock_node(prn
);
3140 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3141 && (safi
== SAFI_UNICAST
)) {
3142 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3144 * Implicit withdraw case.
3146 ++vnc_implicit_withdraw
;
3147 vnc_import_bgp_del_route(bgp
, p
, ri
);
3148 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3153 /* Special handling for EVPN update of an existing route. If the
3154 * extended community attribute has changed, we need to
3156 * the route using its existing extended community. It will be
3157 * subsequently processed for import with the new extended
3160 if (safi
== SAFI_EVPN
&& !same_attr
) {
3162 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3164 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3167 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3168 attr_new
->ecommunity
);
3170 if (bgp_debug_update(peer
, p
, NULL
, 1))
3172 "Change in EXT-COMM, existing %s new %s",
3174 ri
->attr
->ecommunity
),
3176 attr_new
->ecommunity
));
3177 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3183 /* Update to new attribute. */
3184 bgp_attr_unintern(&ri
->attr
);
3185 ri
->attr
= attr_new
;
3187 /* Update MPLS label */
3188 if (has_valid_label
) {
3189 extra
= bgp_info_extra_get(ri
);
3190 memcpy(&extra
->label
, label
,
3191 num_labels
* sizeof(mpls_label_t
));
3192 extra
->num_labels
= num_labels
;
3193 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3194 bgp_set_valid_label(&extra
->label
[0]);
3198 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3199 && (safi
== SAFI_UNICAST
)) {
3200 if (vnc_implicit_withdraw
) {
3202 * Add back the route with its new attributes
3204 * The route is still selected, until the route
3206 * queued by bgp_process actually runs. We have
3208 * update to the VNC side immediately to avoid
3210 * configuration changes (e.g., route-map
3212 * trigger re-importation of the entire RIB.
3214 vnc_import_bgp_add_route(bgp
, p
, ri
);
3215 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3219 /* Update Overlay Index */
3220 if (afi
== AFI_L2VPN
) {
3221 overlay_index_update(
3222 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3223 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3226 /* Update bgp route dampening information. */
3227 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3228 && peer
->sort
== BGP_PEER_EBGP
) {
3229 /* Now we do normal update dampening. */
3230 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3231 if (ret
== BGP_DAMP_SUPPRESSED
) {
3232 bgp_unlock_node(rn
);
3237 /* Nexthop reachability check - for unicast and
3238 * labeled-unicast.. */
3239 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3240 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3241 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3242 && !CHECK_FLAG(peer
->flags
,
3243 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3245 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3250 struct bgp
*bgp_nexthop
= bgp
;
3252 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3253 bgp_nexthop
= ri
->extra
->bgp_orig
;
3255 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3256 ri
, NULL
, connected
)
3257 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3258 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3260 if (BGP_DEBUG(nht
, NHT
)) {
3261 char buf1
[INET6_ADDRSTRLEN
];
3263 (const void *)&attr_new
3265 buf1
, INET6_ADDRSTRLEN
);
3266 zlog_debug("%s(%s): NH unresolved",
3267 __FUNCTION__
, buf1
);
3269 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3272 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3275 if (safi
== SAFI_MPLS_VPN
) {
3276 struct bgp_node
*prn
= NULL
;
3277 struct bgp_table
*table
= NULL
;
3279 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3280 (struct prefix
*)prd
);
3282 table
= (struct bgp_table
*)(prn
->info
);
3284 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3285 bgp
, prd
, table
, p
, ri
);
3287 bgp_unlock_node(prn
);
3291 /* If this is an EVPN route and some attribute has changed,
3293 * route for import. If the extended community has changed, we
3295 * have done the un-import earlier and the import would result
3297 * route getting injected into appropriate L2 VNIs. If it is
3299 * some other attribute change, the import will result in
3301 * the attributes for the route in the VNI(s).
3303 if (safi
== SAFI_EVPN
&& !same_attr
)
3304 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3306 /* Process change. */
3307 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3309 bgp_process(bgp
, rn
, afi
, safi
);
3310 bgp_unlock_node(rn
);
3312 if (SAFI_UNICAST
== safi
3313 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3314 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3316 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3318 if ((SAFI_MPLS_VPN
== safi
)
3319 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3321 vpn_leak_to_vrf_update(bgp
, ri
);
3325 if (SAFI_MPLS_VPN
== safi
) {
3326 mpls_label_t label_decoded
= decode_label(label
);
3328 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3329 type
, sub_type
, &label_decoded
);
3331 if (SAFI_ENCAP
== safi
) {
3332 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3333 type
, sub_type
, NULL
);
3338 } // End of implicit withdraw
3340 /* Received Logging. */
3341 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3342 if (!peer
->rcvd_attr_printed
) {
3343 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3344 peer
->rcvd_attr_str
);
3345 peer
->rcvd_attr_printed
= 1;
3348 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3349 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3351 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3354 /* Make new BGP info. */
3355 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3357 /* Update MPLS label */
3358 if (has_valid_label
) {
3359 extra
= bgp_info_extra_get(new);
3360 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3361 extra
->num_labels
= num_labels
;
3362 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3363 bgp_set_valid_label(&extra
->label
[0]);
3366 /* Update Overlay Index */
3367 if (afi
== AFI_L2VPN
) {
3368 overlay_index_update(new->attr
,
3369 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3370 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3372 /* Nexthop reachability check. */
3373 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3374 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3375 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3376 && !CHECK_FLAG(peer
->flags
,
3377 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3378 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3383 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3384 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3385 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3387 if (BGP_DEBUG(nht
, NHT
)) {
3388 char buf1
[INET6_ADDRSTRLEN
];
3390 (const void *)&attr_new
->nexthop
,
3391 buf1
, INET6_ADDRSTRLEN
);
3392 zlog_debug("%s(%s): NH unresolved",
3393 __FUNCTION__
, buf1
);
3395 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3398 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3401 new->addpath_rx_id
= addpath_id
;
3403 /* Increment prefix */
3404 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3406 /* Register new BGP information. */
3407 bgp_info_add(rn
, new);
3409 /* route_node_get lock */
3410 bgp_unlock_node(rn
);
3413 if (safi
== SAFI_MPLS_VPN
) {
3414 struct bgp_node
*prn
= NULL
;
3415 struct bgp_table
*table
= NULL
;
3417 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3419 table
= (struct bgp_table
*)(prn
->info
);
3421 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3422 bgp
, prd
, table
, p
, new);
3424 bgp_unlock_node(prn
);
3428 /* If maximum prefix count is configured and current prefix
3430 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3433 /* If this is an EVPN route, process for import. */
3434 if (safi
== SAFI_EVPN
)
3435 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3437 /* Process change. */
3438 bgp_process(bgp
, rn
, afi
, safi
);
3440 if (SAFI_UNICAST
== safi
3441 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3442 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3443 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3445 if ((SAFI_MPLS_VPN
== safi
)
3446 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3448 vpn_leak_to_vrf_update(bgp
, new);
3451 if (SAFI_MPLS_VPN
== safi
) {
3452 mpls_label_t label_decoded
= decode_label(label
);
3454 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3455 sub_type
, &label_decoded
);
3457 if (SAFI_ENCAP
== safi
) {
3458 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3465 /* This BGP update is filtered. Log the reason then update BGP
3468 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3469 if (!peer
->rcvd_attr_printed
) {
3470 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3471 peer
->rcvd_attr_str
);
3472 peer
->rcvd_attr_printed
= 1;
3475 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3476 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3478 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3479 peer
->host
, pfx_buf
, reason
);
3483 /* If this is an EVPN route, un-import it as it is now filtered.
3485 if (safi
== SAFI_EVPN
)
3486 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3488 if (SAFI_UNICAST
== safi
3489 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3490 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3492 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3494 if ((SAFI_MPLS_VPN
== safi
)
3495 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3497 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3500 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3503 bgp_unlock_node(rn
);
3507 * Filtered update is treated as an implicit withdrawal (see
3509 * a few lines above)
3511 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3512 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3520 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3521 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3522 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3523 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3526 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3527 struct bgp_node
*rn
;
3528 struct bgp_info
*ri
;
3531 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3532 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3540 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3542 /* If peer is soft reconfiguration enabled. Record input packet for
3543 * further calculation.
3545 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3546 * routes that are filtered. This tanks out Quagga RS pretty badly due
3548 * the iteration over all RS clients.
3549 * Since we need to remove the entry from adj_in anyway, do that first
3551 * if there was no entry, we don't need to do anything more.
3553 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3554 && peer
!= bgp
->peer_self
)
3555 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3556 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3557 bgp_debug_rdpfxpath2str(
3558 afi
, safi
, prd
, p
, label
, num_labels
,
3559 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3562 "%s withdrawing route %s not in adj-in",
3563 peer
->host
, pfx_buf
);
3565 bgp_unlock_node(rn
);
3569 /* Lookup withdrawn route. */
3570 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3571 if (ri
->peer
== peer
&& ri
->type
== type
3572 && ri
->sub_type
== sub_type
3573 && ri
->addpath_rx_id
== addpath_id
)
3577 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3578 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3579 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3581 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3585 /* Withdraw specified route from routing table. */
3586 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3587 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3588 if (SAFI_UNICAST
== safi
3589 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3590 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3591 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3593 if ((SAFI_MPLS_VPN
== safi
)
3594 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3596 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3598 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3599 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3600 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3602 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3605 /* Unlock bgp_node_get() lock. */
3606 bgp_unlock_node(rn
);
3611 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3614 struct update_subgroup
*subgrp
;
3615 subgrp
= peer_subgroup(peer
, afi
, safi
);
3616 subgroup_default_originate(subgrp
, withdraw
);
3621 * bgp_stop_announce_route_timer
3623 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3625 if (!paf
->t_announce_route
)
3628 THREAD_TIMER_OFF(paf
->t_announce_route
);
3632 * bgp_announce_route_timer_expired
3634 * Callback that is invoked when the route announcement timer for a
3637 static int bgp_announce_route_timer_expired(struct thread
*t
)
3639 struct peer_af
*paf
;
3642 paf
= THREAD_ARG(t
);
3645 if (peer
->status
!= Established
)
3648 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3651 peer_af_announce_route(paf
, 1);
3656 * bgp_announce_route
3658 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3660 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3662 struct peer_af
*paf
;
3663 struct update_subgroup
*subgrp
;
3665 paf
= peer_af_find(peer
, afi
, safi
);
3668 subgrp
= PAF_SUBGRP(paf
);
3671 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3672 * or a refresh has already been triggered.
3674 if (!subgrp
|| paf
->t_announce_route
)
3678 * Start a timer to stagger/delay the announce. This serves
3679 * two purposes - announcement can potentially be combined for
3680 * multiple peers and the announcement doesn't happen in the
3683 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3684 (subgrp
->peer_count
== 1)
3685 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3686 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3687 &paf
->t_announce_route
);
3691 * Announce routes from all AF tables to a peer.
3693 * This should ONLY be called when there is a need to refresh the
3694 * routes to the peer based on a policy change for this peer alone
3695 * or a route refresh request received from the peer.
3696 * The operation will result in splitting the peer from its existing
3697 * subgroups and putting it in new subgroups.
3699 void bgp_announce_route_all(struct peer
*peer
)
3704 FOREACH_AFI_SAFI (afi
, safi
)
3705 bgp_announce_route(peer
, afi
, safi
);
3708 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3709 struct bgp_table
*table
,
3710 struct prefix_rd
*prd
)
3713 struct bgp_node
*rn
;
3714 struct bgp_adj_in
*ain
;
3717 table
= peer
->bgp
->rib
[afi
][safi
];
3719 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3720 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3721 if (ain
->peer
!= peer
)
3724 struct bgp_info
*ri
= rn
->info
;
3725 uint32_t num_labels
= 0;
3726 mpls_label_t
*label_pnt
= NULL
;
3728 if (ri
&& ri
->extra
)
3729 num_labels
= ri
->extra
->num_labels
;
3731 label_pnt
= &ri
->extra
->label
[0];
3733 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3734 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3735 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3736 num_labels
, 1, NULL
);
3739 bgp_unlock_node(rn
);
3745 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3747 struct bgp_node
*rn
;
3748 struct bgp_table
*table
;
3750 if (peer
->status
!= Established
)
3753 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3754 && (safi
!= SAFI_EVPN
))
3755 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3757 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3758 rn
= bgp_route_next(rn
))
3759 if ((table
= rn
->info
) != NULL
) {
3760 struct prefix_rd prd
;
3761 prd
.family
= AF_UNSPEC
;
3763 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3765 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3771 struct bgp_clear_node_queue
{
3772 struct bgp_node
*rn
;
3775 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3777 struct bgp_clear_node_queue
*cnq
= data
;
3778 struct bgp_node
*rn
= cnq
->rn
;
3779 struct peer
*peer
= wq
->spec
.data
;
3780 struct bgp_info
*ri
;
3782 afi_t afi
= bgp_node_table(rn
)->afi
;
3783 safi_t safi
= bgp_node_table(rn
)->safi
;
3788 /* It is possible that we have multiple paths for a prefix from a peer
3789 * if that peer is using AddPath.
3791 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3792 if (ri
->peer
!= peer
)
3795 /* graceful restart STALE flag set. */
3796 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3797 && peer
->nsf
[afi
][safi
]
3798 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3799 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3800 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3802 /* If this is an EVPN route, process for
3804 if (safi
== SAFI_EVPN
)
3805 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3807 /* Handle withdraw for VRF route-leaking and L3VPN */
3808 if (SAFI_UNICAST
== safi
3809 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3810 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3811 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3814 if (SAFI_MPLS_VPN
== safi
&&
3815 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3816 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3819 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3825 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3827 struct bgp_clear_node_queue
*cnq
= data
;
3828 struct bgp_node
*rn
= cnq
->rn
;
3829 struct bgp_table
*table
= bgp_node_table(rn
);
3831 bgp_unlock_node(rn
);
3832 bgp_table_unlock(table
);
3833 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3836 static void bgp_clear_node_complete(struct work_queue
*wq
)
3838 struct peer
*peer
= wq
->spec
.data
;
3840 /* Tickle FSM to start moving again */
3841 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3843 peer_unlock(peer
); /* bgp_clear_route */
3846 static void bgp_clear_node_queue_init(struct peer
*peer
)
3848 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3850 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3851 #undef CLEAR_QUEUE_NAME_LEN
3853 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3854 peer
->clear_node_queue
->spec
.hold
= 10;
3855 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3856 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3857 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3858 peer
->clear_node_queue
->spec
.max_retries
= 0;
3860 /* we only 'lock' this peer reference when the queue is actually active
3862 peer
->clear_node_queue
->spec
.data
= peer
;
3865 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3866 struct bgp_table
*table
)
3868 struct bgp_node
*rn
;
3869 int force
= bm
->process_main_queue
? 0 : 1;
3872 table
= peer
->bgp
->rib
[afi
][safi
];
3874 /* If still no table => afi/safi isn't configured at all or smth. */
3878 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3879 struct bgp_info
*ri
, *next
;
3880 struct bgp_adj_in
*ain
;
3881 struct bgp_adj_in
*ain_next
;
3883 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3884 * queued for every clearing peer, regardless of whether it is
3885 * relevant to the peer at hand.
3887 * Overview: There are 3 different indices which need to be
3888 * scrubbed, potentially, when a peer is removed:
3890 * 1 peer's routes visible via the RIB (ie accepted routes)
3891 * 2 peer's routes visible by the (optional) peer's adj-in index
3892 * 3 other routes visible by the peer's adj-out index
3894 * 3 there is no hurry in scrubbing, once the struct peer is
3895 * removed from bgp->peer, we could just GC such deleted peer's
3896 * adj-outs at our leisure.
3898 * 1 and 2 must be 'scrubbed' in some way, at least made
3899 * invisible via RIB index before peer session is allowed to be
3900 * brought back up. So one needs to know when such a 'search' is
3905 * - there'd be a single global queue or a single RIB walker
3906 * - rather than tracking which route_nodes still need to be
3907 * examined on a peer basis, we'd track which peers still
3910 * Given that our per-peer prefix-counts now should be reliable,
3911 * this may actually be achievable. It doesn't seem to be a huge
3912 * problem at this time,
3914 * It is possible that we have multiple paths for a prefix from
3916 * if that peer is using AddPath.
3920 ain_next
= ain
->next
;
3922 if (ain
->peer
== peer
) {
3923 bgp_adj_in_remove(rn
, ain
);
3924 bgp_unlock_node(rn
);
3930 for (ri
= rn
->info
; ri
; ri
= next
) {
3932 if (ri
->peer
!= peer
)
3936 bgp_info_reap(rn
, ri
);
3938 struct bgp_clear_node_queue
*cnq
;
3940 /* both unlocked in bgp_clear_node_queue_del */
3941 bgp_table_lock(bgp_node_table(rn
));
3944 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3945 sizeof(struct bgp_clear_node_queue
));
3947 work_queue_add(peer
->clear_node_queue
, cnq
);
3955 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3957 struct bgp_node
*rn
;
3958 struct bgp_table
*table
;
3960 if (peer
->clear_node_queue
== NULL
)
3961 bgp_clear_node_queue_init(peer
);
3963 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3964 * Idle until it receives a Clearing_Completed event. This protects
3965 * against peers which flap faster than we can we clear, which could
3968 * a) race with routes from the new session being installed before
3969 * clear_route_node visits the node (to delete the route of that
3971 * b) resource exhaustion, clear_route_node likely leads to an entry
3972 * on the process_main queue. Fast-flapping could cause that queue
3976 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3977 * the unlock will happen upon work-queue completion; other wise, the
3978 * unlock happens at the end of this function.
3980 if (!peer
->clear_node_queue
->thread
)
3983 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3984 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3986 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3987 rn
= bgp_route_next(rn
))
3988 if ((table
= rn
->info
) != NULL
)
3989 bgp_clear_route_table(peer
, afi
, safi
, table
);
3991 /* unlock if no nodes got added to the clear-node-queue. */
3992 if (!peer
->clear_node_queue
->thread
)
3996 void bgp_clear_route_all(struct peer
*peer
)
4001 FOREACH_AFI_SAFI (afi
, safi
)
4002 bgp_clear_route(peer
, afi
, safi
);
4005 rfapiProcessPeerDown(peer
);
4009 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4011 struct bgp_table
*table
;
4012 struct bgp_node
*rn
;
4013 struct bgp_adj_in
*ain
;
4014 struct bgp_adj_in
*ain_next
;
4016 table
= peer
->bgp
->rib
[afi
][safi
];
4018 /* It is possible that we have multiple paths for a prefix from a peer
4019 * if that peer is using AddPath.
4021 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4025 ain_next
= ain
->next
;
4027 if (ain
->peer
== peer
) {
4028 bgp_adj_in_remove(rn
, ain
);
4029 bgp_unlock_node(rn
);
4037 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4039 struct bgp_node
*rn
;
4040 struct bgp_info
*ri
;
4041 struct bgp_table
*table
;
4043 if (safi
== SAFI_MPLS_VPN
) {
4044 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4045 rn
= bgp_route_next(rn
)) {
4046 struct bgp_node
*rm
;
4047 struct bgp_info
*ri
;
4049 /* look for neighbor in tables */
4050 if ((table
= rn
->info
) == NULL
)
4053 for (rm
= bgp_table_top(table
); rm
;
4054 rm
= bgp_route_next(rm
))
4055 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4056 if (ri
->peer
!= peer
)
4058 if (!CHECK_FLAG(ri
->flags
,
4062 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4067 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4068 rn
= bgp_route_next(rn
))
4069 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4070 if (ri
->peer
!= peer
)
4072 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4074 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4080 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4083 struct bgp_node
*rn
;
4084 struct bgp_info
*ri
;
4085 struct bgp_info
*next
;
4087 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4088 for (ri
= rn
->info
; ri
; ri
= next
) {
4090 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4091 && ri
->type
== ZEBRA_ROUTE_BGP
4092 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4093 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4094 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4096 if (bgp_fibupd_safi(safi
))
4097 bgp_zebra_withdraw(&rn
->p
, ri
,
4099 bgp_info_reap(rn
, ri
);
4104 /* Delete all kernel routes. */
4105 void bgp_cleanup_routes(struct bgp
*bgp
)
4108 struct bgp_node
*rn
;
4110 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4111 if (afi
== AFI_L2VPN
)
4113 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4116 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4118 if (afi
!= AFI_L2VPN
) {
4120 safi
= SAFI_MPLS_VPN
;
4121 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4122 rn
= bgp_route_next(rn
)) {
4124 bgp_cleanup_table(bgp
,
4125 (struct bgp_table
*)(rn
->info
),
4127 bgp_table_finish((struct bgp_table
**)&(
4130 bgp_unlock_node(rn
);
4134 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4135 rn
= bgp_route_next(rn
)) {
4137 bgp_cleanup_table(bgp
,
4138 (struct bgp_table
*)(rn
->info
),
4140 bgp_table_finish((struct bgp_table
**)&(
4143 bgp_unlock_node(rn
);
4148 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4149 rn
= bgp_route_next(rn
)) {
4151 bgp_cleanup_table(bgp
,
4152 (struct bgp_table
*)(rn
->info
),
4154 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4156 bgp_unlock_node(rn
);
4161 void bgp_reset(void)
4164 bgp_zclient_reset();
4165 access_list_reset();
4166 prefix_list_reset();
4169 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4171 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4172 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4173 PEER_CAP_ADDPATH_AF_TX_RCV
));
4176 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4178 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4179 struct bgp_nlri
*packet
)
4188 int addpath_encoded
;
4189 uint32_t addpath_id
;
4192 lim
= pnt
+ packet
->length
;
4194 safi
= packet
->safi
;
4196 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4198 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4199 syntactic validity. If the field is syntactically incorrect,
4200 then the Error Subcode is set to Invalid Network Field. */
4201 for (; pnt
< lim
; pnt
+= psize
) {
4202 /* Clear prefix structure. */
4203 memset(&p
, 0, sizeof(struct prefix
));
4205 if (addpath_encoded
) {
4207 /* When packet overflow occurs return immediately. */
4208 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4211 addpath_id
= ntohl(*((uint32_t *)pnt
));
4212 pnt
+= BGP_ADDPATH_ID_LEN
;
4215 /* Fetch prefix length. */
4216 p
.prefixlen
= *pnt
++;
4217 /* afi/safi validity already verified by caller,
4218 * bgp_update_receive */
4219 p
.family
= afi2family(afi
);
4221 /* Prefix length check. */
4222 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4225 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4226 peer
->host
, p
.prefixlen
, packet
->afi
);
4230 /* Packet size overflow check. */
4231 psize
= PSIZE(p
.prefixlen
);
4233 /* When packet overflow occur return immediately. */
4234 if (pnt
+ psize
> lim
) {
4237 "%s [Error] Update packet error (prefix length %d overflows packet)",
4238 peer
->host
, p
.prefixlen
);
4242 /* Defensive coding, double-check the psize fits in a struct
4244 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4247 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4248 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4252 /* Fetch prefix from NLRI packet. */
4253 memcpy(p
.u
.val
, pnt
, psize
);
4255 /* Check address. */
4256 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4257 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4258 /* From RFC4271 Section 6.3:
4260 * If a prefix in the NLRI field is semantically
4262 * (e.g., an unexpected multicast IP address),
4264 * be logged locally, and the prefix SHOULD be
4269 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4270 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4275 /* Check address. */
4276 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4277 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4282 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4284 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4289 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4294 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4296 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4303 /* Normal process. */
4305 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4306 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4307 NULL
, NULL
, 0, 0, NULL
);
4309 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4310 safi
, ZEBRA_ROUTE_BGP
,
4311 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4314 /* Address family configuration mismatch or maximum-prefix count
4320 /* Packet length consistency check. */
4324 "%s [Error] Update packet error (prefix length mismatch with total length)",
4332 static struct bgp_static
*bgp_static_new(void)
4334 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4337 static void bgp_static_free(struct bgp_static
*bgp_static
)
4339 if (bgp_static
->rmap
.name
)
4340 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4341 if (bgp_static
->eth_s_id
)
4342 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4343 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4346 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4347 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4349 struct bgp_node
*rn
;
4350 struct bgp_info
*ri
;
4351 struct bgp_info
*new;
4352 struct bgp_info info
;
4354 struct attr
*attr_new
;
4357 int vnc_implicit_withdraw
= 0;
4364 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4366 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4368 attr
.nexthop
= bgp_static
->igpnexthop
;
4369 attr
.med
= bgp_static
->igpmetric
;
4370 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4372 if (bgp_static
->atomic
)
4373 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4375 /* Store label index, if required. */
4376 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4377 attr
.label_index
= bgp_static
->label_index
;
4378 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4381 /* Apply route-map. */
4382 if (bgp_static
->rmap
.name
) {
4383 struct attr attr_tmp
= attr
;
4385 memset(&info
, 0, sizeof(struct bgp_info
));
4386 info
.peer
= bgp
->peer_self
;
4387 info
.attr
= &attr_tmp
;
4389 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4391 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4393 bgp
->peer_self
->rmap_type
= 0;
4395 if (ret
== RMAP_DENYMATCH
) {
4396 /* Free uninterned attribute. */
4397 bgp_attr_flush(&attr_tmp
);
4399 /* Unintern original. */
4400 aspath_unintern(&attr
.aspath
);
4401 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4405 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4406 bgp_attr_add_gshut_community(&attr_tmp
);
4408 attr_new
= bgp_attr_intern(&attr_tmp
);
4411 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4412 bgp_attr_add_gshut_community(&attr
);
4414 attr_new
= bgp_attr_intern(&attr
);
4417 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4418 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4419 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4423 if (attrhash_cmp(ri
->attr
, attr_new
)
4424 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4425 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4426 bgp_unlock_node(rn
);
4427 bgp_attr_unintern(&attr_new
);
4428 aspath_unintern(&attr
.aspath
);
4431 /* The attribute is changed. */
4432 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4434 /* Rewrite BGP route information. */
4435 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4436 bgp_info_restore(rn
, ri
);
4438 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4440 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4441 && (safi
== SAFI_UNICAST
)) {
4442 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4444 * Implicit withdraw case.
4445 * We have to do this before ri is
4448 ++vnc_implicit_withdraw
;
4449 vnc_import_bgp_del_route(bgp
, p
, ri
);
4450 vnc_import_bgp_exterior_del_route(
4455 bgp_attr_unintern(&ri
->attr
);
4456 ri
->attr
= attr_new
;
4457 ri
->uptime
= bgp_clock();
4459 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4460 && (safi
== SAFI_UNICAST
)) {
4461 if (vnc_implicit_withdraw
) {
4462 vnc_import_bgp_add_route(bgp
, p
, ri
);
4463 vnc_import_bgp_exterior_add_route(
4469 /* Nexthop reachability check. */
4470 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4471 && (safi
== SAFI_UNICAST
4472 || safi
== SAFI_LABELED_UNICAST
)) {
4474 struct bgp
*bgp_nexthop
= bgp
;
4476 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4477 bgp_nexthop
= ri
->extra
->bgp_orig
;
4479 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4481 bgp_info_set_flag(rn
, ri
,
4484 if (BGP_DEBUG(nht
, NHT
)) {
4485 char buf1
[INET6_ADDRSTRLEN
];
4486 inet_ntop(p
->family
,
4490 "%s(%s): Route not in table, not advertising",
4491 __FUNCTION__
, buf1
);
4493 bgp_info_unset_flag(rn
, ri
,
4497 /* Delete the NHT structure if any, if we're
4499 * enabling/disabling import check. We
4500 * deregister the route
4501 * from NHT to avoid overloading NHT and the
4502 * process interaction
4504 bgp_unlink_nexthop(ri
);
4505 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4507 /* Process change. */
4508 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4509 bgp_process(bgp
, rn
, afi
, safi
);
4511 if (SAFI_UNICAST
== safi
4512 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4514 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4515 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4519 bgp_unlock_node(rn
);
4520 aspath_unintern(&attr
.aspath
);
4525 /* Make new BGP info. */
4526 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4528 /* Nexthop reachability check. */
4529 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4530 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4531 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4532 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4534 if (BGP_DEBUG(nht
, NHT
)) {
4535 char buf1
[INET6_ADDRSTRLEN
];
4536 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4539 "%s(%s): Route not in table, not advertising",
4540 __FUNCTION__
, buf1
);
4542 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4545 /* Delete the NHT structure if any, if we're toggling between
4546 * enabling/disabling import check. We deregister the route
4547 * from NHT to avoid overloading NHT and the process interaction
4549 bgp_unlink_nexthop(new);
4551 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4554 /* Aggregate address increment. */
4555 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4557 /* Register new BGP information. */
4558 bgp_info_add(rn
, new);
4560 /* route_node_get lock */
4561 bgp_unlock_node(rn
);
4563 /* Process change. */
4564 bgp_process(bgp
, rn
, afi
, safi
);
4566 if (SAFI_UNICAST
== safi
4567 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4568 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4569 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4572 /* Unintern original. */
4573 aspath_unintern(&attr
.aspath
);
4576 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4579 struct bgp_node
*rn
;
4580 struct bgp_info
*ri
;
4582 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4584 /* Check selected route and self inserted route. */
4585 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4586 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4587 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4590 /* Withdraw static BGP route from routing table. */
4592 if (SAFI_UNICAST
== safi
4593 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4594 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4595 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4597 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4598 bgp_unlink_nexthop(ri
);
4599 bgp_info_delete(rn
, ri
);
4600 bgp_process(bgp
, rn
, afi
, safi
);
4603 /* Unlock bgp_node_lookup. */
4604 bgp_unlock_node(rn
);
4608 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4610 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4611 afi_t afi
, safi_t safi
,
4612 struct prefix_rd
*prd
)
4614 struct bgp_node
*rn
;
4615 struct bgp_info
*ri
;
4617 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4619 /* Check selected route and self inserted route. */
4620 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4621 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4622 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4625 /* Withdraw static BGP route from routing table. */
4628 rfapiProcessWithdraw(
4629 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4630 1); /* Kill, since it is an administrative change */
4632 if (SAFI_MPLS_VPN
== safi
4633 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4634 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4636 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4637 bgp_info_delete(rn
, ri
);
4638 bgp_process(bgp
, rn
, afi
, safi
);
4641 /* Unlock bgp_node_lookup. */
4642 bgp_unlock_node(rn
);
4645 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4646 struct bgp_static
*bgp_static
, afi_t afi
,
4649 struct bgp_node
*rn
;
4650 struct bgp_info
*new;
4651 struct attr
*attr_new
;
4652 struct attr attr
= {0};
4653 struct bgp_info
*ri
;
4655 mpls_label_t label
= 0;
4657 uint32_t num_labels
= 0;
4662 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4664 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4667 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4669 attr
.nexthop
= bgp_static
->igpnexthop
;
4670 attr
.med
= bgp_static
->igpmetric
;
4671 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4673 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4674 || (safi
== SAFI_ENCAP
)) {
4675 if (afi
== AFI_IP
) {
4676 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4677 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4680 if (afi
== AFI_L2VPN
) {
4681 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4683 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4684 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4685 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4686 sizeof(struct in6_addr
));
4687 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4688 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4689 struct bgp_encap_type_vxlan bet
;
4690 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4691 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4692 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4694 if (bgp_static
->router_mac
) {
4695 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4698 /* Apply route-map. */
4699 if (bgp_static
->rmap
.name
) {
4700 struct attr attr_tmp
= attr
;
4701 struct bgp_info info
;
4704 info
.peer
= bgp
->peer_self
;
4705 info
.attr
= &attr_tmp
;
4707 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4709 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4711 bgp
->peer_self
->rmap_type
= 0;
4713 if (ret
== RMAP_DENYMATCH
) {
4714 /* Free uninterned attribute. */
4715 bgp_attr_flush(&attr_tmp
);
4717 /* Unintern original. */
4718 aspath_unintern(&attr
.aspath
);
4719 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4724 attr_new
= bgp_attr_intern(&attr_tmp
);
4726 attr_new
= bgp_attr_intern(&attr
);
4729 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4730 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4731 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4736 memset(&add
, 0, sizeof(union gw_addr
));
4737 if (attrhash_cmp(ri
->attr
, attr_new
)
4738 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4739 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4740 bgp_unlock_node(rn
);
4741 bgp_attr_unintern(&attr_new
);
4742 aspath_unintern(&attr
.aspath
);
4745 /* The attribute is changed. */
4746 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4748 /* Rewrite BGP route information. */
4749 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4750 bgp_info_restore(rn
, ri
);
4752 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4753 bgp_attr_unintern(&ri
->attr
);
4754 ri
->attr
= attr_new
;
4755 ri
->uptime
= bgp_clock();
4758 label
= decode_label(&ri
->extra
->label
[0]);
4761 /* Process change. */
4762 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4763 bgp_process(bgp
, rn
, afi
, safi
);
4765 if (SAFI_MPLS_VPN
== safi
4766 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4767 vpn_leak_to_vrf_update(bgp
, ri
);
4770 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4771 ri
->attr
, afi
, safi
, ri
->type
,
4772 ri
->sub_type
, &label
);
4774 bgp_unlock_node(rn
);
4775 aspath_unintern(&attr
.aspath
);
4781 /* Make new BGP info. */
4782 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4784 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4785 new->extra
= bgp_info_extra_new();
4787 new->extra
->label
[0] = bgp_static
->label
;
4788 new->extra
->num_labels
= num_labels
;
4791 label
= decode_label(&bgp_static
->label
);
4794 /* Aggregate address increment. */
4795 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4797 /* Register new BGP information. */
4798 bgp_info_add(rn
, new);
4799 /* route_node_get lock */
4800 bgp_unlock_node(rn
);
4802 /* Process change. */
4803 bgp_process(bgp
, rn
, afi
, safi
);
4805 if (SAFI_MPLS_VPN
== safi
4806 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4807 vpn_leak_to_vrf_update(bgp
, new);
4810 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4811 safi
, new->type
, new->sub_type
, &label
);
4814 /* Unintern original. */
4815 aspath_unintern(&attr
.aspath
);
4818 /* Configure static BGP network. When user don't run zebra, static
4819 route should be installed as valid. */
4820 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4821 const char *ip_str
, afi_t afi
, safi_t safi
,
4822 const char *rmap
, int backdoor
, uint32_t label_index
)
4824 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4827 struct bgp_static
*bgp_static
;
4828 struct bgp_node
*rn
;
4829 uint8_t need_update
= 0;
4831 /* Convert IP prefix string to struct prefix. */
4832 ret
= str2prefix(ip_str
, &p
);
4834 vty_out(vty
, "%% Malformed prefix\n");
4835 return CMD_WARNING_CONFIG_FAILED
;
4837 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4838 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4839 return CMD_WARNING_CONFIG_FAILED
;
4846 /* Set BGP static route configuration. */
4847 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4850 vty_out(vty
, "%% Can't find static route specified\n");
4851 return CMD_WARNING_CONFIG_FAILED
;
4854 bgp_static
= rn
->info
;
4856 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4857 && (label_index
!= bgp_static
->label_index
)) {
4859 "%% label-index doesn't match static route\n");
4860 return CMD_WARNING_CONFIG_FAILED
;
4863 if ((rmap
&& bgp_static
->rmap
.name
)
4864 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4866 "%% route-map name doesn't match static route\n");
4867 return CMD_WARNING_CONFIG_FAILED
;
4870 /* Update BGP RIB. */
4871 if (!bgp_static
->backdoor
)
4872 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4874 /* Clear configuration. */
4875 bgp_static_free(bgp_static
);
4877 bgp_unlock_node(rn
);
4878 bgp_unlock_node(rn
);
4881 /* Set BGP static route configuration. */
4882 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4885 /* Configuration change. */
4886 bgp_static
= rn
->info
;
4888 /* Label index cannot be changed. */
4889 if (bgp_static
->label_index
!= label_index
) {
4890 vty_out(vty
, "%% cannot change label-index\n");
4891 return CMD_WARNING_CONFIG_FAILED
;
4894 /* Check previous routes are installed into BGP. */
4895 if (bgp_static
->valid
4896 && bgp_static
->backdoor
!= backdoor
)
4899 bgp_static
->backdoor
= backdoor
;
4902 if (bgp_static
->rmap
.name
)
4903 XFREE(MTYPE_ROUTE_MAP_NAME
,
4904 bgp_static
->rmap
.name
);
4905 bgp_static
->rmap
.name
=
4906 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4907 bgp_static
->rmap
.map
=
4908 route_map_lookup_by_name(rmap
);
4910 if (bgp_static
->rmap
.name
)
4911 XFREE(MTYPE_ROUTE_MAP_NAME
,
4912 bgp_static
->rmap
.name
);
4913 bgp_static
->rmap
.name
= NULL
;
4914 bgp_static
->rmap
.map
= NULL
;
4915 bgp_static
->valid
= 0;
4917 bgp_unlock_node(rn
);
4919 /* New configuration. */
4920 bgp_static
= bgp_static_new();
4921 bgp_static
->backdoor
= backdoor
;
4922 bgp_static
->valid
= 0;
4923 bgp_static
->igpmetric
= 0;
4924 bgp_static
->igpnexthop
.s_addr
= 0;
4925 bgp_static
->label_index
= label_index
;
4928 if (bgp_static
->rmap
.name
)
4929 XFREE(MTYPE_ROUTE_MAP_NAME
,
4930 bgp_static
->rmap
.name
);
4931 bgp_static
->rmap
.name
=
4932 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4933 bgp_static
->rmap
.map
=
4934 route_map_lookup_by_name(rmap
);
4936 rn
->info
= bgp_static
;
4939 bgp_static
->valid
= 1;
4941 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4943 if (!bgp_static
->backdoor
)
4944 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4950 void bgp_static_add(struct bgp
*bgp
)
4954 struct bgp_node
*rn
;
4955 struct bgp_node
*rm
;
4956 struct bgp_table
*table
;
4957 struct bgp_static
*bgp_static
;
4959 FOREACH_AFI_SAFI (afi
, safi
)
4960 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4961 rn
= bgp_route_next(rn
)) {
4962 if (rn
->info
== NULL
)
4965 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4966 || (safi
== SAFI_EVPN
)) {
4969 for (rm
= bgp_table_top(table
); rm
;
4970 rm
= bgp_route_next(rm
)) {
4971 bgp_static
= rm
->info
;
4972 bgp_static_update_safi(bgp
, &rm
->p
,
4977 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4983 /* Called from bgp_delete(). Delete all static routes from the BGP
4985 void bgp_static_delete(struct bgp
*bgp
)
4989 struct bgp_node
*rn
;
4990 struct bgp_node
*rm
;
4991 struct bgp_table
*table
;
4992 struct bgp_static
*bgp_static
;
4994 FOREACH_AFI_SAFI (afi
, safi
)
4995 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4996 rn
= bgp_route_next(rn
)) {
4997 if (rn
->info
== NULL
)
5000 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5001 || (safi
== SAFI_EVPN
)) {
5004 for (rm
= bgp_table_top(table
); rm
;
5005 rm
= bgp_route_next(rm
)) {
5006 bgp_static
= rm
->info
;
5007 bgp_static_withdraw_safi(
5008 bgp
, &rm
->p
, AFI_IP
, safi
,
5009 (struct prefix_rd
*)&rn
->p
);
5010 bgp_static_free(bgp_static
);
5012 bgp_unlock_node(rn
);
5015 bgp_static
= rn
->info
;
5016 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5017 bgp_static_free(bgp_static
);
5019 bgp_unlock_node(rn
);
5024 void bgp_static_redo_import_check(struct bgp
*bgp
)
5028 struct bgp_node
*rn
;
5029 struct bgp_node
*rm
;
5030 struct bgp_table
*table
;
5031 struct bgp_static
*bgp_static
;
5033 /* Use this flag to force reprocessing of the route */
5034 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5035 FOREACH_AFI_SAFI (afi
, safi
) {
5036 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5037 rn
= bgp_route_next(rn
)) {
5038 if (rn
->info
== NULL
)
5041 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5042 || (safi
== SAFI_EVPN
)) {
5045 for (rm
= bgp_table_top(table
); rm
;
5046 rm
= bgp_route_next(rm
)) {
5047 bgp_static
= rm
->info
;
5048 bgp_static_update_safi(bgp
, &rm
->p
,
5053 bgp_static
= rn
->info
;
5054 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5059 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5062 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5065 struct bgp_table
*table
;
5066 struct bgp_node
*rn
;
5067 struct bgp_info
*ri
;
5069 table
= bgp
->rib
[afi
][safi
];
5070 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5071 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5072 if (ri
->peer
== bgp
->peer_self
5073 && ((ri
->type
== ZEBRA_ROUTE_BGP
5074 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5075 || (ri
->type
!= ZEBRA_ROUTE_BGP
5077 == BGP_ROUTE_REDISTRIBUTE
))) {
5078 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5080 bgp_unlink_nexthop(ri
);
5081 bgp_info_delete(rn
, ri
);
5082 bgp_process(bgp
, rn
, afi
, safi
);
5089 * Purge all networks and redistributed routes from routing table.
5090 * Invoked upon the instance going down.
5092 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5097 FOREACH_AFI_SAFI (afi
, safi
)
5098 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5103 * Currently this is used to set static routes for VPN and ENCAP.
5104 * I think it can probably be factored with bgp_static_set.
5106 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5107 const char *ip_str
, const char *rd_str
,
5108 const char *label_str
, const char *rmap_str
,
5109 int evpn_type
, const char *esi
, const char *gwip
,
5110 const char *ethtag
, const char *routermac
)
5112 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5115 struct prefix_rd prd
;
5116 struct bgp_node
*prn
;
5117 struct bgp_node
*rn
;
5118 struct bgp_table
*table
;
5119 struct bgp_static
*bgp_static
;
5120 mpls_label_t label
= MPLS_INVALID_LABEL
;
5121 struct prefix gw_ip
;
5123 /* validate ip prefix */
5124 ret
= str2prefix(ip_str
, &p
);
5126 vty_out(vty
, "%% Malformed prefix\n");
5127 return CMD_WARNING_CONFIG_FAILED
;
5130 if ((afi
== AFI_L2VPN
)
5131 && (bgp_build_evpn_prefix(evpn_type
,
5132 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5133 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5134 return CMD_WARNING_CONFIG_FAILED
;
5137 ret
= str2prefix_rd(rd_str
, &prd
);
5139 vty_out(vty
, "%% Malformed rd\n");
5140 return CMD_WARNING_CONFIG_FAILED
;
5144 unsigned long label_val
;
5145 label_val
= strtoul(label_str
, NULL
, 10);
5146 encode_label(label_val
, &label
);
5149 if (safi
== SAFI_EVPN
) {
5150 if (esi
&& str2esi(esi
, NULL
) == 0) {
5151 vty_out(vty
, "%% Malformed ESI\n");
5152 return CMD_WARNING_CONFIG_FAILED
;
5154 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5155 vty_out(vty
, "%% Malformed Router MAC\n");
5156 return CMD_WARNING_CONFIG_FAILED
;
5159 memset(&gw_ip
, 0, sizeof(struct prefix
));
5160 ret
= str2prefix(gwip
, &gw_ip
);
5162 vty_out(vty
, "%% Malformed GatewayIp\n");
5163 return CMD_WARNING_CONFIG_FAILED
;
5165 if ((gw_ip
.family
== AF_INET
5166 && is_evpn_prefix_ipaddr_v6(
5167 (struct prefix_evpn
*)&p
))
5168 || (gw_ip
.family
== AF_INET6
5169 && is_evpn_prefix_ipaddr_v4(
5170 (struct prefix_evpn
*)&p
))) {
5172 "%% GatewayIp family differs with IP prefix\n");
5173 return CMD_WARNING_CONFIG_FAILED
;
5177 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5178 if (prn
->info
== NULL
)
5179 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5181 bgp_unlock_node(prn
);
5184 rn
= bgp_node_get(table
, &p
);
5187 vty_out(vty
, "%% Same network configuration exists\n");
5188 bgp_unlock_node(rn
);
5190 /* New configuration. */
5191 bgp_static
= bgp_static_new();
5192 bgp_static
->backdoor
= 0;
5193 bgp_static
->valid
= 0;
5194 bgp_static
->igpmetric
= 0;
5195 bgp_static
->igpnexthop
.s_addr
= 0;
5196 bgp_static
->label
= label
;
5197 bgp_static
->prd
= prd
;
5200 if (bgp_static
->rmap
.name
)
5201 XFREE(MTYPE_ROUTE_MAP_NAME
,
5202 bgp_static
->rmap
.name
);
5203 bgp_static
->rmap
.name
=
5204 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5205 bgp_static
->rmap
.map
=
5206 route_map_lookup_by_name(rmap_str
);
5209 if (safi
== SAFI_EVPN
) {
5211 bgp_static
->eth_s_id
=
5213 sizeof(struct eth_segment_id
));
5214 str2esi(esi
, bgp_static
->eth_s_id
);
5217 bgp_static
->router_mac
=
5218 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5219 (void)prefix_str2mac(routermac
,
5220 bgp_static
->router_mac
);
5223 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5225 rn
->info
= bgp_static
;
5227 bgp_static
->valid
= 1;
5228 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5234 /* Configure static BGP network. */
5235 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5236 const char *ip_str
, const char *rd_str
,
5237 const char *label_str
, int evpn_type
, const char *esi
,
5238 const char *gwip
, const char *ethtag
)
5240 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5243 struct prefix_rd prd
;
5244 struct bgp_node
*prn
;
5245 struct bgp_node
*rn
;
5246 struct bgp_table
*table
;
5247 struct bgp_static
*bgp_static
;
5248 mpls_label_t label
= MPLS_INVALID_LABEL
;
5250 /* Convert IP prefix string to struct prefix. */
5251 ret
= str2prefix(ip_str
, &p
);
5253 vty_out(vty
, "%% Malformed prefix\n");
5254 return CMD_WARNING_CONFIG_FAILED
;
5257 if ((afi
== AFI_L2VPN
)
5258 && (bgp_build_evpn_prefix(evpn_type
,
5259 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5260 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5261 return CMD_WARNING_CONFIG_FAILED
;
5263 ret
= str2prefix_rd(rd_str
, &prd
);
5265 vty_out(vty
, "%% Malformed rd\n");
5266 return CMD_WARNING_CONFIG_FAILED
;
5270 unsigned long label_val
;
5271 label_val
= strtoul(label_str
, NULL
, 10);
5272 encode_label(label_val
, &label
);
5275 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5276 if (prn
->info
== NULL
)
5277 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5279 bgp_unlock_node(prn
);
5282 rn
= bgp_node_lookup(table
, &p
);
5285 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5287 bgp_static
= rn
->info
;
5288 bgp_static_free(bgp_static
);
5290 bgp_unlock_node(rn
);
5291 bgp_unlock_node(rn
);
5293 vty_out(vty
, "%% Can't find the route\n");
5298 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5299 const char *rmap_name
)
5301 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5302 struct bgp_rmap
*rmap
;
5304 rmap
= &bgp
->table_map
[afi
][safi
];
5307 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5308 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5309 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5312 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5317 if (bgp_fibupd_safi(safi
))
5318 bgp_zebra_announce_table(bgp
, afi
, safi
);
5323 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5324 const char *rmap_name
)
5326 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5327 struct bgp_rmap
*rmap
;
5329 rmap
= &bgp
->table_map
[afi
][safi
];
5331 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5335 if (bgp_fibupd_safi(safi
))
5336 bgp_zebra_announce_table(bgp
, afi
, safi
);
5341 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5344 if (bgp
->table_map
[afi
][safi
].name
) {
5345 vty_out(vty
, " table-map %s\n",
5346 bgp
->table_map
[afi
][safi
].name
);
5350 DEFUN (bgp_table_map
,
5353 "BGP table to RIB route download filter\n"
5354 "Name of the route map\n")
5357 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5358 argv
[idx_word
]->arg
);
5360 DEFUN (no_bgp_table_map
,
5361 no_bgp_table_map_cmd
,
5362 "no table-map WORD",
5364 "BGP table to RIB route download filter\n"
5365 "Name of the route map\n")
5368 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5369 argv
[idx_word
]->arg
);
5375 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5376 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5377 backdoor$backdoor}]",
5379 "Specify a network to announce via BGP\n"
5384 "Route-map to modify the attributes\n"
5385 "Name of the route map\n"
5386 "Label index to associate with the prefix\n"
5387 "Label index value\n"
5388 "Specify a BGP backdoor route\n")
5390 char addr_prefix_str
[BUFSIZ
];
5395 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5398 vty_out(vty
, "%% Inconsistent address and mask\n");
5399 return CMD_WARNING_CONFIG_FAILED
;
5403 return bgp_static_set(
5404 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5405 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5406 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5409 DEFPY(ipv6_bgp_network
,
5410 ipv6_bgp_network_cmd
,
5411 "[no] network X:X::X:X/M$prefix \
5412 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5414 "Specify a network to announce via BGP\n"
5416 "Route-map to modify the attributes\n"
5417 "Name of the route map\n"
5418 "Label index to associate with the prefix\n"
5419 "Label index value\n")
5421 return bgp_static_set(
5422 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5423 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5426 /* Aggreagete address:
5428 advertise-map Set condition to advertise attribute
5429 as-set Generate AS set path information
5430 attribute-map Set attributes of aggregate
5431 route-map Set parameters of aggregate
5432 summary-only Filter more specific routes from updates
5433 suppress-map Conditionally filter more specific routes from updates
5436 struct bgp_aggregate
{
5437 /* Summary-only flag. */
5438 uint8_t summary_only
;
5440 /* AS set generation. */
5443 /* Route-map for aggregated route. */
5444 struct route_map
*map
;
5446 /* Suppress-count. */
5447 unsigned long count
;
5449 /* SAFI configuration. */
5453 static struct bgp_aggregate
*bgp_aggregate_new(void)
5455 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5458 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5460 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5463 static int bgp_aggregate_info_same(struct bgp_info
*ri
, struct aspath
*aspath
,
5464 struct community
*comm
)
5466 static struct aspath
*ae
= NULL
;
5469 ae
= aspath_empty();
5474 if (!aspath_cmp(ri
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5477 if (!community_cmp(ri
->attr
->community
, comm
))
5483 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5484 struct prefix
*p
, uint8_t origin
,
5485 struct aspath
*aspath
,
5486 struct community
*community
,
5487 uint8_t atomic_aggregate
,
5488 struct bgp_aggregate
*aggregate
)
5490 struct bgp_node
*rn
;
5491 struct bgp_table
*table
;
5492 struct bgp_info
*ri
, *new;
5494 table
= bgp
->rib
[afi
][safi
];
5496 rn
= bgp_node_get(table
, p
);
5498 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5499 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5500 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5503 if (aggregate
->count
> 0) {
5505 * If the aggregate information has not changed
5506 * no need to re-install it again.
5508 if (bgp_aggregate_info_same(rn
->info
, aspath
, community
)) {
5509 bgp_unlock_node(rn
);
5512 aspath_free(aspath
);
5514 community_free(community
);
5520 * Mark the old as unusable
5523 bgp_info_delete(rn
, ri
);
5526 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5527 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5528 community
, aggregate
->as_set
,
5531 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5533 bgp_info_add(rn
, new);
5534 bgp_process(bgp
, rn
, afi
, safi
);
5536 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5537 if (ri
->peer
== bgp
->peer_self
5538 && ri
->type
== ZEBRA_ROUTE_BGP
5539 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5542 /* Withdraw static BGP route from routing table. */
5544 bgp_info_delete(rn
, ri
);
5545 bgp_process(bgp
, rn
, afi
, safi
);
5549 bgp_unlock_node(rn
);
5552 /* Update an aggregate as routes are added/removed from the BGP table */
5553 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5554 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5555 struct bgp_info
*del
,
5556 struct bgp_aggregate
*aggregate
)
5558 struct bgp_table
*table
;
5559 struct bgp_node
*top
;
5560 struct bgp_node
*rn
;
5562 struct aspath
*aspath
= NULL
;
5563 struct aspath
*asmerge
= NULL
;
5564 struct community
*community
= NULL
;
5565 struct community
*commerge
= NULL
;
5566 struct bgp_info
*ri
;
5567 unsigned long match
= 0;
5568 uint8_t atomic_aggregate
= 0;
5570 /* ORIGIN attribute: If at least one route among routes that are
5571 aggregated has ORIGIN with the value INCOMPLETE, then the
5572 aggregated route must have the ORIGIN attribute with the value
5573 INCOMPLETE. Otherwise, if at least one route among routes that
5574 are aggregated has ORIGIN with the value EGP, then the aggregated
5575 route must have the origin attribute with the value EGP. In all
5576 other case the value of the ORIGIN attribute of the aggregated
5577 route is INTERNAL. */
5578 origin
= BGP_ORIGIN_IGP
;
5580 table
= bgp
->rib
[afi
][safi
];
5582 top
= bgp_node_get(table
, p
);
5583 for (rn
= bgp_node_get(table
, p
); rn
;
5584 rn
= bgp_route_next_until(rn
, top
)) {
5585 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5590 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5591 if (BGP_INFO_HOLDDOWN(ri
))
5594 if (del
&& ri
== del
)
5598 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5599 atomic_aggregate
= 1;
5601 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5605 * summary-only aggregate route suppress
5606 * aggregated route announcements.
5608 if (aggregate
->summary_only
) {
5609 (bgp_info_extra_get(ri
))->suppress
++;
5610 bgp_info_set_flag(rn
, ri
,
5611 BGP_INFO_ATTR_CHANGED
);
5618 * If at least one route among routes that are
5619 * aggregated has ORIGIN with the value INCOMPLETE,
5620 * then the aggregated route MUST have the ORIGIN
5621 * attribute with the value INCOMPLETE. Otherwise, if
5622 * at least one route among routes that are aggregated
5623 * has ORIGIN with the value EGP, then the aggregated
5624 * route MUST have the ORIGIN attribute with the value
5627 if (origin
< ri
->attr
->origin
)
5628 origin
= ri
->attr
->origin
;
5630 if (!aggregate
->as_set
)
5634 * as-set aggregate route generate origin, as path,
5635 * and community aggregation.
5638 asmerge
= aspath_aggregate(aspath
,
5640 aspath_free(aspath
);
5643 aspath
= aspath_dup(ri
->attr
->aspath
);
5645 if (!ri
->attr
->community
)
5649 commerge
= community_merge(community
,
5650 ri
->attr
->community
);
5651 community
= community_uniq_sort(commerge
);
5652 community_free(commerge
);
5654 community
= community_dup(ri
->attr
->community
);
5657 bgp_process(bgp
, rn
, afi
, safi
);
5659 bgp_unlock_node(top
);
5664 if (aggregate
->summary_only
)
5665 (bgp_info_extra_get(rinew
))->suppress
++;
5667 if (origin
< rinew
->attr
->origin
)
5668 origin
= rinew
->attr
->origin
;
5670 if (aggregate
->as_set
) {
5672 asmerge
= aspath_aggregate(aspath
,
5673 rinew
->attr
->aspath
);
5674 aspath_free(aspath
);
5677 aspath
= aspath_dup(rinew
->attr
->aspath
);
5679 if (rinew
->attr
->community
) {
5681 commerge
= community_merge(
5683 rinew
->attr
->community
);
5685 community_uniq_sort(commerge
);
5686 community_free(commerge
);
5688 community
= community_dup(
5689 rinew
->attr
->community
);
5694 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5695 atomic_aggregate
, aggregate
);
5697 if (aggregate
->count
== 0) {
5699 aspath_free(aspath
);
5701 community_free(community
);
5705 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5706 safi_t safi
, struct bgp_aggregate
*aggregate
)
5708 struct bgp_table
*table
;
5709 struct bgp_node
*top
;
5710 struct bgp_node
*rn
;
5711 struct bgp_info
*ri
;
5712 unsigned long match
;
5714 table
= bgp
->rib
[afi
][safi
];
5716 /* If routes exists below this node, generate aggregate routes. */
5717 top
= bgp_node_get(table
, p
);
5718 for (rn
= bgp_node_get(table
, p
); rn
;
5719 rn
= bgp_route_next_until(rn
, top
)) {
5720 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5724 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5725 if (BGP_INFO_HOLDDOWN(ri
))
5728 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5731 if (aggregate
->summary_only
&& ri
->extra
) {
5732 ri
->extra
->suppress
--;
5734 if (ri
->extra
->suppress
== 0) {
5736 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5743 /* If this node was suppressed, process the change. */
5745 bgp_process(bgp
, rn
, afi
, safi
);
5747 bgp_unlock_node(top
);
5750 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5751 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5753 struct bgp_node
*child
;
5754 struct bgp_node
*rn
;
5755 struct bgp_aggregate
*aggregate
;
5756 struct bgp_table
*table
;
5758 table
= bgp
->aggregate
[afi
][safi
];
5760 /* No aggregates configured. */
5761 if (bgp_table_top_nolock(table
) == NULL
)
5764 if (p
->prefixlen
== 0)
5767 if (BGP_INFO_HOLDDOWN(ri
))
5770 child
= bgp_node_get(table
, p
);
5772 /* Aggregate address configuration check. */
5773 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5774 if ((aggregate
= rn
->info
) != NULL
5775 && rn
->p
.prefixlen
< p
->prefixlen
) {
5776 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5777 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5780 bgp_unlock_node(child
);
5783 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5784 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5786 struct bgp_node
*child
;
5787 struct bgp_node
*rn
;
5788 struct bgp_aggregate
*aggregate
;
5789 struct bgp_table
*table
;
5791 table
= bgp
->aggregate
[afi
][safi
];
5793 /* No aggregates configured. */
5794 if (bgp_table_top_nolock(table
) == NULL
)
5797 if (p
->prefixlen
== 0)
5800 child
= bgp_node_get(table
, p
);
5802 /* Aggregate address configuration check. */
5803 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5804 if ((aggregate
= rn
->info
) != NULL
5805 && rn
->p
.prefixlen
< p
->prefixlen
) {
5806 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5807 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5810 bgp_unlock_node(child
);
5813 /* Aggregate route attribute. */
5814 #define AGGREGATE_SUMMARY_ONLY 1
5815 #define AGGREGATE_AS_SET 1
5817 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5818 afi_t afi
, safi_t safi
)
5820 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5823 struct bgp_node
*rn
;
5824 struct bgp_aggregate
*aggregate
;
5826 /* Convert string to prefix structure. */
5827 ret
= str2prefix(prefix_str
, &p
);
5829 vty_out(vty
, "Malformed prefix\n");
5830 return CMD_WARNING_CONFIG_FAILED
;
5834 /* Old configuration check. */
5835 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5838 "%% There is no aggregate-address configuration.\n");
5839 return CMD_WARNING_CONFIG_FAILED
;
5842 aggregate
= rn
->info
;
5843 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5844 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
, 0, aggregate
);
5846 /* Unlock aggregate address configuration. */
5848 bgp_aggregate_free(aggregate
);
5849 bgp_unlock_node(rn
);
5850 bgp_unlock_node(rn
);
5855 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5856 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5858 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5861 struct bgp_node
*rn
;
5862 struct bgp_aggregate
*aggregate
;
5864 /* Convert string to prefix structure. */
5865 ret
= str2prefix(prefix_str
, &p
);
5867 vty_out(vty
, "Malformed prefix\n");
5868 return CMD_WARNING_CONFIG_FAILED
;
5872 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5873 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5874 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5876 return CMD_WARNING_CONFIG_FAILED
;
5879 /* Old configuration check. */
5880 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5883 vty_out(vty
, "There is already same aggregate network.\n");
5884 /* try to remove the old entry */
5885 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5887 vty_out(vty
, "Error deleting aggregate.\n");
5888 bgp_unlock_node(rn
);
5889 return CMD_WARNING_CONFIG_FAILED
;
5893 /* Make aggregate address structure. */
5894 aggregate
= bgp_aggregate_new();
5895 aggregate
->summary_only
= summary_only
;
5896 aggregate
->as_set
= as_set
;
5897 aggregate
->safi
= safi
;
5898 rn
->info
= aggregate
;
5900 /* Aggregate address insert into BGP routing table. */
5901 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
5906 DEFUN (aggregate_address
,
5907 aggregate_address_cmd
,
5908 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5909 "Configure BGP aggregate entries\n"
5910 "Aggregate prefix\n"
5911 "Generate AS set path information\n"
5912 "Filter more specific routes from updates\n"
5913 "Filter more specific routes from updates\n"
5914 "Generate AS set path information\n")
5917 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5918 char *prefix
= argv
[idx
]->arg
;
5920 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5922 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5923 ? AGGREGATE_SUMMARY_ONLY
5926 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5927 summary_only
, as_set
);
5930 DEFUN (aggregate_address_mask
,
5931 aggregate_address_mask_cmd
,
5932 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5933 "Configure BGP aggregate entries\n"
5934 "Aggregate address\n"
5936 "Generate AS set path information\n"
5937 "Filter more specific routes from updates\n"
5938 "Filter more specific routes from updates\n"
5939 "Generate AS set path information\n")
5942 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5943 char *prefix
= argv
[idx
]->arg
;
5944 char *mask
= argv
[idx
+ 1]->arg
;
5946 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5948 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5949 ? AGGREGATE_SUMMARY_ONLY
5952 char prefix_str
[BUFSIZ
];
5953 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5956 vty_out(vty
, "%% Inconsistent address and mask\n");
5957 return CMD_WARNING_CONFIG_FAILED
;
5960 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5961 summary_only
, as_set
);
5964 DEFUN (no_aggregate_address
,
5965 no_aggregate_address_cmd
,
5966 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5968 "Configure BGP aggregate entries\n"
5969 "Aggregate prefix\n"
5970 "Generate AS set path information\n"
5971 "Filter more specific routes from updates\n"
5972 "Filter more specific routes from updates\n"
5973 "Generate AS set path information\n")
5976 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5977 char *prefix
= argv
[idx
]->arg
;
5978 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5981 DEFUN (no_aggregate_address_mask
,
5982 no_aggregate_address_mask_cmd
,
5983 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5985 "Configure BGP aggregate entries\n"
5986 "Aggregate address\n"
5988 "Generate AS set path information\n"
5989 "Filter more specific routes from updates\n"
5990 "Filter more specific routes from updates\n"
5991 "Generate AS set path information\n")
5994 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5995 char *prefix
= argv
[idx
]->arg
;
5996 char *mask
= argv
[idx
+ 1]->arg
;
5998 char prefix_str
[BUFSIZ
];
5999 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6002 vty_out(vty
, "%% Inconsistent address and mask\n");
6003 return CMD_WARNING_CONFIG_FAILED
;
6006 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6009 DEFUN (ipv6_aggregate_address
,
6010 ipv6_aggregate_address_cmd
,
6011 "aggregate-address X:X::X:X/M [summary-only]",
6012 "Configure BGP aggregate entries\n"
6013 "Aggregate prefix\n"
6014 "Filter more specific routes from updates\n")
6017 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6018 char *prefix
= argv
[idx
]->arg
;
6019 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6020 ? AGGREGATE_SUMMARY_ONLY
6022 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6026 DEFUN (no_ipv6_aggregate_address
,
6027 no_ipv6_aggregate_address_cmd
,
6028 "no aggregate-address X:X::X:X/M [summary-only]",
6030 "Configure BGP aggregate entries\n"
6031 "Aggregate prefix\n"
6032 "Filter more specific routes from updates\n")
6035 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6036 char *prefix
= argv
[idx
]->arg
;
6037 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6040 /* Redistribute route treatment. */
6041 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6042 const union g_addr
*nexthop
, ifindex_t ifindex
,
6043 enum nexthop_types_t nhtype
, uint32_t metric
,
6044 uint8_t type
, unsigned short instance
,
6047 struct bgp_info
*new;
6048 struct bgp_info
*bi
;
6049 struct bgp_info info
;
6050 struct bgp_node
*bn
;
6052 struct attr
*new_attr
;
6055 struct bgp_redist
*red
;
6057 /* Make default attribute. */
6058 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6061 case NEXTHOP_TYPE_IFINDEX
:
6063 case NEXTHOP_TYPE_IPV4
:
6064 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6065 attr
.nexthop
= nexthop
->ipv4
;
6067 case NEXTHOP_TYPE_IPV6
:
6068 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6069 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6070 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6072 case NEXTHOP_TYPE_BLACKHOLE
:
6073 switch (p
->family
) {
6075 attr
.nexthop
.s_addr
= INADDR_ANY
;
6078 memset(&attr
.mp_nexthop_global
, 0,
6079 sizeof(attr
.mp_nexthop_global
));
6080 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6085 attr
.nh_ifindex
= ifindex
;
6088 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6091 afi
= family2afi(p
->family
);
6093 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6095 struct attr attr_new
;
6097 /* Copy attribute for modification. */
6098 bgp_attr_dup(&attr_new
, &attr
);
6100 if (red
->redist_metric_flag
)
6101 attr_new
.med
= red
->redist_metric
;
6103 /* Apply route-map. */
6104 if (red
->rmap
.name
) {
6105 memset(&info
, 0, sizeof(struct bgp_info
));
6106 info
.peer
= bgp
->peer_self
;
6107 info
.attr
= &attr_new
;
6109 SET_FLAG(bgp
->peer_self
->rmap_type
,
6110 PEER_RMAP_TYPE_REDISTRIBUTE
);
6112 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6115 bgp
->peer_self
->rmap_type
= 0;
6117 if (ret
== RMAP_DENYMATCH
) {
6118 /* Free uninterned attribute. */
6119 bgp_attr_flush(&attr_new
);
6121 /* Unintern original. */
6122 aspath_unintern(&attr
.aspath
);
6123 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6128 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6129 bgp_attr_add_gshut_community(&attr_new
);
6131 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6132 SAFI_UNICAST
, p
, NULL
);
6134 new_attr
= bgp_attr_intern(&attr_new
);
6136 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6137 if (bi
->peer
== bgp
->peer_self
6138 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6142 /* Ensure the (source route) type is updated. */
6144 if (attrhash_cmp(bi
->attr
, new_attr
)
6145 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6146 bgp_attr_unintern(&new_attr
);
6147 aspath_unintern(&attr
.aspath
);
6148 bgp_unlock_node(bn
);
6151 /* The attribute is changed. */
6152 bgp_info_set_flag(bn
, bi
,
6153 BGP_INFO_ATTR_CHANGED
);
6155 /* Rewrite BGP route information. */
6156 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6157 bgp_info_restore(bn
, bi
);
6159 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6161 bgp_attr_unintern(&bi
->attr
);
6162 bi
->attr
= new_attr
;
6163 bi
->uptime
= bgp_clock();
6165 /* Process change. */
6166 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6168 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6169 bgp_unlock_node(bn
);
6170 aspath_unintern(&attr
.aspath
);
6172 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6174 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6176 vpn_leak_from_vrf_update(
6177 bgp_get_default(), bgp
, bi
);
6183 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6184 bgp
->peer_self
, new_attr
, bn
);
6185 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6187 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6188 bgp_info_add(bn
, new);
6189 bgp_unlock_node(bn
);
6190 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6192 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6193 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6195 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6199 /* Unintern original. */
6200 aspath_unintern(&attr
.aspath
);
6203 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6204 unsigned short instance
)
6207 struct bgp_node
*rn
;
6208 struct bgp_info
*ri
;
6209 struct bgp_redist
*red
;
6211 afi
= family2afi(p
->family
);
6213 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6215 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6216 SAFI_UNICAST
, p
, NULL
);
6218 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6219 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6223 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6224 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6226 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6229 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6230 bgp_info_delete(rn
, ri
);
6231 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6233 bgp_unlock_node(rn
);
6237 /* Withdraw specified route type's route. */
6238 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6239 unsigned short instance
)
6241 struct bgp_node
*rn
;
6242 struct bgp_info
*ri
;
6243 struct bgp_table
*table
;
6245 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6247 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6248 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6249 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6250 && ri
->instance
== instance
)
6254 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6255 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6257 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6260 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6262 bgp_info_delete(rn
, ri
);
6263 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6268 /* Static function to display route. */
6269 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6275 if (p
->family
== AF_INET
) {
6279 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6282 json_object_string_add(json
, "prefix",
6283 inet_ntop(p
->family
,
6286 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6288 } else if (p
->family
== AF_ETHERNET
) {
6289 prefix2str(p
, buf
, PREFIX_STRLEN
);
6290 len
= vty_out(vty
, "%s", buf
);
6291 } else if (p
->family
== AF_EVPN
) {
6295 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6298 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6299 } else if (p
->family
== AF_FLOWSPEC
) {
6300 route_vty_out_flowspec(vty
, p
, NULL
,
6302 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6303 NLRI_STRING_FORMAT_MIN
, json
);
6308 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6315 vty_out(vty
, "\n%*s", 20, " ");
6317 vty_out(vty
, "%*s", len
, " ");
6321 enum bgp_display_type
{
6325 /* Print the short form route status for a bgp_info */
6326 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6327 json_object
*json_path
)
6331 /* Route status display. */
6332 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6333 json_object_boolean_true_add(json_path
, "removed");
6335 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6336 json_object_boolean_true_add(json_path
, "stale");
6338 if (binfo
->extra
&& binfo
->extra
->suppress
)
6339 json_object_boolean_true_add(json_path
, "suppressed");
6341 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6342 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6343 json_object_boolean_true_add(json_path
, "valid");
6346 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6347 json_object_boolean_true_add(json_path
, "history");
6349 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6350 json_object_boolean_true_add(json_path
, "damped");
6352 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6353 json_object_boolean_true_add(json_path
, "bestpath");
6355 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6356 json_object_boolean_true_add(json_path
, "multipath");
6358 /* Internal route. */
6359 if ((binfo
->peer
->as
)
6360 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6361 json_object_string_add(json_path
, "pathFrom",
6364 json_object_string_add(json_path
, "pathFrom",
6370 /* Route status display. */
6371 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6373 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6375 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6377 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6378 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6384 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6386 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6388 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6390 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6395 /* Internal route. */
6396 if (binfo
->peer
&& (binfo
->peer
->as
)
6397 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6403 /* called from terminal list command */
6404 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6405 int display
, safi_t safi
, json_object
*json_paths
)
6408 json_object
*json_path
= NULL
;
6409 json_object
*json_nexthops
= NULL
;
6410 json_object
*json_nexthop_global
= NULL
;
6411 json_object
*json_nexthop_ll
= NULL
;
6412 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6413 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6416 bool nexthop_othervrf
= false;
6417 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6418 const char *nexthop_vrfname
= "Default";
6421 json_path
= json_object_new_object();
6423 /* short status lead text */
6424 route_vty_short_status_out(vty
, binfo
, json_path
);
6427 /* print prefix and mask */
6429 route_vty_out_route(p
, vty
, json_path
);
6431 vty_out(vty
, "%*s", 17, " ");
6433 route_vty_out_route(p
, vty
, json_path
);
6436 /* Print attribute */
6440 json_object_array_add(json_paths
, json_path
);
6448 * If vrf id of nexthop is different from that of prefix,
6449 * set up printable string to append
6451 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6452 const char *self
= "";
6457 nexthop_othervrf
= true;
6458 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6460 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6461 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6462 "@%s%s", VRFID_NONE_STR
, self
);
6464 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6465 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6467 if (binfo
->extra
->bgp_orig
->inst_type
!=
6468 BGP_INSTANCE_TYPE_DEFAULT
)
6470 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6472 const char *self
= "";
6477 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6481 * For ENCAP and EVPN routes, nexthop address family is not
6482 * neccessarily the same as the prefix address family.
6483 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6484 * EVPN routes are also exchanged with a MP nexthop. Currently,
6486 * is only IPv4, the value will be present in either
6488 * attr->mp_nexthop_global_in
6490 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6493 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6497 sprintf(nexthop
, "%s",
6498 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6502 sprintf(nexthop
, "%s",
6503 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6507 sprintf(nexthop
, "?");
6512 json_nexthop_global
= json_object_new_object();
6514 json_object_string_add(json_nexthop_global
, "afi",
6515 (af
== AF_INET
) ? "ip" : "ipv6");
6516 json_object_string_add(json_nexthop_global
,
6517 (af
== AF_INET
) ? "ip" : "ipv6",
6519 json_object_boolean_true_add(json_nexthop_global
,
6522 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6523 } else if (safi
== SAFI_EVPN
) {
6525 json_nexthop_global
= json_object_new_object();
6527 json_object_string_add(json_nexthop_global
, "ip",
6528 inet_ntoa(attr
->nexthop
));
6529 json_object_string_add(json_nexthop_global
, "afi",
6531 json_object_boolean_true_add(json_nexthop_global
,
6534 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6536 } else if (safi
== SAFI_FLOWSPEC
) {
6537 if (attr
->nexthop
.s_addr
!= 0) {
6539 json_nexthop_global
= json_object_new_object();
6540 json_object_string_add(
6541 json_nexthop_global
, "ip",
6542 inet_ntoa(attr
->nexthop
));
6543 json_object_string_add(json_nexthop_global
,
6545 json_object_boolean_true_add(json_nexthop_global
,
6548 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6551 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6553 json_nexthop_global
= json_object_new_object();
6555 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6556 json_object_string_add(
6557 json_nexthop_global
, "ip",
6558 inet_ntoa(attr
->mp_nexthop_global_in
));
6560 json_object_string_add(
6561 json_nexthop_global
, "ip",
6562 inet_ntoa(attr
->nexthop
));
6564 json_object_string_add(json_nexthop_global
, "afi",
6566 json_object_boolean_true_add(json_nexthop_global
,
6571 snprintf(buf
, sizeof(buf
), "%s%s",
6572 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6573 vty_out(vty
, "%-16s", buf
);
6578 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6583 json_nexthop_global
= json_object_new_object();
6584 json_object_string_add(
6585 json_nexthop_global
, "ip",
6586 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6588 json_object_string_add(json_nexthop_global
, "afi",
6590 json_object_string_add(json_nexthop_global
, "scope",
6593 /* We display both LL & GL if both have been
6595 if ((attr
->mp_nexthop_len
== 32)
6596 || (binfo
->peer
->conf_if
)) {
6597 json_nexthop_ll
= json_object_new_object();
6598 json_object_string_add(
6599 json_nexthop_ll
, "ip",
6601 &attr
->mp_nexthop_local
, buf
,
6603 json_object_string_add(json_nexthop_ll
, "afi",
6605 json_object_string_add(json_nexthop_ll
, "scope",
6608 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6609 &attr
->mp_nexthop_local
)
6611 && !attr
->mp_nexthop_prefer_global
)
6612 json_object_boolean_true_add(
6613 json_nexthop_ll
, "used");
6615 json_object_boolean_true_add(
6616 json_nexthop_global
, "used");
6618 json_object_boolean_true_add(
6619 json_nexthop_global
, "used");
6621 /* Display LL if LL/Global both in table unless
6622 * prefer-global is set */
6623 if (((attr
->mp_nexthop_len
== 32)
6624 && !attr
->mp_nexthop_prefer_global
)
6625 || (binfo
->peer
->conf_if
)) {
6626 if (binfo
->peer
->conf_if
) {
6627 len
= vty_out(vty
, "%s",
6628 binfo
->peer
->conf_if
);
6629 len
= 16 - len
; /* len of IPv6
6635 vty_out(vty
, "\n%*s", 36, " ");
6637 vty_out(vty
, "%*s", len
, " ");
6643 &attr
->mp_nexthop_local
,
6649 vty_out(vty
, "\n%*s", 36, " ");
6651 vty_out(vty
, "%*s", len
, " ");
6657 &attr
->mp_nexthop_global
, buf
,
6663 vty_out(vty
, "\n%*s", 36, " ");
6665 vty_out(vty
, "%*s", len
, " ");
6671 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6673 json_object_int_add(json_path
, "med", attr
->med
);
6675 vty_out(vty
, "%10u", attr
->med
);
6676 else if (!json_paths
)
6680 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6682 json_object_int_add(json_path
, "localpref",
6685 vty_out(vty
, "%7u", attr
->local_pref
);
6686 else if (!json_paths
)
6690 json_object_int_add(json_path
, "weight", attr
->weight
);
6692 vty_out(vty
, "%7u ", attr
->weight
);
6696 json_object_string_add(
6697 json_path
, "peerId",
6698 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6704 json_object_string_add(json_path
, "aspath",
6707 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6712 json_object_string_add(json_path
, "origin",
6713 bgp_origin_long_str
[attr
->origin
]);
6715 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6719 json_object_boolean_true_add(json_path
,
6720 "announceNexthopSelf");
6721 if (nexthop_othervrf
) {
6722 json_object_string_add(json_path
, "nhVrfName",
6725 json_object_int_add(json_path
, "nhVrfId",
6726 ((nexthop_vrfid
== VRF_UNKNOWN
)
6728 : (int)nexthop_vrfid
));
6733 if (json_nexthop_global
|| json_nexthop_ll
) {
6734 json_nexthops
= json_object_new_array();
6736 if (json_nexthop_global
)
6737 json_object_array_add(json_nexthops
,
6738 json_nexthop_global
);
6740 if (json_nexthop_ll
)
6741 json_object_array_add(json_nexthops
,
6744 json_object_object_add(json_path
, "nexthops",
6748 json_object_array_add(json_paths
, json_path
);
6752 /* prints an additional line, indented, with VNC info, if
6754 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6755 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6760 /* called from terminal list command */
6761 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6762 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6764 json_object
*json_status
= NULL
;
6765 json_object
*json_net
= NULL
;
6767 /* Route status display. */
6769 json_status
= json_object_new_object();
6770 json_net
= json_object_new_object();
6777 /* print prefix and mask */
6779 json_object_string_add(
6780 json_net
, "addrPrefix",
6781 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6783 route_vty_out_route(p
, vty
, NULL
);
6785 /* Print attribute */
6788 if (p
->family
== AF_INET
6789 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6790 || safi
== SAFI_EVPN
6791 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6792 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6793 || safi
== SAFI_EVPN
)
6794 json_object_string_add(
6795 json_net
, "nextHop",
6797 attr
->mp_nexthop_global_in
));
6799 json_object_string_add(
6800 json_net
, "nextHop",
6801 inet_ntoa(attr
->nexthop
));
6802 } else if (p
->family
== AF_INET6
6803 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6806 json_object_string_add(
6807 json_net
, "netHopGloabal",
6809 &attr
->mp_nexthop_global
, buf
,
6814 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6815 json_object_int_add(json_net
, "metric",
6818 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6819 json_object_int_add(json_net
, "localPref",
6822 json_object_int_add(json_net
, "weight", attr
->weight
);
6826 json_object_string_add(json_net
, "asPath",
6830 json_object_string_add(json_net
, "bgpOriginCode",
6831 bgp_origin_str
[attr
->origin
]);
6833 if (p
->family
== AF_INET
6834 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6835 || safi
== SAFI_EVPN
6836 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6837 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6838 || safi
== SAFI_EVPN
)
6839 vty_out(vty
, "%-16s",
6841 attr
->mp_nexthop_global_in
));
6843 vty_out(vty
, "%-16s",
6844 inet_ntoa(attr
->nexthop
));
6845 } else if (p
->family
== AF_INET6
6846 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6853 &attr
->mp_nexthop_global
, buf
,
6857 vty_out(vty
, "\n%*s", 36, " ");
6859 vty_out(vty
, "%*s", len
, " ");
6862 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6863 vty_out(vty
, "%10u", attr
->med
);
6867 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6868 vty_out(vty
, "%7u", attr
->local_pref
);
6872 vty_out(vty
, "%7u ", attr
->weight
);
6876 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6879 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6883 json_object_boolean_true_add(json_status
, "*");
6884 json_object_boolean_true_add(json_status
, ">");
6885 json_object_object_add(json_net
, "appliedStatusSymbols",
6887 char buf_cut
[BUFSIZ
];
6888 json_object_object_add(
6890 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6896 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6897 struct bgp_info
*binfo
, int display
, safi_t safi
,
6900 json_object
*json_out
= NULL
;
6902 mpls_label_t label
= MPLS_INVALID_LABEL
;
6908 json_out
= json_object_new_object();
6910 /* short status lead text */
6911 route_vty_short_status_out(vty
, binfo
, json_out
);
6913 /* print prefix and mask */
6916 route_vty_out_route(p
, vty
, NULL
);
6918 vty_out(vty
, "%*s", 17, " ");
6921 /* Print attribute */
6924 if (((p
->family
== AF_INET
)
6925 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6926 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6927 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6928 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6929 || safi
== SAFI_EVPN
) {
6931 json_object_string_add(
6932 json_out
, "mpNexthopGlobalIn",
6934 attr
->mp_nexthop_global_in
));
6936 vty_out(vty
, "%-16s",
6938 attr
->mp_nexthop_global_in
));
6941 json_object_string_add(
6942 json_out
, "nexthop",
6943 inet_ntoa(attr
->nexthop
));
6945 vty_out(vty
, "%-16s",
6946 inet_ntoa(attr
->nexthop
));
6948 } else if (((p
->family
== AF_INET6
)
6949 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6950 || (safi
== SAFI_EVPN
6951 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6952 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6956 if (attr
->mp_nexthop_len
6957 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6959 json_object_string_add(
6960 json_out
, "mpNexthopGlobalIn",
6963 &attr
->mp_nexthop_global
,
6964 buf_a
, sizeof(buf_a
)));
6969 &attr
->mp_nexthop_global
,
6970 buf_a
, sizeof(buf_a
)));
6971 } else if (attr
->mp_nexthop_len
6972 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6975 &attr
->mp_nexthop_global
,
6976 buf_a
, sizeof(buf_a
));
6978 &attr
->mp_nexthop_local
,
6979 buf_b
, sizeof(buf_b
));
6980 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6981 json_object_string_add(
6983 "mpNexthopGlobalLocal", buf_c
);
6985 vty_out(vty
, "%s(%s)",
6988 &attr
->mp_nexthop_global
,
6989 buf_a
, sizeof(buf_a
)),
6992 &attr
->mp_nexthop_local
,
6993 buf_b
, sizeof(buf_b
)));
6998 label
= decode_label(&binfo
->extra
->label
[0]);
7000 if (bgp_is_valid_label(&label
)) {
7002 json_object_int_add(json_out
, "notag", label
);
7003 json_object_array_add(json
, json_out
);
7005 vty_out(vty
, "notag/%d", label
);
7011 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7012 struct bgp_info
*binfo
, int display
,
7013 json_object
*json_paths
)
7017 json_object
*json_path
= NULL
;
7020 json_path
= json_object_new_object();
7025 /* short status lead text */
7026 route_vty_short_status_out(vty
, binfo
, json_path
);
7028 /* print prefix and mask */
7030 route_vty_out_route(p
, vty
, NULL
);
7032 vty_out(vty
, "%*s", 17, " ");
7034 /* Print attribute */
7038 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7042 vty_out(vty
, "%-16s",
7043 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7047 vty_out(vty
, "%s(%s)",
7048 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7050 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7057 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7059 vty_out(vty
, "%s", str
);
7060 XFREE(MTYPE_TMP
, str
);
7062 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7064 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7065 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7068 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7071 if (attr
->ecommunity
) {
7073 struct ecommunity_val
*routermac
= ecommunity_lookup(
7074 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7075 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7077 mac
= ecom_mac2str((char *)routermac
->val
);
7079 vty_out(vty
, "/%s", (char *)mac
);
7080 XFREE(MTYPE_TMP
, mac
);
7088 /* dampening route */
7089 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7090 struct bgp_info
*binfo
, int display
, safi_t safi
,
7091 uint8_t use_json
, json_object
*json
)
7095 char timebuf
[BGP_UPTIME_LEN
];
7097 /* short status lead text */
7098 route_vty_short_status_out(vty
, binfo
, json
);
7100 /* print prefix and mask */
7103 route_vty_out_route(p
, vty
, NULL
);
7105 vty_out(vty
, "%*s", 17, " ");
7108 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7112 vty_out(vty
, "\n%*s", 34, " ");
7115 json_object_int_add(json
, "peerHost", len
);
7117 vty_out(vty
, "%*s", len
, " ");
7121 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7124 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7128 /* Print attribute */
7134 json_object_string_add(json
, "asPath",
7137 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7142 json_object_string_add(json
, "origin",
7143 bgp_origin_str
[attr
->origin
]);
7145 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7152 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7153 struct bgp_info
*binfo
, int display
, safi_t safi
,
7154 uint8_t use_json
, json_object
*json
)
7157 struct bgp_damp_info
*bdi
;
7158 char timebuf
[BGP_UPTIME_LEN
];
7164 bdi
= binfo
->extra
->damp_info
;
7166 /* short status lead text */
7167 route_vty_short_status_out(vty
, binfo
, json
);
7169 /* print prefix and mask */
7172 route_vty_out_route(p
, vty
, NULL
);
7174 vty_out(vty
, "%*s", 17, " ");
7177 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7181 vty_out(vty
, "\n%*s", 33, " ");
7184 json_object_int_add(json
, "peerHost", len
);
7186 vty_out(vty
, "%*s", len
, " ");
7189 len
= vty_out(vty
, "%d", bdi
->flap
);
7196 json_object_int_add(json
, "bdiFlap", len
);
7198 vty_out(vty
, "%*s", len
, " ");
7202 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7205 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7206 BGP_UPTIME_LEN
, 0, NULL
));
7208 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7209 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7211 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7212 BGP_UPTIME_LEN
, use_json
, json
);
7215 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7220 vty_out(vty
, "%*s ", 8, " ");
7223 /* Print attribute */
7229 json_object_string_add(json
, "asPath",
7232 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7237 json_object_string_add(json
, "origin",
7238 bgp_origin_str
[attr
->origin
]);
7240 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7246 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7247 int *first
, const char *header
,
7248 json_object
*json_adv_to
)
7250 char buf1
[INET6_ADDRSTRLEN
];
7251 json_object
*json_peer
= NULL
;
7254 /* 'advertised-to' is a dictionary of peers we have advertised
7256 * prefix too. The key is the peer's IP or swpX, the value is
7258 * hostname if we know it and "" if not.
7260 json_peer
= json_object_new_object();
7263 json_object_string_add(json_peer
, "hostname",
7267 json_object_object_add(json_adv_to
, peer
->conf_if
,
7270 json_object_object_add(
7272 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7276 vty_out(vty
, "%s", header
);
7281 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7283 vty_out(vty
, " %s(%s)", peer
->hostname
,
7286 vty_out(vty
, " %s(%s)", peer
->hostname
,
7287 sockunion2str(&peer
->su
, buf1
,
7291 vty_out(vty
, " %s", peer
->conf_if
);
7294 sockunion2str(&peer
->su
, buf1
,
7300 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7301 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7302 json_object
*json_paths
)
7304 char buf
[INET6_ADDRSTRLEN
];
7306 char buf2
[EVPN_ROUTE_STRLEN
];
7308 int sockunion_vty_out(struct vty
*, union sockunion
*);
7310 json_object
*json_bestpath
= NULL
;
7311 json_object
*json_cluster_list
= NULL
;
7312 json_object
*json_cluster_list_list
= NULL
;
7313 json_object
*json_ext_community
= NULL
;
7314 json_object
*json_last_update
= NULL
;
7315 json_object
*json_pmsi
= NULL
;
7316 json_object
*json_nexthop_global
= NULL
;
7317 json_object
*json_nexthop_ll
= NULL
;
7318 json_object
*json_nexthops
= NULL
;
7319 json_object
*json_path
= NULL
;
7320 json_object
*json_peer
= NULL
;
7321 json_object
*json_string
= NULL
;
7322 json_object
*json_adv_to
= NULL
;
7324 struct listnode
*node
, *nnode
;
7326 int addpath_capable
;
7328 unsigned int first_as
;
7329 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7334 json_path
= json_object_new_object();
7335 json_peer
= json_object_new_object();
7336 json_nexthop_global
= json_object_new_object();
7339 if (!json_paths
&& safi
== SAFI_EVPN
) {
7342 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7343 vty_out(vty
, " Route %s", buf2
);
7345 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7346 bgp_evpn_label2str(binfo
->extra
->label
,
7347 binfo
->extra
->num_labels
, tag_buf
,
7349 vty_out(vty
, " VNI %s", tag_buf
);
7352 if (binfo
->extra
&& binfo
->extra
->parent
) {
7353 struct bgp_info
*parent_ri
;
7354 struct bgp_node
*rn
, *prn
;
7356 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7357 rn
= parent_ri
->net
;
7358 if (rn
&& rn
->prn
) {
7360 vty_out(vty
, " Imported from %s:%s\n",
7362 (struct prefix_rd
*)&prn
->p
,
7363 buf1
, sizeof(buf1
)),
7372 /* Line1 display AS-path, Aggregator */
7375 if (!attr
->aspath
->json
)
7376 aspath_str_update(attr
->aspath
, true);
7377 json_object_lock(attr
->aspath
->json
);
7378 json_object_object_add(json_path
, "aspath",
7379 attr
->aspath
->json
);
7381 if (attr
->aspath
->segments
)
7382 aspath_print_vty(vty
, " %s",
7385 vty_out(vty
, " Local");
7389 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7391 json_object_boolean_true_add(json_path
,
7394 vty_out(vty
, ", (removed)");
7397 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7399 json_object_boolean_true_add(json_path
,
7402 vty_out(vty
, ", (stale)");
7405 if (CHECK_FLAG(attr
->flag
,
7406 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7408 json_object_int_add(json_path
, "aggregatorAs",
7409 attr
->aggregator_as
);
7410 json_object_string_add(
7411 json_path
, "aggregatorId",
7412 inet_ntoa(attr
->aggregator_addr
));
7414 vty_out(vty
, ", (aggregated by %u %s)",
7415 attr
->aggregator_as
,
7416 inet_ntoa(attr
->aggregator_addr
));
7420 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7421 PEER_FLAG_REFLECTOR_CLIENT
)) {
7423 json_object_boolean_true_add(
7424 json_path
, "rxedFromRrClient");
7426 vty_out(vty
, ", (Received from a RR-client)");
7429 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7430 PEER_FLAG_RSERVER_CLIENT
)) {
7432 json_object_boolean_true_add(
7433 json_path
, "rxedFromRsClient");
7435 vty_out(vty
, ", (Received from a RS-client)");
7438 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7440 json_object_boolean_true_add(
7441 json_path
, "dampeningHistoryEntry");
7443 vty_out(vty
, ", (history entry)");
7444 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7446 json_object_boolean_true_add(
7447 json_path
, "dampeningSuppressed");
7449 vty_out(vty
, ", (suppressed due to dampening)");
7455 /* Line2 display Next-hop, Neighbor, Router-id */
7456 /* Display the nexthop */
7457 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7458 || p
->family
== AF_EVPN
)
7459 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7460 || safi
== SAFI_EVPN
7461 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7462 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7463 || safi
== SAFI_EVPN
) {
7465 json_object_string_add(
7466 json_nexthop_global
, "ip",
7468 attr
->mp_nexthop_global_in
));
7472 attr
->mp_nexthop_global_in
));
7475 json_object_string_add(
7476 json_nexthop_global
, "ip",
7477 inet_ntoa(attr
->nexthop
));
7480 inet_ntoa(attr
->nexthop
));
7484 json_object_string_add(json_nexthop_global
,
7488 json_object_string_add(
7489 json_nexthop_global
, "ip",
7491 &attr
->mp_nexthop_global
, buf
,
7493 json_object_string_add(json_nexthop_global
,
7495 json_object_string_add(json_nexthop_global
,
7500 &attr
->mp_nexthop_global
, buf
,
7505 /* Display the IGP cost or 'inaccessible' */
7506 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7508 json_object_boolean_false_add(
7509 json_nexthop_global
, "accessible");
7511 vty_out(vty
, " (inaccessible)");
7513 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7515 json_object_int_add(
7516 json_nexthop_global
, "metric",
7517 binfo
->extra
->igpmetric
);
7519 vty_out(vty
, " (metric %u)",
7520 binfo
->extra
->igpmetric
);
7523 /* IGP cost is 0, display this only for json */
7526 json_object_int_add(json_nexthop_global
,
7531 json_object_boolean_true_add(
7532 json_nexthop_global
, "accessible");
7535 /* Display peer "from" output */
7536 /* This path was originated locally */
7537 if (binfo
->peer
== bgp
->peer_self
) {
7539 if (safi
== SAFI_EVPN
7540 || (p
->family
== AF_INET
7541 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7543 json_object_string_add(
7544 json_peer
, "peerId", "0.0.0.0");
7546 vty_out(vty
, " from 0.0.0.0 ");
7549 json_object_string_add(json_peer
,
7552 vty_out(vty
, " from :: ");
7556 json_object_string_add(
7557 json_peer
, "routerId",
7558 inet_ntoa(bgp
->router_id
));
7560 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7563 /* We RXed this path from one of our peers */
7567 json_object_string_add(
7568 json_peer
, "peerId",
7569 sockunion2str(&binfo
->peer
->su
, buf
,
7571 json_object_string_add(
7572 json_peer
, "routerId",
7574 &binfo
->peer
->remote_id
, buf1
,
7577 if (binfo
->peer
->hostname
)
7578 json_object_string_add(
7579 json_peer
, "hostname",
7580 binfo
->peer
->hostname
);
7582 if (binfo
->peer
->domainname
)
7583 json_object_string_add(
7584 json_peer
, "domainname",
7585 binfo
->peer
->domainname
);
7587 if (binfo
->peer
->conf_if
)
7588 json_object_string_add(
7589 json_peer
, "interface",
7590 binfo
->peer
->conf_if
);
7592 if (binfo
->peer
->conf_if
) {
7593 if (binfo
->peer
->hostname
7596 BGP_FLAG_SHOW_HOSTNAME
))
7597 vty_out(vty
, " from %s(%s)",
7598 binfo
->peer
->hostname
,
7599 binfo
->peer
->conf_if
);
7601 vty_out(vty
, " from %s",
7602 binfo
->peer
->conf_if
);
7604 if (binfo
->peer
->hostname
7607 BGP_FLAG_SHOW_HOSTNAME
))
7608 vty_out(vty
, " from %s(%s)",
7609 binfo
->peer
->hostname
,
7612 vty_out(vty
, " from %s",
7621 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7622 vty_out(vty
, " (%s)",
7623 inet_ntoa(attr
->originator_id
));
7625 vty_out(vty
, " (%s)",
7628 &binfo
->peer
->remote_id
,
7629 buf1
, sizeof(buf1
)));
7634 * Note when vrfid of nexthop is different from that of prefix
7636 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7637 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7642 if (binfo
->extra
->bgp_orig
->inst_type
==
7643 BGP_INSTANCE_TYPE_DEFAULT
)
7647 vn
= binfo
->extra
->bgp_orig
->name
;
7649 json_object_string_add(json_path
, "nhVrfName",
7652 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7653 json_object_int_add(json_path
,
7656 json_object_int_add(json_path
,
7657 "nhVrfId", (int)nexthop_vrfid
);
7660 if (nexthop_vrfid
== VRF_UNKNOWN
)
7661 vty_out(vty
, " vrf ?");
7663 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7669 json_object_boolean_true_add(json_path
,
7670 "announceNexthopSelf");
7672 vty_out(vty
, " announce-nh-self");
7679 /* display the link-local nexthop */
7680 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7682 json_nexthop_ll
= json_object_new_object();
7683 json_object_string_add(
7684 json_nexthop_ll
, "ip",
7686 &attr
->mp_nexthop_local
, buf
,
7688 json_object_string_add(json_nexthop_ll
, "afi",
7690 json_object_string_add(json_nexthop_ll
, "scope",
7693 json_object_boolean_true_add(json_nexthop_ll
,
7696 if (!attr
->mp_nexthop_prefer_global
)
7697 json_object_boolean_true_add(
7698 json_nexthop_ll
, "used");
7700 json_object_boolean_true_add(
7701 json_nexthop_global
, "used");
7703 vty_out(vty
, " (%s) %s\n",
7705 &attr
->mp_nexthop_local
, buf
,
7707 attr
->mp_nexthop_prefer_global
7712 /* If we do not have a link-local nexthop then we must flag the
7716 json_object_boolean_true_add(
7717 json_nexthop_global
, "used");
7720 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7721 * Int/Ext/Local, Atomic, best */
7723 json_object_string_add(
7724 json_path
, "origin",
7725 bgp_origin_long_str
[attr
->origin
]);
7727 vty_out(vty
, " Origin %s",
7728 bgp_origin_long_str
[attr
->origin
]);
7730 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7732 json_object_int_add(json_path
, "med",
7735 vty_out(vty
, ", metric %u", attr
->med
);
7738 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7740 json_object_int_add(json_path
, "localpref",
7743 vty_out(vty
, ", localpref %u",
7747 if (attr
->weight
!= 0) {
7749 json_object_int_add(json_path
, "weight",
7752 vty_out(vty
, ", weight %u", attr
->weight
);
7755 if (attr
->tag
!= 0) {
7757 json_object_int_add(json_path
, "tag",
7760 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7764 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7766 json_object_boolean_false_add(json_path
,
7769 vty_out(vty
, ", invalid");
7770 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7772 json_object_boolean_true_add(json_path
,
7775 vty_out(vty
, ", valid");
7778 if (binfo
->peer
!= bgp
->peer_self
) {
7779 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7780 if (CHECK_FLAG(bgp
->config
,
7781 BGP_CONFIG_CONFEDERATION
)) {
7783 json_object_string_add(
7788 ", confed-internal");
7791 json_object_string_add(
7795 vty_out(vty
, ", internal");
7798 if (bgp_confederation_peers_check(
7799 bgp
, binfo
->peer
->as
)) {
7801 json_object_string_add(
7806 ", confed-external");
7809 json_object_string_add(
7813 vty_out(vty
, ", external");
7816 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7818 json_object_boolean_true_add(json_path
,
7820 json_object_boolean_true_add(json_path
,
7823 vty_out(vty
, ", aggregated, local");
7825 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7827 json_object_boolean_true_add(json_path
,
7830 vty_out(vty
, ", sourced");
7833 json_object_boolean_true_add(json_path
,
7835 json_object_boolean_true_add(json_path
,
7838 vty_out(vty
, ", sourced, local");
7842 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7844 json_object_boolean_true_add(json_path
,
7847 vty_out(vty
, ", atomic-aggregate");
7850 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7851 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7852 && bgp_info_mpath_count(binfo
))) {
7854 json_object_boolean_true_add(json_path
,
7857 vty_out(vty
, ", multipath");
7860 // Mark the bestpath(s)
7861 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7862 first_as
= aspath_get_first_as(attr
->aspath
);
7867 json_object_new_object();
7868 json_object_int_add(json_bestpath
,
7869 "bestpathFromAs", first_as
);
7872 vty_out(vty
, ", bestpath-from-AS %u",
7876 ", bestpath-from-AS Local");
7880 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7884 json_object_new_object();
7885 json_object_boolean_true_add(json_bestpath
,
7888 vty_out(vty
, ", best");
7892 json_object_object_add(json_path
, "bestpath",
7898 /* Line 4 display Community */
7899 if (attr
->community
) {
7901 if (!attr
->community
->json
)
7902 community_str(attr
->community
, true);
7903 json_object_lock(attr
->community
->json
);
7904 json_object_object_add(json_path
, "community",
7905 attr
->community
->json
);
7907 vty_out(vty
, " Community: %s\n",
7908 attr
->community
->str
);
7912 /* Line 5 display Extended-community */
7913 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7915 json_ext_community
= json_object_new_object();
7916 json_object_string_add(json_ext_community
,
7918 attr
->ecommunity
->str
);
7919 json_object_object_add(json_path
,
7920 "extendedCommunity",
7921 json_ext_community
);
7923 vty_out(vty
, " Extended Community: %s\n",
7924 attr
->ecommunity
->str
);
7928 /* Line 6 display Large community */
7929 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7931 if (!attr
->lcommunity
->json
)
7932 lcommunity_str(attr
->lcommunity
, true);
7933 json_object_lock(attr
->lcommunity
->json
);
7934 json_object_object_add(json_path
,
7936 attr
->lcommunity
->json
);
7938 vty_out(vty
, " Large Community: %s\n",
7939 attr
->lcommunity
->str
);
7943 /* Line 7 display Originator, Cluster-id */
7944 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7945 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7947 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7949 json_object_string_add(
7950 json_path
, "originatorId",
7951 inet_ntoa(attr
->originator_id
));
7953 vty_out(vty
, " Originator: %s",
7954 inet_ntoa(attr
->originator_id
));
7957 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7962 json_object_new_object();
7963 json_cluster_list_list
=
7964 json_object_new_array();
7967 i
< attr
->cluster
->length
/ 4;
7969 json_string
= json_object_new_string(
7973 json_object_array_add(
7974 json_cluster_list_list
,
7978 /* struct cluster_list does not have
7980 * aspath and community do. Add this
7983 json_object_string_add(json_cluster_list,
7984 "string", attr->cluster->str);
7986 json_object_object_add(
7987 json_cluster_list
, "list",
7988 json_cluster_list_list
);
7989 json_object_object_add(
7990 json_path
, "clusterList",
7993 vty_out(vty
, ", Cluster list: ");
7996 i
< attr
->cluster
->length
/ 4;
8010 if (binfo
->extra
&& binfo
->extra
->damp_info
)
8011 bgp_damp_info_vty(vty
, binfo
, json_path
);
8014 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8015 && safi
!= SAFI_EVPN
) {
8016 mpls_label_t label
=
8017 label_pton(&binfo
->extra
->label
[0]);
8019 json_object_int_add(json_path
, "remoteLabel",
8022 vty_out(vty
, " Remote label: %d\n", label
);
8026 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8028 json_object_int_add(json_path
, "labelIndex",
8031 vty_out(vty
, " Label Index: %d\n",
8035 /* Line 8 display Addpath IDs */
8036 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8038 json_object_int_add(json_path
, "addpathRxId",
8039 binfo
->addpath_rx_id
);
8040 json_object_int_add(json_path
, "addpathTxId",
8041 binfo
->addpath_tx_id
);
8043 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8044 binfo
->addpath_rx_id
,
8045 binfo
->addpath_tx_id
);
8049 /* If we used addpath to TX a non-bestpath we need to display
8050 * "Advertised to" on a path-by-path basis */
8051 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8054 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8056 bgp_addpath_encode_tx(peer
, afi
, safi
);
8057 has_adj
= bgp_adj_out_lookup(
8058 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8060 if ((addpath_capable
&& has_adj
)
8061 || (!addpath_capable
&& has_adj
8062 && CHECK_FLAG(binfo
->flags
,
8063 BGP_INFO_SELECTED
))) {
8064 if (json_path
&& !json_adv_to
)
8066 json_object_new_object();
8068 route_vty_out_advertised_to(
8077 json_object_object_add(json_path
,
8088 /* Line 9 display Uptime */
8089 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8091 json_last_update
= json_object_new_object();
8092 json_object_int_add(json_last_update
, "epoch", tbuf
);
8093 json_object_string_add(json_last_update
, "string",
8095 json_object_object_add(json_path
, "lastUpdate",
8098 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8100 /* Line 10 display PMSI tunnel attribute, if present */
8101 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8102 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8103 attr
->pmsi_tnl_type
,
8104 PMSI_TNLTYPE_STR_DEFAULT
);
8107 json_pmsi
= json_object_new_object();
8108 json_object_string_add(json_pmsi
,
8110 json_object_object_add(json_path
, "pmsi",
8113 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8119 /* We've constructed the json object for this path, add it to the json
8123 if (json_nexthop_global
|| json_nexthop_ll
) {
8124 json_nexthops
= json_object_new_array();
8126 if (json_nexthop_global
)
8127 json_object_array_add(json_nexthops
,
8128 json_nexthop_global
);
8130 if (json_nexthop_ll
)
8131 json_object_array_add(json_nexthops
,
8134 json_object_object_add(json_path
, "nexthops",
8138 json_object_object_add(json_path
, "peer", json_peer
);
8139 json_object_array_add(json_paths
, json_path
);
8144 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8145 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8146 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8148 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8149 const char *prefix_list_str
, afi_t afi
,
8150 safi_t safi
, enum bgp_show_type type
);
8151 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8152 const char *filter
, afi_t afi
, safi_t safi
,
8153 enum bgp_show_type type
);
8154 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8155 const char *rmap_str
, afi_t afi
, safi_t safi
,
8156 enum bgp_show_type type
);
8157 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8158 const char *com
, int exact
, afi_t afi
,
8160 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8161 const char *prefix
, afi_t afi
, safi_t safi
,
8162 enum bgp_show_type type
);
8163 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8164 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8165 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8166 const char *comstr
, int exact
, afi_t afi
,
8167 safi_t safi
, uint8_t use_json
);
8170 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8171 struct bgp_table
*table
, enum bgp_show_type type
,
8172 void *output_arg
, uint8_t use_json
, char *rd
,
8173 int is_last
, unsigned long *output_cum
,
8174 unsigned long *total_cum
,
8175 unsigned long *json_header_depth
)
8177 struct bgp_info
*ri
;
8178 struct bgp_node
*rn
;
8181 unsigned long output_count
= 0;
8182 unsigned long total_count
= 0;
8186 json_object
*json_paths
= NULL
;
8189 if (output_cum
&& *output_cum
!= 0)
8192 if (use_json
&& !*json_header_depth
) {
8194 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8195 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8196 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8197 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8199 table
->version
, inet_ntoa(bgp
->router_id
));
8200 *json_header_depth
= 2;
8202 vty_out(vty
, " \"routeDistinguishers\" : {");
8203 ++*json_header_depth
;
8207 if (use_json
&& rd
) {
8208 vty_out(vty
, " \"%s\" : { ", rd
);
8211 /* Start processing of routes. */
8212 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8213 if (rn
->info
== NULL
)
8218 json_paths
= json_object_new_array();
8222 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8224 if (type
== bgp_show_type_flap_statistics
8225 || type
== bgp_show_type_flap_neighbor
8226 || type
== bgp_show_type_dampend_paths
8227 || type
== bgp_show_type_damp_neighbor
) {
8228 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8231 if (type
== bgp_show_type_regexp
) {
8232 regex_t
*regex
= output_arg
;
8234 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8238 if (type
== bgp_show_type_prefix_list
) {
8239 struct prefix_list
*plist
= output_arg
;
8241 if (prefix_list_apply(plist
, &rn
->p
)
8245 if (type
== bgp_show_type_filter_list
) {
8246 struct as_list
*as_list
= output_arg
;
8248 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8249 != AS_FILTER_PERMIT
)
8252 if (type
== bgp_show_type_route_map
) {
8253 struct route_map
*rmap
= output_arg
;
8254 struct bgp_info binfo
;
8255 struct attr dummy_attr
;
8258 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8260 binfo
.peer
= ri
->peer
;
8261 binfo
.attr
= &dummy_attr
;
8263 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8265 if (ret
== RMAP_DENYMATCH
)
8268 if (type
== bgp_show_type_neighbor
8269 || type
== bgp_show_type_flap_neighbor
8270 || type
== bgp_show_type_damp_neighbor
) {
8271 union sockunion
*su
= output_arg
;
8273 if (ri
->peer
== NULL
8274 || ri
->peer
->su_remote
== NULL
8275 || !sockunion_same(ri
->peer
->su_remote
, su
))
8278 if (type
== bgp_show_type_cidr_only
) {
8279 uint32_t destination
;
8281 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8282 if (IN_CLASSC(destination
)
8283 && rn
->p
.prefixlen
== 24)
8285 if (IN_CLASSB(destination
)
8286 && rn
->p
.prefixlen
== 16)
8288 if (IN_CLASSA(destination
)
8289 && rn
->p
.prefixlen
== 8)
8292 if (type
== bgp_show_type_prefix_longer
) {
8293 struct prefix
*p
= output_arg
;
8295 if (!prefix_match(p
, &rn
->p
))
8298 if (type
== bgp_show_type_community_all
) {
8299 if (!ri
->attr
->community
)
8302 if (type
== bgp_show_type_community
) {
8303 struct community
*com
= output_arg
;
8305 if (!ri
->attr
->community
8306 || !community_match(ri
->attr
->community
,
8310 if (type
== bgp_show_type_community_exact
) {
8311 struct community
*com
= output_arg
;
8313 if (!ri
->attr
->community
8314 || !community_cmp(ri
->attr
->community
, com
))
8317 if (type
== bgp_show_type_community_list
) {
8318 struct community_list
*list
= output_arg
;
8320 if (!community_list_match(ri
->attr
->community
,
8324 if (type
== bgp_show_type_community_list_exact
) {
8325 struct community_list
*list
= output_arg
;
8327 if (!community_list_exact_match(
8328 ri
->attr
->community
, list
))
8331 if (type
== bgp_show_type_lcommunity
) {
8332 struct lcommunity
*lcom
= output_arg
;
8334 if (!ri
->attr
->lcommunity
8335 || !lcommunity_match(ri
->attr
->lcommunity
,
8339 if (type
== bgp_show_type_lcommunity_list
) {
8340 struct community_list
*list
= output_arg
;
8342 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8346 if (type
== bgp_show_type_lcommunity_all
) {
8347 if (!ri
->attr
->lcommunity
)
8350 if (type
== bgp_show_type_dampend_paths
8351 || type
== bgp_show_type_damp_neighbor
) {
8352 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8353 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8357 if (!use_json
&& header
) {
8358 vty_out(vty
, "BGP table version is %" PRIu64
8359 ", local router ID is %s, vrf id ",
8361 inet_ntoa(bgp
->router_id
));
8362 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8363 vty_out(vty
, "%s", VRFID_NONE_STR
);
8365 vty_out(vty
, "%u", bgp
->vrf_id
);
8367 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8368 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8369 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8370 if (type
== bgp_show_type_dampend_paths
8371 || type
== bgp_show_type_damp_neighbor
)
8372 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8373 else if (type
== bgp_show_type_flap_statistics
8374 || type
== bgp_show_type_flap_neighbor
)
8375 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8377 vty_out(vty
, BGP_SHOW_HEADER
);
8380 if (rd
!= NULL
&& !display
&& !output_count
) {
8383 "Route Distinguisher: %s\n",
8386 if (type
== bgp_show_type_dampend_paths
8387 || type
== bgp_show_type_damp_neighbor
)
8388 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8389 safi
, use_json
, json_paths
);
8390 else if (type
== bgp_show_type_flap_statistics
8391 || type
== bgp_show_type_flap_neighbor
)
8392 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8393 safi
, use_json
, json_paths
);
8395 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8406 sprintf(buf2
, "%s/%d",
8407 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8410 vty_out(vty
, "\"%s\": ", buf2
);
8412 vty_out(vty
, ",\"%s\": ", buf2
);
8415 json_object_to_json_string(json_paths
));
8416 json_object_free(json_paths
);
8423 output_count
+= *output_cum
;
8424 *output_cum
= output_count
;
8427 total_count
+= *total_cum
;
8428 *total_cum
= total_count
;
8432 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8436 for (i
= 0; i
< *json_header_depth
; ++i
)
8437 vty_out(vty
, " } ");
8441 /* No route is displayed */
8442 if (output_count
== 0) {
8443 if (type
== bgp_show_type_normal
)
8445 "No BGP prefixes displayed, %ld exist\n",
8449 "\nDisplayed %ld routes and %ld total paths\n",
8450 output_count
, total_count
);
8457 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8458 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8459 enum bgp_show_type type
, void *output_arg
,
8462 struct bgp_node
*rn
, *next
;
8463 unsigned long output_cum
= 0;
8464 unsigned long total_cum
= 0;
8465 unsigned long json_header_depth
= 0;
8468 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8470 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8471 next
= bgp_route_next(rn
);
8472 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8474 if (rn
->info
!= NULL
) {
8475 struct prefix_rd prd
;
8476 char rd
[RD_ADDRSTRLEN
];
8478 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8479 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8480 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8481 output_arg
, use_json
, rd
, next
== NULL
,
8482 &output_cum
, &total_cum
,
8483 &json_header_depth
);
8489 if (output_cum
== 0)
8490 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8494 "\nDisplayed %ld routes and %ld total paths\n",
8495 output_cum
, total_cum
);
8499 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8500 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8502 struct bgp_table
*table
;
8503 unsigned long json_header_depth
= 0;
8506 bgp
= bgp_get_default();
8511 vty_out(vty
, "No BGP process is configured\n");
8513 vty_out(vty
, "{}\n");
8517 table
= bgp
->rib
[afi
][safi
];
8518 /* use MPLS and ENCAP specific shows until they are merged */
8519 if (safi
== SAFI_MPLS_VPN
) {
8520 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8521 output_arg
, use_json
);
8524 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8525 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8526 output_arg
, use_json
,
8529 /* labeled-unicast routes live in the unicast table */
8530 else if (safi
== SAFI_LABELED_UNICAST
)
8531 safi
= SAFI_UNICAST
;
8533 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8534 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8537 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8538 safi_t safi
, uint8_t use_json
)
8540 struct listnode
*node
, *nnode
;
8545 vty_out(vty
, "{\n");
8547 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8550 vty_out(vty
, ",\n");
8554 vty_out(vty
, "\"%s\":",
8555 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8559 vty_out(vty
, "\nInstance %s:\n",
8560 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8564 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8569 vty_out(vty
, "}\n");
8572 /* Header of detailed BGP route information */
8573 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8574 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8575 afi_t afi
, safi_t safi
, json_object
*json
)
8577 struct bgp_info
*ri
;
8580 struct listnode
*node
, *nnode
;
8581 char buf1
[RD_ADDRSTRLEN
];
8582 char buf2
[INET6_ADDRSTRLEN
];
8583 char buf3
[EVPN_ROUTE_STRLEN
];
8584 char prefix_str
[BUFSIZ
];
8589 int no_advertise
= 0;
8592 int has_valid_label
= 0;
8593 mpls_label_t label
= 0;
8594 json_object
*json_adv_to
= NULL
;
8597 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8599 if (has_valid_label
)
8600 label
= label_pton(&rn
->local_label
);
8603 if (has_valid_label
)
8604 json_object_int_add(json
, "localLabel", label
);
8606 json_object_string_add(
8608 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8610 if (safi
== SAFI_EVPN
)
8611 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8612 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8615 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8616 buf3
, sizeof(buf3
)));
8618 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8619 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8620 ? prefix_rd2str(prd
, buf1
,
8623 safi
== SAFI_MPLS_VPN
? ":" : "",
8624 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8628 if (has_valid_label
)
8629 vty_out(vty
, "Local label: %d\n", label
);
8630 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8631 vty_out(vty
, "not allocated\n");
8634 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8636 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8638 if (ri
->extra
&& ri
->extra
->suppress
)
8640 if (ri
->attr
->community
!= NULL
) {
8641 if (community_include(ri
->attr
->community
,
8642 COMMUNITY_NO_ADVERTISE
))
8644 if (community_include(ri
->attr
->community
,
8645 COMMUNITY_NO_EXPORT
))
8647 if (community_include(ri
->attr
->community
,
8648 COMMUNITY_LOCAL_AS
))
8655 vty_out(vty
, "Paths: (%d available", count
);
8657 vty_out(vty
, ", best #%d", best
);
8658 if (safi
== SAFI_UNICAST
)
8659 vty_out(vty
, ", table %s",
8661 == BGP_INSTANCE_TYPE_DEFAULT
)
8662 ? "Default-IP-Routing-Table"
8665 vty_out(vty
, ", no best path");
8668 vty_out(vty
, ", not advertised to any peer");
8670 vty_out(vty
, ", not advertised to EBGP peer");
8672 vty_out(vty
, ", not advertised outside local AS");
8676 ", Advertisements suppressed by an aggregate.");
8677 vty_out(vty
, ")\n");
8680 /* If we are not using addpath then we can display Advertised to and
8682 * show what peers we advertised the bestpath to. If we are using
8684 * though then we must display Advertised to on a path-by-path basis. */
8685 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8686 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8687 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8688 if (json
&& !json_adv_to
)
8689 json_adv_to
= json_object_new_object();
8691 route_vty_out_advertised_to(
8693 " Advertised to non peer-group peers:\n ",
8700 json_object_object_add(json
, "advertisedTo",
8705 vty_out(vty
, " Not advertised to any peer");
8711 /* Display specified route of BGP table. */
8712 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8713 struct bgp_table
*rib
, const char *ip_str
,
8714 afi_t afi
, safi_t safi
,
8715 struct prefix_rd
*prd
, int prefix_check
,
8716 enum bgp_path_type pathtype
,
8722 struct prefix match
;
8723 struct bgp_node
*rn
;
8724 struct bgp_node
*rm
;
8725 struct bgp_info
*ri
;
8726 struct bgp_table
*table
;
8727 json_object
*json
= NULL
;
8728 json_object
*json_paths
= NULL
;
8730 /* Check IP address argument. */
8731 ret
= str2prefix(ip_str
, &match
);
8733 vty_out(vty
, "address is malformed\n");
8737 match
.family
= afi2family(afi
);
8740 json
= json_object_new_object();
8741 json_paths
= json_object_new_array();
8744 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8745 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8746 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8749 if ((table
= rn
->info
) == NULL
)
8754 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8758 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8759 bgp_unlock_node(rm
);
8763 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8765 route_vty_out_detail_header(
8767 (struct prefix_rd
*)&rn
->p
,
8768 AFI_IP
, safi
, json
);
8773 if (pathtype
== BGP_PATH_ALL
8774 || (pathtype
== BGP_PATH_BESTPATH
8775 && CHECK_FLAG(ri
->flags
,
8777 || (pathtype
== BGP_PATH_MULTIPATH
8778 && (CHECK_FLAG(ri
->flags
,
8780 || CHECK_FLAG(ri
->flags
,
8781 BGP_INFO_SELECTED
))))
8782 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8787 bgp_unlock_node(rm
);
8789 } else if (safi
== SAFI_FLOWSPEC
) {
8790 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
8791 &match
, prefix_check
,
8798 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8800 || rn
->p
.prefixlen
== match
.prefixlen
) {
8801 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8803 route_vty_out_detail_header(
8804 vty
, bgp
, rn
, NULL
, afi
,
8810 if (pathtype
== BGP_PATH_ALL
8811 || (pathtype
== BGP_PATH_BESTPATH
8815 || (pathtype
== BGP_PATH_MULTIPATH
8821 BGP_INFO_SELECTED
))))
8822 route_vty_out_detail(
8823 vty
, bgp
, &rn
->p
, ri
,
8824 afi
, safi
, json_paths
);
8828 bgp_unlock_node(rn
);
8834 json_object_object_add(json
, "paths", json_paths
);
8836 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8837 json
, JSON_C_TO_STRING_PRETTY
));
8838 json_object_free(json
);
8841 vty_out(vty
, "%% Network not in table\n");
8849 /* Display specified route of Main RIB */
8850 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8851 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8852 int prefix_check
, enum bgp_path_type pathtype
,
8856 bgp
= bgp_get_default();
8859 vty_out(vty
, "No BGP process is configured\n");
8861 vty_out(vty
, "{}\n");
8866 /* labeled-unicast routes live in the unicast table */
8867 if (safi
== SAFI_LABELED_UNICAST
)
8868 safi
= SAFI_UNICAST
;
8870 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8871 afi
, safi
, prd
, prefix_check
, pathtype
,
8875 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8876 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8879 struct lcommunity
*lcom
;
8885 b
= buffer_new(1024);
8886 for (i
= 0; i
< argc
; i
++) {
8888 buffer_putc(b
, ' ');
8890 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8892 buffer_putstr(b
, argv
[i
]->arg
);
8896 buffer_putc(b
, '\0');
8898 str
= buffer_getstr(b
);
8901 lcom
= lcommunity_str2com(str
);
8902 XFREE(MTYPE_TMP
, str
);
8904 vty_out(vty
, "%% Large-community malformed\n");
8908 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8912 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8913 const char *lcom
, afi_t afi
, safi_t safi
,
8916 struct community_list
*list
;
8918 list
= community_list_lookup(bgp_clist
, lcom
,
8919 LARGE_COMMUNITY_LIST_MASTER
);
8921 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8926 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8930 DEFUN (show_ip_bgp_large_community_list
,
8931 show_ip_bgp_large_community_list_cmd
,
8932 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8936 BGP_INSTANCE_HELP_STR
8938 BGP_SAFI_WITH_LABEL_HELP_STR
8939 "Display routes matching the large-community-list\n"
8940 "large-community-list number\n"
8941 "large-community-list name\n"
8945 afi_t afi
= AFI_IP6
;
8946 safi_t safi
= SAFI_UNICAST
;
8949 if (argv_find(argv
, argc
, "ip", &idx
))
8951 if (argv_find(argv
, argc
, "view", &idx
)
8952 || argv_find(argv
, argc
, "vrf", &idx
))
8953 vrf
= argv
[++idx
]->arg
;
8954 if (argv_find(argv
, argc
, "ipv4", &idx
)
8955 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8956 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8957 if (argv_find(argv
, argc
, "unicast", &idx
)
8958 || argv_find(argv
, argc
, "multicast", &idx
))
8959 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8962 int uj
= use_json(argc
, argv
);
8964 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8966 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8970 argv_find(argv
, argc
, "large-community-list", &idx
);
8971 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8974 DEFUN (show_ip_bgp_large_community
,
8975 show_ip_bgp_large_community_cmd
,
8976 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8980 BGP_INSTANCE_HELP_STR
8982 BGP_SAFI_WITH_LABEL_HELP_STR
8983 "Display routes matching the large-communities\n"
8984 "List of large-community numbers\n"
8988 afi_t afi
= AFI_IP6
;
8989 safi_t safi
= SAFI_UNICAST
;
8992 if (argv_find(argv
, argc
, "ip", &idx
))
8994 if (argv_find(argv
, argc
, "view", &idx
)
8995 || argv_find(argv
, argc
, "vrf", &idx
))
8996 vrf
= argv
[++idx
]->arg
;
8997 if (argv_find(argv
, argc
, "ipv4", &idx
)
8998 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8999 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9000 if (argv_find(argv
, argc
, "unicast", &idx
)
9001 || argv_find(argv
, argc
, "multicast", &idx
))
9002 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9005 int uj
= use_json(argc
, argv
);
9007 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9009 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9013 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9014 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9016 return bgp_show(vty
, bgp
, afi
, safi
,
9017 bgp_show_type_lcommunity_all
, NULL
, uj
);
9020 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9024 /* BGP route print out function without JSON */
9027 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9028 <dampening <parameters>\
9033 |community-list <(1-500)|WORD> [exact-match]\
9034 |A.B.C.D/M longer-prefixes\
9035 |X:X::X:X/M longer-prefixes\
9040 BGP_INSTANCE_HELP_STR
9042 BGP_SAFI_WITH_LABEL_HELP_STR
9043 "Display detailed information about dampening\n"
9044 "Display detail of configured dampening parameters\n"
9045 "Display routes matching the route-map\n"
9046 "A route-map to match on\n"
9047 "Display routes conforming to the prefix-list\n"
9048 "Prefix-list name\n"
9049 "Display routes conforming to the filter-list\n"
9050 "Regular expression access list name\n"
9051 "BGP RIB advertisement statistics\n"
9052 "Display routes matching the community-list\n"
9053 "community-list number\n"
9054 "community-list name\n"
9055 "Exact match of the communities\n"
9057 "Display route and more specific routes\n"
9059 "Display route and more specific routes\n")
9061 afi_t afi
= AFI_IP6
;
9062 safi_t safi
= SAFI_UNICAST
;
9063 int exact_match
= 0;
9064 struct bgp
*bgp
= NULL
;
9067 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9072 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9073 if (argv_find(argv
, argc
, "parameters", &idx
))
9074 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9077 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9078 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9079 safi
, bgp_show_type_prefix_list
);
9081 if (argv_find(argv
, argc
, "filter-list", &idx
))
9082 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9083 safi
, bgp_show_type_filter_list
);
9085 if (argv_find(argv
, argc
, "statistics", &idx
))
9086 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9088 if (argv_find(argv
, argc
, "route-map", &idx
))
9089 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9090 safi
, bgp_show_type_route_map
);
9092 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9093 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9094 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9096 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9097 exact_match
, afi
, safi
);
9100 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9101 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9102 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9104 bgp_show_type_prefix_longer
);
9109 /* BGP route print out function with JSON */
9110 DEFUN (show_ip_bgp_json
,
9111 show_ip_bgp_json_cmd
,
9112 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9115 |dampening <flap-statistics|dampened-paths>\
9116 |community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown>] [exact-match]\
9121 BGP_INSTANCE_HELP_STR
9123 BGP_SAFI_WITH_LABEL_HELP_STR
9124 "Display only routes with non-natural netmasks\n"
9125 "Display detailed information about dampening\n"
9126 "Display flap statistics of routes\n"
9127 "Display paths suppressed due to dampening\n"
9128 "Display routes matching the communities\n"
9130 "Do not send outside local AS (well-known community)\n"
9131 "Do not advertise to any peer (well-known community)\n"
9132 "Do not export to next AS (well-known community)\n"
9133 "Graceful shutdown (well-known community)\n"
9134 "Exact match of the communities\n"
9137 afi_t afi
= AFI_IP6
;
9138 safi_t safi
= SAFI_UNICAST
;
9139 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9140 struct bgp
*bgp
= NULL
;
9142 int idx_community_type
= 0;
9143 int exact_match
= 0;
9145 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9150 int uj
= use_json(argc
, argv
);
9154 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9155 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9158 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9159 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9160 return bgp_show(vty
, bgp
, afi
, safi
,
9161 bgp_show_type_dampend_paths
, NULL
, uj
);
9162 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9163 return bgp_show(vty
, bgp
, afi
, safi
,
9164 bgp_show_type_flap_statistics
, NULL
,
9168 if (argv_find(argv
, argc
, "community", &idx
)) {
9170 /* show a specific community */
9171 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
) ||
9172 argv_find(argv
, argc
, "no-advertise",
9173 &idx_community_type
) ||
9174 argv_find(argv
, argc
, "no-export",
9175 &idx_community_type
) ||
9176 argv_find(argv
, argc
, "graceful-shutdown",
9177 &idx_community_type
) ||
9178 argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9179 if (argv_find(argv
, argc
, "exact-match", &idx
))
9182 return (bgp_show_community(vty
, bgp
,
9183 argv
[idx_community_type
]->arg
,
9184 exact_match
, afi
, safi
, uj
));
9187 /* show all communities */
9188 return (bgp_show(vty
, bgp
, afi
, safi
,
9189 bgp_show_type_community_all
, NULL
,
9194 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9197 DEFUN (show_ip_bgp_route
,
9198 show_ip_bgp_route_cmd
,
9199 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9200 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9204 BGP_INSTANCE_HELP_STR
9206 BGP_SAFI_WITH_LABEL_HELP_STR
9207 "Network in the BGP routing table to display\n"
9209 "Network in the BGP routing table to display\n"
9211 "Display only the bestpath\n"
9212 "Display only multipaths\n"
9215 int prefix_check
= 0;
9217 afi_t afi
= AFI_IP6
;
9218 safi_t safi
= SAFI_UNICAST
;
9219 char *prefix
= NULL
;
9220 struct bgp
*bgp
= NULL
;
9221 enum bgp_path_type path_type
;
9222 uint8_t uj
= use_json(argc
, argv
);
9226 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9233 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9237 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9238 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9239 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9241 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9242 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9245 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9246 && afi
!= AFI_IP6
) {
9248 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9251 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9254 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9258 prefix
= argv
[idx
]->arg
;
9260 /* [<bestpath|multipath>] */
9261 if (argv_find(argv
, argc
, "bestpath", &idx
))
9262 path_type
= BGP_PATH_BESTPATH
;
9263 else if (argv_find(argv
, argc
, "multipath", &idx
))
9264 path_type
= BGP_PATH_MULTIPATH
;
9266 path_type
= BGP_PATH_ALL
;
9268 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9272 DEFUN (show_ip_bgp_regexp
,
9273 show_ip_bgp_regexp_cmd
,
9274 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9278 BGP_INSTANCE_HELP_STR
9280 BGP_SAFI_WITH_LABEL_HELP_STR
9281 "Display routes matching the AS path regular expression\n"
9282 "A regular-expression to match the BGP AS paths\n")
9284 afi_t afi
= AFI_IP6
;
9285 safi_t safi
= SAFI_UNICAST
;
9286 struct bgp
*bgp
= NULL
;
9289 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9294 // get index of regex
9295 argv_find(argv
, argc
, "regexp", &idx
);
9298 char *regstr
= argv_concat(argv
, argc
, idx
);
9299 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9300 bgp_show_type_regexp
);
9301 XFREE(MTYPE_TMP
, regstr
);
9305 DEFUN (show_ip_bgp_instance_all
,
9306 show_ip_bgp_instance_all_cmd
,
9307 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9311 BGP_INSTANCE_ALL_HELP_STR
9313 BGP_SAFI_WITH_LABEL_HELP_STR
9317 safi_t safi
= SAFI_UNICAST
;
9318 struct bgp
*bgp
= NULL
;
9321 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9326 int uj
= use_json(argc
, argv
);
9330 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9334 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9335 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9340 regex
= bgp_regcomp(regstr
);
9342 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9346 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9347 bgp_regex_free(regex
);
9351 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9352 const char *prefix_list_str
, afi_t afi
,
9353 safi_t safi
, enum bgp_show_type type
)
9355 struct prefix_list
*plist
;
9357 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9358 if (plist
== NULL
) {
9359 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9364 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9367 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9368 const char *filter
, afi_t afi
, safi_t safi
,
9369 enum bgp_show_type type
)
9371 struct as_list
*as_list
;
9373 as_list
= as_list_lookup(filter
);
9374 if (as_list
== NULL
) {
9375 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9380 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9383 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9384 const char *rmap_str
, afi_t afi
, safi_t safi
,
9385 enum bgp_show_type type
)
9387 struct route_map
*rmap
;
9389 rmap
= route_map_lookup_by_name(rmap_str
);
9391 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9395 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9398 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9399 const char *comstr
, int exact
, afi_t afi
,
9400 safi_t safi
, uint8_t use_json
)
9402 struct community
*com
;
9405 com
= community_str2com(comstr
);
9407 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9411 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9412 (exact
? bgp_show_type_community_exact
9413 : bgp_show_type_community
),
9415 community_free(com
);
9420 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9421 const char *com
, int exact
, afi_t afi
,
9424 struct community_list
*list
;
9426 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9428 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9432 return bgp_show(vty
, bgp
, afi
, safi
,
9433 (exact
? bgp_show_type_community_list_exact
9434 : bgp_show_type_community_list
),
9438 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9439 const char *prefix
, afi_t afi
, safi_t safi
,
9440 enum bgp_show_type type
)
9447 ret
= str2prefix(prefix
, p
);
9449 vty_out(vty
, "%% Malformed Prefix\n");
9453 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9458 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9459 const char *ip_str
, uint8_t use_json
)
9465 /* Get peer sockunion. */
9466 ret
= str2sockunion(ip_str
, &su
);
9468 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9470 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9474 json_object
*json_no
= NULL
;
9475 json_no
= json_object_new_object();
9476 json_object_string_add(
9478 "malformedAddressOrName",
9480 vty_out(vty
, "%s\n",
9481 json_object_to_json_string_ext(
9483 JSON_C_TO_STRING_PRETTY
));
9484 json_object_free(json_no
);
9487 "%% Malformed address or name: %s\n",
9495 /* Peer structure lookup. */
9496 peer
= peer_lookup(bgp
, &su
);
9499 json_object
*json_no
= NULL
;
9500 json_no
= json_object_new_object();
9501 json_object_string_add(json_no
, "warning",
9502 "No such neighbor in this view/vrf");
9503 vty_out(vty
, "%s\n",
9504 json_object_to_json_string_ext(
9505 json_no
, JSON_C_TO_STRING_PRETTY
));
9506 json_object_free(json_no
);
9508 vty_out(vty
, "No such neighbor in this view/vrf\n");
9516 BGP_STATS_MAXBITLEN
= 0,
9520 BGP_STATS_UNAGGREGATEABLE
,
9521 BGP_STATS_MAX_AGGREGATEABLE
,
9522 BGP_STATS_AGGREGATES
,
9524 BGP_STATS_ASPATH_COUNT
,
9525 BGP_STATS_ASPATH_MAXHOPS
,
9526 BGP_STATS_ASPATH_TOTHOPS
,
9527 BGP_STATS_ASPATH_MAXSIZE
,
9528 BGP_STATS_ASPATH_TOTSIZE
,
9529 BGP_STATS_ASN_HIGHEST
,
9533 static const char *table_stats_strs
[] = {
9534 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9535 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9536 [BGP_STATS_RIB
] = "Total Advertisements",
9537 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9538 [BGP_STATS_MAX_AGGREGATEABLE
] =
9539 "Maximum aggregateable prefixes",
9540 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9541 [BGP_STATS_SPACE
] = "Address space advertised",
9542 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9543 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9544 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9545 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9546 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9547 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9548 [BGP_STATS_MAX
] = NULL
,
9551 struct bgp_table_stats
{
9552 struct bgp_table
*table
;
9553 unsigned long long counts
[BGP_STATS_MAX
];
9558 #define TALLY_SIGFIG 100000
9559 static unsigned long
9560 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9562 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9563 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9564 unsigned long ret
= newtot
/ count
;
9566 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9573 static int bgp_table_stats_walker(struct thread
*t
)
9575 struct bgp_node
*rn
;
9576 struct bgp_node
*top
;
9577 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9578 unsigned int space
= 0;
9580 if (!(top
= bgp_table_top(ts
->table
)))
9583 switch (top
->p
.family
) {
9585 space
= IPV4_MAX_BITLEN
;
9588 space
= IPV6_MAX_BITLEN
;
9592 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9594 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9595 struct bgp_info
*ri
;
9596 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9597 unsigned int rinum
= 0;
9605 ts
->counts
[BGP_STATS_PREFIXES
]++;
9606 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9609 ts
->counts
[BGP_STATS_AVGPLEN
]
9610 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9611 ts
->counts
[BGP_STATS_AVGPLEN
],
9615 /* check if the prefix is included by any other announcements */
9616 while (prn
&& !prn
->info
)
9617 prn
= bgp_node_parent_nolock(prn
);
9619 if (prn
== NULL
|| prn
== top
) {
9620 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9621 /* announced address space */
9624 pow(2.0, space
- rn
->p
.prefixlen
);
9625 } else if (prn
->info
)
9626 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9628 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9630 ts
->counts
[BGP_STATS_RIB
]++;
9633 && (CHECK_FLAG(ri
->attr
->flag
,
9635 BGP_ATTR_ATOMIC_AGGREGATE
))))
9636 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9639 if (ri
->attr
&& ri
->attr
->aspath
) {
9641 aspath_count_hops(ri
->attr
->aspath
);
9643 aspath_size(ri
->attr
->aspath
);
9644 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9646 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9648 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9649 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9652 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9653 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9656 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9657 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9659 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9660 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9661 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9663 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9664 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9665 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9668 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9669 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9677 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9680 struct bgp_table_stats ts
;
9683 if (!bgp
->rib
[afi
][safi
]) {
9684 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9689 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9691 /* labeled-unicast routes live in the unicast table */
9692 if (safi
== SAFI_LABELED_UNICAST
)
9693 safi
= SAFI_UNICAST
;
9695 memset(&ts
, 0, sizeof(ts
));
9696 ts
.table
= bgp
->rib
[afi
][safi
];
9697 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9699 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9700 if (!table_stats_strs
[i
])
9705 case BGP_STATS_ASPATH_AVGHOPS
:
9706 case BGP_STATS_ASPATH_AVGSIZE
:
9707 case BGP_STATS_AVGPLEN
:
9708 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9709 vty_out (vty
, "%12.2f",
9710 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9713 case BGP_STATS_ASPATH_TOTHOPS
:
9714 case BGP_STATS_ASPATH_TOTSIZE
:
9715 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9716 vty_out(vty
, "%12.2f",
9718 ? (float)ts
.counts
[i
]
9720 [BGP_STATS_ASPATH_COUNT
]
9723 case BGP_STATS_TOTPLEN
:
9724 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9725 vty_out(vty
, "%12.2f",
9727 ? (float)ts
.counts
[i
]
9729 [BGP_STATS_PREFIXES
]
9732 case BGP_STATS_SPACE
:
9733 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9734 vty_out(vty
, "%12g\n", ts
.total_space
);
9736 if (afi
== AFI_IP6
) {
9737 vty_out(vty
, "%30s: ", "/32 equivalent ");
9738 vty_out(vty
, "%12g\n",
9739 ts
.total_space
* pow(2.0, -128 + 32));
9740 vty_out(vty
, "%30s: ", "/48 equivalent ");
9741 vty_out(vty
, "%12g\n",
9742 ts
.total_space
* pow(2.0, -128 + 48));
9744 vty_out(vty
, "%30s: ", "% announced ");
9745 vty_out(vty
, "%12.2f\n",
9746 ts
.total_space
* 100. * pow(2.0, -32));
9747 vty_out(vty
, "%30s: ", "/8 equivalent ");
9748 vty_out(vty
, "%12.2f\n",
9749 ts
.total_space
* pow(2.0, -32 + 8));
9750 vty_out(vty
, "%30s: ", "/24 equivalent ");
9751 vty_out(vty
, "%12.2f\n",
9752 ts
.total_space
* pow(2.0, -32 + 24));
9756 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9757 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9774 PCOUNT_PFCNT
, /* the figure we display to users */
9778 static const char *pcount_strs
[] = {
9779 [PCOUNT_ADJ_IN
] = "Adj-in",
9780 [PCOUNT_DAMPED
] = "Damped",
9781 [PCOUNT_REMOVED
] = "Removed",
9782 [PCOUNT_HISTORY
] = "History",
9783 [PCOUNT_STALE
] = "Stale",
9784 [PCOUNT_VALID
] = "Valid",
9785 [PCOUNT_ALL
] = "All RIB",
9786 [PCOUNT_COUNTED
] = "PfxCt counted",
9787 [PCOUNT_PFCNT
] = "Useable",
9788 [PCOUNT_MAX
] = NULL
,
9791 struct peer_pcounts
{
9792 unsigned int count
[PCOUNT_MAX
];
9793 const struct peer
*peer
;
9794 const struct bgp_table
*table
;
9797 static int bgp_peer_count_walker(struct thread
*t
)
9799 struct bgp_node
*rn
;
9800 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9801 const struct peer
*peer
= pc
->peer
;
9803 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9804 struct bgp_adj_in
*ain
;
9805 struct bgp_info
*ri
;
9807 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9808 if (ain
->peer
== peer
)
9809 pc
->count
[PCOUNT_ADJ_IN
]++;
9811 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9812 char buf
[SU_ADDRSTRLEN
];
9814 if (ri
->peer
!= peer
)
9817 pc
->count
[PCOUNT_ALL
]++;
9819 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9820 pc
->count
[PCOUNT_DAMPED
]++;
9821 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9822 pc
->count
[PCOUNT_HISTORY
]++;
9823 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9824 pc
->count
[PCOUNT_REMOVED
]++;
9825 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9826 pc
->count
[PCOUNT_STALE
]++;
9827 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9828 pc
->count
[PCOUNT_VALID
]++;
9829 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9830 pc
->count
[PCOUNT_PFCNT
]++;
9832 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9833 pc
->count
[PCOUNT_COUNTED
]++;
9834 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9836 "%s [pcount] %s/%d is counted but flags 0x%x",
9838 inet_ntop(rn
->p
.family
,
9839 &rn
->p
.u
.prefix
, buf
,
9841 rn
->p
.prefixlen
, ri
->flags
);
9843 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9845 "%s [pcount] %s/%d not counted but flags 0x%x",
9847 inet_ntop(rn
->p
.family
,
9848 &rn
->p
.u
.prefix
, buf
,
9850 rn
->p
.prefixlen
, ri
->flags
);
9857 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9858 safi_t safi
, uint8_t use_json
)
9860 struct peer_pcounts pcounts
= {.peer
= peer
};
9862 json_object
*json
= NULL
;
9863 json_object
*json_loop
= NULL
;
9866 json
= json_object_new_object();
9867 json_loop
= json_object_new_object();
9870 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9871 || !peer
->bgp
->rib
[afi
][safi
]) {
9873 json_object_string_add(
9875 "No such neighbor or address family");
9876 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9877 json_object_free(json
);
9879 vty_out(vty
, "%% No such neighbor or address family\n");
9884 memset(&pcounts
, 0, sizeof(pcounts
));
9885 pcounts
.peer
= peer
;
9886 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9888 /* in-place call via thread subsystem so as to record execution time
9889 * stats for the thread-walk (i.e. ensure this can't be blamed on
9890 * on just vty_read()).
9892 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9895 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9896 json_object_string_add(json
, "multiProtocol",
9897 afi_safi_print(afi
, safi
));
9898 json_object_int_add(json
, "pfxCounter",
9899 peer
->pcount
[afi
][safi
]);
9901 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9902 json_object_int_add(json_loop
, pcount_strs
[i
],
9905 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9907 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9908 json_object_string_add(json
, "pfxctDriftFor",
9910 json_object_string_add(
9911 json
, "recommended",
9912 "Please report this bug, with the above command output");
9914 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9915 json
, JSON_C_TO_STRING_PRETTY
));
9916 json_object_free(json
);
9920 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9921 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9922 peer
->hostname
, peer
->host
,
9923 afi_safi_print(afi
, safi
));
9925 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9926 afi_safi_print(afi
, safi
));
9929 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9930 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9932 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9933 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9936 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9937 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9939 "Please report this bug, with the above command output\n");
9946 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9947 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9948 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9949 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9953 BGP_INSTANCE_HELP_STR
9956 "Detailed information on TCP and BGP neighbor connections\n"
9957 "Neighbor to display information about\n"
9958 "Neighbor to display information about\n"
9959 "Neighbor on BGP configured interface\n"
9960 "Display detailed prefix count information\n"
9963 afi_t afi
= AFI_IP6
;
9964 safi_t safi
= SAFI_UNICAST
;
9967 struct bgp
*bgp
= NULL
;
9969 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9974 int uj
= use_json(argc
, argv
);
9978 argv_find(argv
, argc
, "neighbors", &idx
);
9979 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9983 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9986 #ifdef KEEP_OLD_VPN_COMMANDS
9987 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9988 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9989 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9994 "Display information about all VPNv4 NLRIs\n"
9995 "Detailed information on TCP and BGP neighbor connections\n"
9996 "Neighbor to display information about\n"
9997 "Neighbor to display information about\n"
9998 "Neighbor on BGP configured interface\n"
9999 "Display detailed prefix count information\n"
10004 uint8_t uj
= use_json(argc
, argv
);
10006 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10008 return CMD_WARNING
;
10010 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10013 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10014 show_ip_bgp_vpn_all_route_prefix_cmd
,
10015 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10020 "Display information about all VPNv4 NLRIs\n"
10021 "Network in the BGP routing table to display\n"
10022 "Network in the BGP routing table to display\n"
10026 char *network
= NULL
;
10027 struct bgp
*bgp
= bgp_get_default();
10029 vty_out(vty
, "Can't find default instance\n");
10030 return CMD_WARNING
;
10033 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10034 network
= argv
[idx
]->arg
;
10035 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10036 network
= argv
[idx
]->arg
;
10038 vty_out(vty
, "Unable to figure out Network\n");
10039 return CMD_WARNING
;
10042 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10043 BGP_PATH_ALL
, use_json(argc
, argv
));
10045 #endif /* KEEP_OLD_VPN_COMMANDS */
10047 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10048 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10049 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10055 "Display information about all EVPN NLRIs\n"
10056 "Network in the BGP routing table to display\n"
10057 "Network in the BGP routing table to display\n"
10061 char *network
= NULL
;
10063 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10064 network
= argv
[idx
]->arg
;
10065 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10066 network
= argv
[idx
]->arg
;
10068 vty_out(vty
, "Unable to figure out Network\n");
10069 return CMD_WARNING
;
10071 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10072 BGP_PATH_ALL
, use_json(argc
, argv
));
10075 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10076 safi_t safi
, enum bgp_show_adj_route_type type
,
10077 const char *rmap_name
, uint8_t use_json
,
10080 struct bgp_table
*table
;
10081 struct bgp_adj_in
*ain
;
10082 struct bgp_adj_out
*adj
;
10083 unsigned long output_count
;
10084 unsigned long filtered_count
;
10085 struct bgp_node
*rn
;
10091 struct update_subgroup
*subgrp
;
10092 json_object
*json_scode
= NULL
;
10093 json_object
*json_ocode
= NULL
;
10094 json_object
*json_ar
= NULL
;
10095 struct peer_af
*paf
;
10096 bool route_filtered
;
10099 json_scode
= json_object_new_object();
10100 json_ocode
= json_object_new_object();
10101 json_ar
= json_object_new_object();
10103 json_object_string_add(json_scode
, "suppressed", "s");
10104 json_object_string_add(json_scode
, "damped", "d");
10105 json_object_string_add(json_scode
, "history", "h");
10106 json_object_string_add(json_scode
, "valid", "*");
10107 json_object_string_add(json_scode
, "best", ">");
10108 json_object_string_add(json_scode
, "multipath", "=");
10109 json_object_string_add(json_scode
, "internal", "i");
10110 json_object_string_add(json_scode
, "ribFailure", "r");
10111 json_object_string_add(json_scode
, "stale", "S");
10112 json_object_string_add(json_scode
, "removed", "R");
10114 json_object_string_add(json_ocode
, "igp", "i");
10115 json_object_string_add(json_ocode
, "egp", "e");
10116 json_object_string_add(json_ocode
, "incomplete", "?");
10123 json_object_string_add(json
, "alert", "no BGP");
10124 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10125 json_object_free(json
);
10127 vty_out(vty
, "%% No bgp\n");
10131 table
= bgp
->rib
[afi
][safi
];
10133 output_count
= filtered_count
= 0;
10134 subgrp
= peer_subgroup(peer
, afi
, safi
);
10136 if (type
== bgp_show_adj_route_advertised
&& subgrp
10137 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10139 json_object_int_add(json
, "bgpTableVersion",
10141 json_object_string_add(json
, "bgpLocalRouterId",
10142 inet_ntoa(bgp
->router_id
));
10143 json_object_object_add(json
, "bgpStatusCodes",
10145 json_object_object_add(json
, "bgpOriginCodes",
10147 json_object_string_add(
10148 json
, "bgpOriginatingDefaultNetwork",
10149 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10151 vty_out(vty
, "BGP table version is %" PRIu64
10152 ", local router ID is %s, vrf id ",
10153 table
->version
, inet_ntoa(bgp
->router_id
));
10154 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10155 vty_out(vty
, "%s", VRFID_NONE_STR
);
10157 vty_out(vty
, "%u", bgp
->vrf_id
);
10158 vty_out(vty
, "\n");
10159 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10160 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10161 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10163 vty_out(vty
, "Originating default network %s\n\n",
10164 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10169 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10170 if (type
== bgp_show_adj_route_received
10171 || type
== bgp_show_adj_route_filtered
) {
10172 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10173 if (ain
->peer
!= peer
|| !ain
->attr
)
10178 json_object_int_add(
10179 json
, "bgpTableVersion",
10181 json_object_string_add(
10183 "bgpLocalRouterId",
10186 json_object_object_add(
10187 json
, "bgpStatusCodes",
10189 json_object_object_add(
10190 json
, "bgpOriginCodes",
10194 "BGP table version is 0, local router ID is %s, vrf id ",
10197 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10203 vty_out(vty
, "\n");
10205 BGP_SHOW_SCODE_HEADER
);
10207 BGP_SHOW_NCODE_HEADER
);
10209 BGP_SHOW_OCODE_HEADER
);
10215 vty_out(vty
, BGP_SHOW_HEADER
);
10219 bgp_attr_dup(&attr
, ain
->attr
);
10220 route_filtered
= false;
10222 /* Filter prefix using distribute list,
10223 * filter list or prefix list
10225 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10226 safi
)) == FILTER_DENY
)
10227 route_filtered
= true;
10229 /* Filter prefix using route-map */
10230 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10231 afi
, safi
, rmap_name
);
10233 if (type
== bgp_show_adj_route_filtered
&&
10234 !route_filtered
&& ret
!= RMAP_DENY
) {
10235 bgp_attr_undup(&attr
, ain
->attr
);
10239 if (type
== bgp_show_adj_route_received
&&
10240 (route_filtered
|| ret
== RMAP_DENY
))
10243 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10244 use_json
, json_ar
);
10245 bgp_attr_undup(&attr
, ain
->attr
);
10248 } else if (type
== bgp_show_adj_route_advertised
) {
10249 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10250 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10251 if (paf
->peer
!= peer
|| !adj
->attr
)
10256 json_object_int_add(
10260 json_object_string_add(
10262 "bgpLocalRouterId",
10265 json_object_object_add(
10269 json_object_object_add(
10275 "BGP table version is %" PRIu64
10276 ", local router ID is %s, vrf id ",
10289 vty_out(vty
, "\n");
10291 BGP_SHOW_SCODE_HEADER
);
10293 BGP_SHOW_NCODE_HEADER
);
10295 BGP_SHOW_OCODE_HEADER
);
10306 bgp_attr_dup(&attr
, adj
->attr
);
10307 ret
= bgp_output_modifier(
10308 peer
, &rn
->p
, &attr
, afi
, safi
,
10311 if (ret
!= RMAP_DENY
) {
10312 route_vty_out_tmp(vty
, &rn
->p
,
10321 bgp_attr_undup(&attr
, adj
->attr
);
10327 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10328 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10329 json_object_int_add(json
, "filteredPrefixCounter",
10332 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10333 json
, JSON_C_TO_STRING_PRETTY
));
10334 json_object_free(json
);
10335 } else if (output_count
> 0) {
10336 if (filtered_count
> 0)
10338 "\nTotal number of prefixes %ld (%ld filtered)\n",
10339 output_count
, filtered_count
);
10341 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10346 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10347 safi_t safi
, enum bgp_show_adj_route_type type
,
10348 const char *rmap_name
, uint8_t use_json
)
10350 json_object
*json
= NULL
;
10353 json
= json_object_new_object();
10355 /* labeled-unicast routes live in the unicast table */
10356 if (safi
== SAFI_LABELED_UNICAST
)
10357 safi
= SAFI_UNICAST
;
10359 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10361 json_object_string_add(
10363 "No such neighbor or address family");
10364 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10365 json_object_free(json
);
10367 vty_out(vty
, "%% No such neighbor or address family\n");
10369 return CMD_WARNING
;
10372 if ((type
== bgp_show_adj_route_received
10373 || type
== bgp_show_adj_route_filtered
)
10374 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10375 PEER_FLAG_SOFT_RECONFIG
)) {
10377 json_object_string_add(
10379 "Inbound soft reconfiguration not enabled");
10380 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10381 json_object_free(json
);
10384 "%% Inbound soft reconfiguration not enabled\n");
10386 return CMD_WARNING
;
10389 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10391 return CMD_SUCCESS
;
10394 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10395 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10396 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10397 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10401 BGP_INSTANCE_HELP_STR
10403 BGP_SAFI_WITH_LABEL_HELP_STR
10404 "Detailed information on TCP and BGP neighbor connections\n"
10405 "Neighbor to display information about\n"
10406 "Neighbor to display information about\n"
10407 "Neighbor on BGP configured interface\n"
10408 "Display the routes advertised to a BGP neighbor\n"
10409 "Display the received routes from neighbor\n"
10410 "Display the filtered routes received from neighbor\n"
10411 "Route-map to modify the attributes\n"
10412 "Name of the route map\n"
10415 afi_t afi
= AFI_IP6
;
10416 safi_t safi
= SAFI_UNICAST
;
10417 char *rmap_name
= NULL
;
10418 char *peerstr
= NULL
;
10419 struct bgp
*bgp
= NULL
;
10421 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10424 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10427 return CMD_WARNING
;
10429 int uj
= use_json(argc
, argv
);
10434 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10435 argv_find(argv
, argc
, "neighbors", &idx
);
10436 peerstr
= argv
[++idx
]->arg
;
10438 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10440 return CMD_WARNING
;
10442 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10443 type
= bgp_show_adj_route_advertised
;
10444 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10445 type
= bgp_show_adj_route_received
;
10446 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10447 type
= bgp_show_adj_route_filtered
;
10449 if (argv_find(argv
, argc
, "route-map", &idx
))
10450 rmap_name
= argv
[++idx
]->arg
;
10452 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10455 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10456 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10457 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10463 "Address Family modifier\n"
10464 "Detailed information on TCP and BGP neighbor connections\n"
10465 "Neighbor to display information about\n"
10466 "Neighbor to display information about\n"
10467 "Neighbor on BGP configured interface\n"
10468 "Display information received from a BGP neighbor\n"
10469 "Display the prefixlist filter\n"
10472 afi_t afi
= AFI_IP6
;
10473 safi_t safi
= SAFI_UNICAST
;
10474 char *peerstr
= NULL
;
10477 union sockunion su
;
10483 /* show [ip] bgp */
10484 if (argv_find(argv
, argc
, "ip", &idx
))
10486 /* [<ipv4|ipv6> [unicast]] */
10487 if (argv_find(argv
, argc
, "ipv4", &idx
))
10489 if (argv_find(argv
, argc
, "ipv6", &idx
))
10491 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10492 argv_find(argv
, argc
, "neighbors", &idx
);
10493 peerstr
= argv
[++idx
]->arg
;
10495 uint8_t uj
= use_json(argc
, argv
);
10497 ret
= str2sockunion(peerstr
, &su
);
10499 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10502 vty_out(vty
, "{}\n");
10505 "%% Malformed address or name: %s\n",
10507 return CMD_WARNING
;
10510 peer
= peer_lookup(NULL
, &su
);
10513 vty_out(vty
, "{}\n");
10515 vty_out(vty
, "No peer\n");
10516 return CMD_WARNING
;
10520 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10521 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10524 vty_out(vty
, "Address Family: %s\n",
10525 afi_safi_print(afi
, safi
));
10526 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10529 vty_out(vty
, "{}\n");
10531 vty_out(vty
, "No functional output\n");
10534 return CMD_SUCCESS
;
10537 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10538 afi_t afi
, safi_t safi
,
10539 enum bgp_show_type type
, uint8_t use_json
)
10541 /* labeled-unicast routes live in the unicast table */
10542 if (safi
== SAFI_LABELED_UNICAST
)
10543 safi
= SAFI_UNICAST
;
10545 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10547 json_object
*json_no
= NULL
;
10548 json_no
= json_object_new_object();
10549 json_object_string_add(
10550 json_no
, "warning",
10551 "No such neighbor or address family");
10552 vty_out(vty
, "%s\n",
10553 json_object_to_json_string(json_no
));
10554 json_object_free(json_no
);
10556 vty_out(vty
, "%% No such neighbor or address family\n");
10557 return CMD_WARNING
;
10560 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10563 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10564 show_ip_bgp_flowspec_routes_detailed_cmd
,
10565 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10569 BGP_INSTANCE_HELP_STR
10572 "Detailed information on flowspec entries\n"
10575 afi_t afi
= AFI_IP
;
10576 safi_t safi
= SAFI_UNICAST
;
10577 struct bgp
*bgp
= NULL
;
10580 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10583 return CMD_WARNING
;
10585 return bgp_show(vty
, bgp
, afi
, safi
,
10586 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10589 DEFUN (show_ip_bgp_neighbor_routes
,
10590 show_ip_bgp_neighbor_routes_cmd
,
10591 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10592 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10596 BGP_INSTANCE_HELP_STR
10598 BGP_SAFI_WITH_LABEL_HELP_STR
10599 "Detailed information on TCP and BGP neighbor connections\n"
10600 "Neighbor to display information about\n"
10601 "Neighbor to display information about\n"
10602 "Neighbor on BGP configured interface\n"
10603 "Display flap statistics of the routes learned from neighbor\n"
10604 "Display the dampened routes received from neighbor\n"
10605 "Display routes learned from neighbor\n"
10608 char *peerstr
= NULL
;
10609 struct bgp
*bgp
= NULL
;
10610 afi_t afi
= AFI_IP6
;
10611 safi_t safi
= SAFI_UNICAST
;
10613 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10617 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10620 return CMD_WARNING
;
10622 int uj
= use_json(argc
, argv
);
10626 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10627 argv_find(argv
, argc
, "neighbors", &idx
);
10628 peerstr
= argv
[++idx
]->arg
;
10630 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10632 return CMD_WARNING
;
10634 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10635 sh_type
= bgp_show_type_flap_neighbor
;
10636 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10637 sh_type
= bgp_show_type_damp_neighbor
;
10638 else if (argv_find(argv
, argc
, "routes", &idx
))
10639 sh_type
= bgp_show_type_neighbor
;
10641 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10644 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10646 struct bgp_distance
{
10647 /* Distance value for the IP source prefix. */
10650 /* Name of the access-list to be matched. */
10654 DEFUN (show_bgp_afi_vpn_rd_route
,
10655 show_bgp_afi_vpn_rd_route_cmd
,
10656 "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]",
10660 "Address Family modifier\n"
10661 "Display information for a route distinguisher\n"
10662 "Route Distinguisher\n"
10663 "Network in the BGP routing table to display\n"
10664 "Network in the BGP routing table to display\n"
10668 struct prefix_rd prd
;
10669 afi_t afi
= AFI_MAX
;
10672 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10673 vty_out(vty
, "%% Malformed Address Family\n");
10674 return CMD_WARNING
;
10677 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10679 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10680 return CMD_WARNING
;
10683 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10684 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10687 static struct bgp_distance
*bgp_distance_new(void)
10689 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10692 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10694 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10697 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10698 const char *ip_str
, const char *access_list_str
)
10705 struct bgp_node
*rn
;
10706 struct bgp_distance
*bdistance
;
10708 afi
= bgp_node_afi(vty
);
10709 safi
= bgp_node_safi(vty
);
10711 ret
= str2prefix(ip_str
, &p
);
10713 vty_out(vty
, "Malformed prefix\n");
10714 return CMD_WARNING_CONFIG_FAILED
;
10717 distance
= atoi(distance_str
);
10719 /* Get BGP distance node. */
10720 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10722 bdistance
= rn
->info
;
10723 bgp_unlock_node(rn
);
10725 bdistance
= bgp_distance_new();
10726 rn
->info
= bdistance
;
10729 /* Set distance value. */
10730 bdistance
->distance
= distance
;
10732 /* Reset access-list configuration. */
10733 if (bdistance
->access_list
) {
10734 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10735 bdistance
->access_list
= NULL
;
10737 if (access_list_str
)
10738 bdistance
->access_list
=
10739 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10741 return CMD_SUCCESS
;
10744 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10745 const char *ip_str
, const char *access_list_str
)
10752 struct bgp_node
*rn
;
10753 struct bgp_distance
*bdistance
;
10755 afi
= bgp_node_afi(vty
);
10756 safi
= bgp_node_safi(vty
);
10758 ret
= str2prefix(ip_str
, &p
);
10760 vty_out(vty
, "Malformed prefix\n");
10761 return CMD_WARNING_CONFIG_FAILED
;
10764 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10765 (struct prefix
*)&p
);
10767 vty_out(vty
, "Can't find specified prefix\n");
10768 return CMD_WARNING_CONFIG_FAILED
;
10771 bdistance
= rn
->info
;
10772 distance
= atoi(distance_str
);
10774 if (bdistance
->distance
!= distance
) {
10775 vty_out(vty
, "Distance does not match configured\n");
10776 return CMD_WARNING_CONFIG_FAILED
;
10779 if (bdistance
->access_list
)
10780 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10781 bgp_distance_free(bdistance
);
10784 bgp_unlock_node(rn
);
10785 bgp_unlock_node(rn
);
10787 return CMD_SUCCESS
;
10790 /* Apply BGP information to distance method. */
10791 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10792 safi_t safi
, struct bgp
*bgp
)
10794 struct bgp_node
*rn
;
10797 struct bgp_distance
*bdistance
;
10798 struct access_list
*alist
;
10799 struct bgp_static
*bgp_static
;
10804 peer
= rinfo
->peer
;
10806 /* Check source address. */
10807 sockunion2hostprefix(&peer
->su
, &q
);
10808 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10810 bdistance
= rn
->info
;
10811 bgp_unlock_node(rn
);
10813 if (bdistance
->access_list
) {
10814 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10816 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10817 return bdistance
->distance
;
10819 return bdistance
->distance
;
10822 /* Backdoor check. */
10823 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10825 bgp_static
= rn
->info
;
10826 bgp_unlock_node(rn
);
10828 if (bgp_static
->backdoor
) {
10829 if (bgp
->distance_local
[afi
][safi
])
10830 return bgp
->distance_local
[afi
][safi
];
10832 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10836 if (peer
->sort
== BGP_PEER_EBGP
) {
10837 if (bgp
->distance_ebgp
[afi
][safi
])
10838 return bgp
->distance_ebgp
[afi
][safi
];
10839 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10841 if (bgp
->distance_ibgp
[afi
][safi
])
10842 return bgp
->distance_ibgp
[afi
][safi
];
10843 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10847 DEFUN (bgp_distance
,
10849 "distance bgp (1-255) (1-255) (1-255)",
10850 "Define an administrative distance\n"
10852 "Distance for routes external to the AS\n"
10853 "Distance for routes internal to the AS\n"
10854 "Distance for local routes\n")
10856 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10857 int idx_number
= 2;
10858 int idx_number_2
= 3;
10859 int idx_number_3
= 4;
10863 afi
= bgp_node_afi(vty
);
10864 safi
= bgp_node_safi(vty
);
10866 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10867 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10868 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10869 return CMD_SUCCESS
;
10872 DEFUN (no_bgp_distance
,
10873 no_bgp_distance_cmd
,
10874 "no distance bgp [(1-255) (1-255) (1-255)]",
10876 "Define an administrative distance\n"
10878 "Distance for routes external to the AS\n"
10879 "Distance for routes internal to the AS\n"
10880 "Distance for local routes\n")
10882 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10886 afi
= bgp_node_afi(vty
);
10887 safi
= bgp_node_safi(vty
);
10889 bgp
->distance_ebgp
[afi
][safi
] = 0;
10890 bgp
->distance_ibgp
[afi
][safi
] = 0;
10891 bgp
->distance_local
[afi
][safi
] = 0;
10892 return CMD_SUCCESS
;
10896 DEFUN (bgp_distance_source
,
10897 bgp_distance_source_cmd
,
10898 "distance (1-255) A.B.C.D/M",
10899 "Define an administrative distance\n"
10900 "Administrative distance\n"
10901 "IP source prefix\n")
10903 int idx_number
= 1;
10904 int idx_ipv4_prefixlen
= 2;
10905 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10906 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10907 return CMD_SUCCESS
;
10910 DEFUN (no_bgp_distance_source
,
10911 no_bgp_distance_source_cmd
,
10912 "no distance (1-255) A.B.C.D/M",
10914 "Define an administrative distance\n"
10915 "Administrative distance\n"
10916 "IP source prefix\n")
10918 int idx_number
= 2;
10919 int idx_ipv4_prefixlen
= 3;
10920 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10921 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10922 return CMD_SUCCESS
;
10925 DEFUN (bgp_distance_source_access_list
,
10926 bgp_distance_source_access_list_cmd
,
10927 "distance (1-255) A.B.C.D/M WORD",
10928 "Define an administrative distance\n"
10929 "Administrative distance\n"
10930 "IP source prefix\n"
10931 "Access list name\n")
10933 int idx_number
= 1;
10934 int idx_ipv4_prefixlen
= 2;
10936 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10937 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10938 return CMD_SUCCESS
;
10941 DEFUN (no_bgp_distance_source_access_list
,
10942 no_bgp_distance_source_access_list_cmd
,
10943 "no distance (1-255) A.B.C.D/M WORD",
10945 "Define an administrative distance\n"
10946 "Administrative distance\n"
10947 "IP source prefix\n"
10948 "Access list name\n")
10950 int idx_number
= 2;
10951 int idx_ipv4_prefixlen
= 3;
10953 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10954 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10955 return CMD_SUCCESS
;
10958 DEFUN (ipv6_bgp_distance_source
,
10959 ipv6_bgp_distance_source_cmd
,
10960 "distance (1-255) X:X::X:X/M",
10961 "Define an administrative distance\n"
10962 "Administrative distance\n"
10963 "IP source prefix\n")
10965 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10966 return CMD_SUCCESS
;
10969 DEFUN (no_ipv6_bgp_distance_source
,
10970 no_ipv6_bgp_distance_source_cmd
,
10971 "no distance (1-255) X:X::X:X/M",
10973 "Define an administrative distance\n"
10974 "Administrative distance\n"
10975 "IP source prefix\n")
10977 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10978 return CMD_SUCCESS
;
10981 DEFUN (ipv6_bgp_distance_source_access_list
,
10982 ipv6_bgp_distance_source_access_list_cmd
,
10983 "distance (1-255) X:X::X:X/M WORD",
10984 "Define an administrative distance\n"
10985 "Administrative distance\n"
10986 "IP source prefix\n"
10987 "Access list name\n")
10989 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10990 return CMD_SUCCESS
;
10993 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10994 no_ipv6_bgp_distance_source_access_list_cmd
,
10995 "no distance (1-255) X:X::X:X/M WORD",
10997 "Define an administrative distance\n"
10998 "Administrative distance\n"
10999 "IP source prefix\n"
11000 "Access list name\n")
11002 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11003 return CMD_SUCCESS
;
11006 DEFUN (bgp_damp_set
,
11008 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11009 "BGP Specific commands\n"
11010 "Enable route-flap dampening\n"
11011 "Half-life time for the penalty\n"
11012 "Value to start reusing a route\n"
11013 "Value to start suppressing a route\n"
11014 "Maximum duration to suppress a stable route\n")
11016 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11017 int idx_half_life
= 2;
11019 int idx_suppress
= 4;
11020 int idx_max_suppress
= 5;
11021 int half
= DEFAULT_HALF_LIFE
* 60;
11022 int reuse
= DEFAULT_REUSE
;
11023 int suppress
= DEFAULT_SUPPRESS
;
11024 int max
= 4 * half
;
11027 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11028 reuse
= atoi(argv
[idx_reuse
]->arg
);
11029 suppress
= atoi(argv
[idx_suppress
]->arg
);
11030 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11031 } else if (argc
== 3) {
11032 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11036 if (suppress
< reuse
) {
11038 "Suppress value cannot be less than reuse value \n");
11042 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11043 reuse
, suppress
, max
);
11046 DEFUN (bgp_damp_unset
,
11047 bgp_damp_unset_cmd
,
11048 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11050 "BGP Specific commands\n"
11051 "Enable route-flap dampening\n"
11052 "Half-life time for the penalty\n"
11053 "Value to start reusing a route\n"
11054 "Value to start suppressing a route\n"
11055 "Maximum duration to suppress a stable route\n")
11057 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11058 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11061 /* Display specified route of BGP table. */
11062 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11063 const char *ip_str
, afi_t afi
, safi_t safi
,
11064 struct prefix_rd
*prd
, int prefix_check
)
11067 struct prefix match
;
11068 struct bgp_node
*rn
;
11069 struct bgp_node
*rm
;
11070 struct bgp_info
*ri
;
11071 struct bgp_info
*ri_temp
;
11073 struct bgp_table
*table
;
11075 /* BGP structure lookup. */
11077 bgp
= bgp_lookup_by_name(view_name
);
11079 vty_out(vty
, "%% Can't find BGP instance %s\n",
11081 return CMD_WARNING
;
11084 bgp
= bgp_get_default();
11086 vty_out(vty
, "%% No BGP process is configured\n");
11087 return CMD_WARNING
;
11091 /* Check IP address argument. */
11092 ret
= str2prefix(ip_str
, &match
);
11094 vty_out(vty
, "%% address is malformed\n");
11095 return CMD_WARNING
;
11098 match
.family
= afi2family(afi
);
11100 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11101 || (safi
== SAFI_EVPN
)) {
11102 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11103 rn
= bgp_route_next(rn
)) {
11104 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11106 if ((table
= rn
->info
) == NULL
)
11108 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11112 || rm
->p
.prefixlen
== match
.prefixlen
) {
11115 if (ri
->extra
&& ri
->extra
->damp_info
) {
11116 ri_temp
= ri
->next
;
11117 bgp_damp_info_free(
11118 ri
->extra
->damp_info
,
11126 bgp_unlock_node(rm
);
11129 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11132 || rn
->p
.prefixlen
== match
.prefixlen
) {
11135 if (ri
->extra
&& ri
->extra
->damp_info
) {
11136 ri_temp
= ri
->next
;
11137 bgp_damp_info_free(
11138 ri
->extra
->damp_info
,
11146 bgp_unlock_node(rn
);
11150 return CMD_SUCCESS
;
11153 DEFUN (clear_ip_bgp_dampening
,
11154 clear_ip_bgp_dampening_cmd
,
11155 "clear ip bgp dampening",
11159 "Clear route flap dampening information\n")
11161 bgp_damp_info_clean();
11162 return CMD_SUCCESS
;
11165 DEFUN (clear_ip_bgp_dampening_prefix
,
11166 clear_ip_bgp_dampening_prefix_cmd
,
11167 "clear ip bgp dampening A.B.C.D/M",
11171 "Clear route flap dampening information\n"
11174 int idx_ipv4_prefixlen
= 4;
11175 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11176 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11179 DEFUN (clear_ip_bgp_dampening_address
,
11180 clear_ip_bgp_dampening_address_cmd
,
11181 "clear ip bgp dampening A.B.C.D",
11185 "Clear route flap dampening information\n"
11186 "Network to clear damping information\n")
11189 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11190 SAFI_UNICAST
, NULL
, 0);
11193 DEFUN (clear_ip_bgp_dampening_address_mask
,
11194 clear_ip_bgp_dampening_address_mask_cmd
,
11195 "clear ip bgp dampening A.B.C.D A.B.C.D",
11199 "Clear route flap dampening information\n"
11200 "Network to clear damping information\n"
11204 int idx_ipv4_2
= 5;
11206 char prefix_str
[BUFSIZ
];
11208 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11211 vty_out(vty
, "%% Inconsistent address and mask\n");
11212 return CMD_WARNING
;
11215 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11219 /* also used for encap safi */
11220 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11221 afi_t afi
, safi_t safi
)
11223 struct bgp_node
*prn
;
11224 struct bgp_node
*rn
;
11225 struct bgp_table
*table
;
11227 struct prefix_rd
*prd
;
11228 struct bgp_static
*bgp_static
;
11229 mpls_label_t label
;
11230 char buf
[SU_ADDRSTRLEN
];
11231 char rdbuf
[RD_ADDRSTRLEN
];
11233 /* Network configuration. */
11234 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11235 prn
= bgp_route_next(prn
)) {
11236 if ((table
= prn
->info
) == NULL
)
11239 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11240 if ((bgp_static
= rn
->info
) == NULL
)
11244 prd
= (struct prefix_rd
*)&prn
->p
;
11246 /* "network" configuration display. */
11247 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11248 label
= decode_label(&bgp_static
->label
);
11250 vty_out(vty
, " network %s/%d rd %s",
11251 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11253 p
->prefixlen
, rdbuf
);
11254 if (safi
== SAFI_MPLS_VPN
)
11255 vty_out(vty
, " label %u", label
);
11257 if (bgp_static
->rmap
.name
)
11258 vty_out(vty
, " route-map %s",
11259 bgp_static
->rmap
.name
);
11261 if (bgp_static
->backdoor
)
11262 vty_out(vty
, " backdoor");
11264 vty_out(vty
, "\n");
11269 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11270 afi_t afi
, safi_t safi
)
11272 struct bgp_node
*prn
;
11273 struct bgp_node
*rn
;
11274 struct bgp_table
*table
;
11276 struct prefix_rd
*prd
;
11277 struct bgp_static
*bgp_static
;
11278 char buf
[PREFIX_STRLEN
* 2];
11279 char buf2
[SU_ADDRSTRLEN
];
11280 char rdbuf
[RD_ADDRSTRLEN
];
11282 /* Network configuration. */
11283 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11284 prn
= bgp_route_next(prn
)) {
11285 if ((table
= prn
->info
) == NULL
)
11288 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11289 if ((bgp_static
= rn
->info
) == NULL
)
11292 char *macrouter
= NULL
;
11295 if (bgp_static
->router_mac
)
11296 macrouter
= prefix_mac2str(
11297 bgp_static
->router_mac
, NULL
, 0);
11298 if (bgp_static
->eth_s_id
)
11299 esi
= esi2str(bgp_static
->eth_s_id
);
11301 prd
= (struct prefix_rd
*)&prn
->p
;
11303 /* "network" configuration display. */
11304 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11305 if (p
->u
.prefix_evpn
.route_type
== 5) {
11306 char local_buf
[PREFIX_STRLEN
];
11307 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11308 struct prefix_evpn
*)p
)
11312 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11313 local_buf
, PREFIX_STRLEN
);
11314 sprintf(buf
, "%s/%u", local_buf
,
11315 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11317 prefix2str(p
, buf
, sizeof(buf
));
11320 if (bgp_static
->gatewayIp
.family
== AF_INET
11321 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11322 inet_ntop(bgp_static
->gatewayIp
.family
,
11323 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11326 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11328 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11329 decode_label(&bgp_static
->label
), esi
, buf2
,
11333 XFREE(MTYPE_TMP
, macrouter
);
11335 XFREE(MTYPE_TMP
, esi
);
11340 /* Configuration of static route announcement and aggregate
11342 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11345 struct bgp_node
*rn
;
11347 struct bgp_static
*bgp_static
;
11348 struct bgp_aggregate
*bgp_aggregate
;
11349 char buf
[SU_ADDRSTRLEN
];
11351 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11352 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11356 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11357 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11361 /* Network configuration. */
11362 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11363 rn
= bgp_route_next(rn
)) {
11364 if ((bgp_static
= rn
->info
) == NULL
)
11369 /* "network" configuration display. */
11370 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11371 uint32_t destination
;
11372 struct in_addr netmask
;
11374 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11375 masklen2ip(p
->prefixlen
, &netmask
);
11376 vty_out(vty
, " network %s",
11377 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11380 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11381 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11382 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11383 || p
->u
.prefix4
.s_addr
== 0) {
11384 /* Natural mask is not display. */
11386 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11388 vty_out(vty
, " network %s/%d",
11389 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11394 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11395 vty_out(vty
, " label-index %u",
11396 bgp_static
->label_index
);
11398 if (bgp_static
->rmap
.name
)
11399 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11401 if (bgp_static
->backdoor
)
11402 vty_out(vty
, " backdoor");
11404 vty_out(vty
, "\n");
11407 /* Aggregate-address configuration. */
11408 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11409 rn
= bgp_route_next(rn
)) {
11410 if ((bgp_aggregate
= rn
->info
) == NULL
)
11415 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11416 struct in_addr netmask
;
11418 masklen2ip(p
->prefixlen
, &netmask
);
11419 vty_out(vty
, " aggregate-address %s %s",
11420 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11422 inet_ntoa(netmask
));
11424 vty_out(vty
, " aggregate-address %s/%d",
11425 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11430 if (bgp_aggregate
->as_set
)
11431 vty_out(vty
, " as-set");
11433 if (bgp_aggregate
->summary_only
)
11434 vty_out(vty
, " summary-only");
11436 vty_out(vty
, "\n");
11440 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11443 struct bgp_node
*rn
;
11444 struct bgp_distance
*bdistance
;
11446 /* Distance configuration. */
11447 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11448 && bgp
->distance_local
[afi
][safi
]
11449 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11450 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11451 || bgp
->distance_local
[afi
][safi
]
11452 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11453 vty_out(vty
, " distance bgp %d %d %d\n",
11454 bgp
->distance_ebgp
[afi
][safi
],
11455 bgp
->distance_ibgp
[afi
][safi
],
11456 bgp
->distance_local
[afi
][safi
]);
11459 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11460 rn
= bgp_route_next(rn
))
11461 if ((bdistance
= rn
->info
) != NULL
) {
11462 char buf
[PREFIX_STRLEN
];
11464 vty_out(vty
, " distance %d %s %s\n",
11465 bdistance
->distance
,
11466 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11467 bdistance
->access_list
? bdistance
->access_list
11472 /* Allocate routing table structure and install commands. */
11473 void bgp_route_init(void)
11478 /* Init BGP distance table. */
11479 FOREACH_AFI_SAFI (afi
, safi
)
11480 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11482 /* IPv4 BGP commands. */
11483 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11484 install_element(BGP_NODE
, &bgp_network_cmd
);
11485 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11487 install_element(BGP_NODE
, &aggregate_address_cmd
);
11488 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11489 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11490 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11492 /* IPv4 unicast configuration. */
11493 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11494 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11495 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11497 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11498 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11499 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11500 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11502 /* IPv4 multicast configuration. */
11503 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11504 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11505 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11506 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11507 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11508 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11509 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11511 /* IPv4 labeled-unicast configuration. */
11512 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11513 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11514 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11515 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11516 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11518 install_element(VIEW_NODE
,
11519 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11520 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11521 install_element(VIEW_NODE
,
11522 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11523 #ifdef KEEP_OLD_VPN_COMMANDS
11524 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11525 #endif /* KEEP_OLD_VPN_COMMANDS */
11526 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11527 install_element(VIEW_NODE
,
11528 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11530 /* BGP dampening clear commands */
11531 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11532 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11534 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11535 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11538 install_element(ENABLE_NODE
,
11539 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11540 #ifdef KEEP_OLD_VPN_COMMANDS
11541 install_element(ENABLE_NODE
,
11542 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11543 #endif /* KEEP_OLD_VPN_COMMANDS */
11545 /* New config IPv6 BGP commands. */
11546 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11547 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11548 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11550 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11551 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11553 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11555 install_element(BGP_NODE
, &bgp_distance_cmd
);
11556 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11557 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11558 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11559 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11560 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11561 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11562 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11563 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11564 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11565 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11566 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11567 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11568 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11569 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11570 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11571 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11572 install_element(BGP_IPV4M_NODE
,
11573 &no_bgp_distance_source_access_list_cmd
);
11574 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11575 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11576 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11577 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11578 install_element(BGP_IPV6_NODE
,
11579 &ipv6_bgp_distance_source_access_list_cmd
);
11580 install_element(BGP_IPV6_NODE
,
11581 &no_ipv6_bgp_distance_source_access_list_cmd
);
11582 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11583 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11584 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11585 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11586 install_element(BGP_IPV6M_NODE
,
11587 &ipv6_bgp_distance_source_access_list_cmd
);
11588 install_element(BGP_IPV6M_NODE
,
11589 &no_ipv6_bgp_distance_source_access_list_cmd
);
11591 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11592 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11593 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11594 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11596 /* IPv4 Multicast Mode */
11597 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11598 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11600 /* Large Communities */
11601 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11602 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11604 /* show bgp ipv4 flowspec detailed */
11605 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11609 void bgp_route_finish(void)
11614 FOREACH_AFI_SAFI (afi
, safi
) {
11615 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11616 bgp_distance_table
[afi
][safi
] = NULL
;