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_aspath.h"
48 #include "bgpd/bgp_regex.h"
49 #include "bgpd/bgp_community.h"
50 #include "bgpd/bgp_ecommunity.h"
51 #include "bgpd/bgp_lcommunity.h"
52 #include "bgpd/bgp_clist.h"
53 #include "bgpd/bgp_packet.h"
54 #include "bgpd/bgp_filter.h"
55 #include "bgpd/bgp_fsm.h"
56 #include "bgpd/bgp_mplsvpn.h"
57 #include "bgpd/bgp_nexthop.h"
58 #include "bgpd/bgp_damp.h"
59 #include "bgpd/bgp_advertise.h"
60 #include "bgpd/bgp_zebra.h"
61 #include "bgpd/bgp_vty.h"
62 #include "bgpd/bgp_mpath.h"
63 #include "bgpd/bgp_nht.h"
64 #include "bgpd/bgp_updgrp.h"
65 #include "bgpd/bgp_label.h"
68 #include "bgpd/rfapi/rfapi_backend.h"
69 #include "bgpd/rfapi/vnc_import_bgp.h"
70 #include "bgpd/rfapi/vnc_export_bgp.h"
72 #include "bgpd/bgp_encap_types.h"
73 #include "bgpd/bgp_encap_tlv.h"
74 #include "bgpd/bgp_evpn.h"
75 #include "bgpd/bgp_evpn_vty.h"
76 #include "bgpd/bgp_flowspec.h"
77 #include "bgpd/bgp_flowspec_util.h"
78 #include "bgpd/bgp_pbr.h"
80 #ifndef VTYSH_EXTRACT_PL
81 #include "bgpd/bgp_route_clippy.c"
84 /* Extern from bgp_dump.c */
85 extern const char *bgp_origin_str
[];
86 extern const char *bgp_origin_long_str
[];
89 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
90 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
91 static const struct message bgp_pmsi_tnltype_str
[] = {
92 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
93 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
94 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
95 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
96 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
97 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
98 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
99 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
103 #define VRFID_NONE_STR "-"
105 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
106 safi_t safi
, struct prefix
*p
,
107 struct prefix_rd
*prd
)
110 struct bgp_node
*prn
= NULL
;
116 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
117 || (safi
== SAFI_EVPN
)) {
118 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
120 if (prn
->info
== NULL
)
121 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
123 bgp_unlock_node(prn
);
127 rn
= bgp_node_get(table
, p
);
129 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
130 || (safi
== SAFI_EVPN
))
136 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
137 safi_t safi
, struct prefix
*p
,
138 struct prefix_rd
*prd
)
141 struct bgp_node
*prn
= NULL
;
146 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
147 || (safi
== SAFI_EVPN
)) {
148 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
152 if (prn
->info
== NULL
) {
153 bgp_unlock_node(prn
);
160 rn
= bgp_node_lookup(table
, p
);
165 /* Allocate bgp_info_extra */
166 static struct bgp_info_extra
*bgp_info_extra_new(void)
168 struct bgp_info_extra
*new;
169 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
170 new->label
[0] = MPLS_INVALID_LABEL
;
175 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
177 struct bgp_info_extra
*e
;
179 if (!extra
|| !*extra
)
184 bgp_damp_info_free(e
->damp_info
, 0);
188 struct bgp_info
*bi
= (struct bgp_info
*)e
->parent
;
191 bi
->net
= bgp_unlock_node((struct bgp_node
*)bi
->net
);
192 bgp_info_unlock(e
->parent
);
197 bgp_unlock(e
->bgp_orig
);
199 if ((*extra
)->bgp_fs_pbr
)
200 list_delete_all_node((*extra
)->bgp_fs_pbr
);
201 (*extra
)->bgp_fs_pbr
= NULL
;
202 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
207 /* Get bgp_info extra information for the given bgp_info, lazy allocated
210 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
213 ri
->extra
= bgp_info_extra_new();
217 /* Allocate new bgp info structure. */
218 struct bgp_info
*bgp_info_new(void)
220 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
223 /* Free bgp route information. */
224 static void bgp_info_free(struct bgp_info
*binfo
)
227 bgp_attr_unintern(&binfo
->attr
);
229 bgp_unlink_nexthop(binfo
);
230 bgp_info_extra_free(&binfo
->extra
);
231 bgp_info_mpath_free(&binfo
->mpath
);
233 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
235 XFREE(MTYPE_BGP_ROUTE
, binfo
);
238 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
244 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
246 assert(binfo
&& binfo
->lock
> 0);
249 if (binfo
->lock
== 0) {
251 zlog_debug ("%s: unlocked and freeing", __func__
);
252 zlog_backtrace (LOG_DEBUG
);
254 bgp_info_free(binfo
);
259 if (binfo
->lock
== 1)
261 zlog_debug ("%s: unlocked to 1", __func__
);
262 zlog_backtrace (LOG_DEBUG
);
269 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
271 struct bgp_info
*top
;
283 peer_lock(ri
->peer
); /* bgp_info peer reference */
286 /* Do the actual removal of info from RIB, for use by bgp_process
287 completion callback *only* */
288 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
291 ri
->next
->prev
= ri
->prev
;
293 ri
->prev
->next
= ri
->next
;
297 bgp_info_mpath_dequeue(ri
);
302 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
304 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
305 /* set of previous already took care of pcount */
306 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
309 /* undo the effects of a previous call to bgp_info_delete; typically
310 called when a route is deleted and then quickly re-added before the
311 deletion has been processed */
312 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
314 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
315 /* unset of previous already took care of pcount */
316 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
319 /* Adjust pcount as required */
320 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
322 struct bgp_table
*table
;
324 assert(rn
&& bgp_node_table(rn
));
325 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
327 table
= bgp_node_table(rn
);
329 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
332 if (!BGP_INFO_COUNTABLE(ri
)
333 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
335 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
337 /* slight hack, but more robust against errors. */
338 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
339 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
342 "%s: Asked to decrement 0 prefix count for peer %s",
343 __func__
, ri
->peer
->host
);
344 zlog_backtrace(LOG_WARNING
);
345 zlog_warn("%s: Please report to Quagga bugzilla",
348 } else if (BGP_INFO_COUNTABLE(ri
)
349 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
350 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
351 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
355 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
357 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
360 /* Set/unset bgp_info flags, adjusting any other state as needed.
361 * This is here primarily to keep prefix-count in check.
363 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, uint32_t flag
)
365 SET_FLAG(ri
->flags
, flag
);
367 /* early bath if we know it's not a flag that changes countability state
369 if (!CHECK_FLAG(flag
,
370 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
373 bgp_pcount_adjust(rn
, ri
);
376 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
379 UNSET_FLAG(ri
->flags
, flag
);
381 /* early bath if we know it's not a flag that changes countability state
383 if (!CHECK_FLAG(flag
,
384 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
387 bgp_pcount_adjust(rn
, ri
);
390 /* Get MED value. If MED value is missing and "bgp bestpath
391 missing-as-worst" is specified, treat it as the worst value. */
392 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
394 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
397 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
404 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
406 if (ri
->addpath_rx_id
)
407 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
410 sprintf(buf
, "path %s", ri
->peer
->host
);
413 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
415 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
416 struct bgp_info
*exist
, int *paths_eq
,
417 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
418 char *pfx_buf
, afi_t afi
, safi_t safi
)
420 struct attr
*newattr
, *existattr
;
421 bgp_peer_sort_t new_sort
;
422 bgp_peer_sort_t exist_sort
;
428 uint32_t exist_weight
;
429 uint32_t newm
, existm
;
430 struct in_addr new_id
;
431 struct in_addr exist_id
;
434 int internal_as_route
;
437 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
438 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
440 uint32_t exist_mm_seq
;
447 zlog_debug("%s: new is NULL", pfx_buf
);
452 bgp_info_path_with_addpath_rx_str(new, new_buf
);
456 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
462 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
463 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
464 pfx_buf
, new_buf
, new->flags
, exist_buf
,
469 existattr
= exist
->attr
;
471 /* For EVPN routes, we cannot just go by local vs remote, we have to
472 * look at the MAC mobility sequence number, if present.
474 if (safi
== SAFI_EVPN
) {
475 /* This is an error condition described in RFC 7432 Section
477 * states that in this scenario "the PE MUST alert the operator"
479 * does not state what other action to take. In order to provide
481 * consistency in this scenario we are going to prefer the path
485 if (newattr
->sticky
!= existattr
->sticky
) {
487 prefix2str(&new->net
->p
, pfx_buf
,
489 * PREFIX2STR_BUFFER
);
490 bgp_info_path_with_addpath_rx_str(new, new_buf
);
491 bgp_info_path_with_addpath_rx_str(exist
,
495 if (newattr
->sticky
&& !existattr
->sticky
) {
497 "%s: %s wins over %s due to sticky MAC flag",
498 pfx_buf
, new_buf
, exist_buf
);
502 if (!newattr
->sticky
&& existattr
->sticky
) {
504 "%s: %s loses to %s due to sticky MAC flag",
505 pfx_buf
, new_buf
, exist_buf
);
510 new_mm_seq
= mac_mobility_seqnum(newattr
);
511 exist_mm_seq
= mac_mobility_seqnum(existattr
);
513 if (new_mm_seq
> exist_mm_seq
) {
516 "%s: %s wins over %s due to MM seq %u > %u",
517 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
522 if (new_mm_seq
< exist_mm_seq
) {
525 "%s: %s loses to %s due to MM seq %u < %u",
526 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
532 /* 1. Weight check. */
533 new_weight
= newattr
->weight
;
534 exist_weight
= existattr
->weight
;
536 if (new_weight
> exist_weight
) {
538 zlog_debug("%s: %s wins over %s due to weight %d > %d",
539 pfx_buf
, new_buf
, exist_buf
, new_weight
,
544 if (new_weight
< exist_weight
) {
546 zlog_debug("%s: %s loses to %s due to weight %d < %d",
547 pfx_buf
, new_buf
, exist_buf
, new_weight
,
552 /* 2. Local preference check. */
553 new_pref
= exist_pref
= bgp
->default_local_pref
;
555 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
556 new_pref
= newattr
->local_pref
;
557 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
558 exist_pref
= existattr
->local_pref
;
560 if (new_pref
> exist_pref
) {
563 "%s: %s wins over %s due to localpref %d > %d",
564 pfx_buf
, new_buf
, exist_buf
, new_pref
,
569 if (new_pref
< exist_pref
) {
572 "%s: %s loses to %s due to localpref %d < %d",
573 pfx_buf
, new_buf
, exist_buf
, new_pref
,
578 /* 3. Local route check. We prefer:
580 * - BGP_ROUTE_AGGREGATE
581 * - BGP_ROUTE_REDISTRIBUTE
583 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
584 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
587 "%s: %s wins over %s due to preferred BGP_ROUTE type",
588 pfx_buf
, new_buf
, exist_buf
);
592 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
593 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
596 "%s: %s loses to %s due to preferred BGP_ROUTE type",
597 pfx_buf
, new_buf
, exist_buf
);
601 /* 4. AS path length check. */
602 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
603 int exist_hops
= aspath_count_hops(existattr
->aspath
);
604 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
606 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
609 aspath_hops
= aspath_count_hops(newattr
->aspath
);
610 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
612 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
615 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
616 pfx_buf
, new_buf
, exist_buf
,
618 (exist_hops
+ exist_confeds
));
622 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
625 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
626 pfx_buf
, new_buf
, exist_buf
,
628 (exist_hops
+ exist_confeds
));
632 int newhops
= aspath_count_hops(newattr
->aspath
);
634 if (newhops
< exist_hops
) {
637 "%s: %s wins over %s due to aspath hopcount %d < %d",
638 pfx_buf
, new_buf
, exist_buf
,
639 newhops
, exist_hops
);
643 if (newhops
> exist_hops
) {
646 "%s: %s loses to %s due to aspath hopcount %d > %d",
647 pfx_buf
, new_buf
, exist_buf
,
648 newhops
, exist_hops
);
654 /* 5. Origin check. */
655 if (newattr
->origin
< existattr
->origin
) {
657 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
658 pfx_buf
, new_buf
, exist_buf
,
659 bgp_origin_long_str
[newattr
->origin
],
660 bgp_origin_long_str
[existattr
->origin
]);
664 if (newattr
->origin
> existattr
->origin
) {
666 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
667 pfx_buf
, new_buf
, exist_buf
,
668 bgp_origin_long_str
[newattr
->origin
],
669 bgp_origin_long_str
[existattr
->origin
]);
674 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
675 && aspath_count_hops(existattr
->aspath
) == 0);
676 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
677 && aspath_count_confeds(existattr
->aspath
) > 0
678 && aspath_count_hops(newattr
->aspath
) == 0
679 && aspath_count_hops(existattr
->aspath
) == 0);
681 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
682 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
683 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
684 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
685 || internal_as_route
) {
686 new_med
= bgp_med_value(new->attr
, bgp
);
687 exist_med
= bgp_med_value(exist
->attr
, bgp
);
689 if (new_med
< exist_med
) {
692 "%s: %s wins over %s due to MED %d < %d",
693 pfx_buf
, new_buf
, exist_buf
, new_med
,
698 if (new_med
> exist_med
) {
701 "%s: %s loses to %s due to MED %d > %d",
702 pfx_buf
, new_buf
, exist_buf
, new_med
,
708 /* 7. Peer type check. */
709 new_sort
= new->peer
->sort
;
710 exist_sort
= exist
->peer
->sort
;
712 if (new_sort
== BGP_PEER_EBGP
713 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
716 "%s: %s wins over %s due to eBGP peer > iBGP peer",
717 pfx_buf
, new_buf
, exist_buf
);
721 if (exist_sort
== BGP_PEER_EBGP
722 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
725 "%s: %s loses to %s due to iBGP peer < eBGP peer",
726 pfx_buf
, new_buf
, exist_buf
);
730 /* 8. IGP metric check. */
734 newm
= new->extra
->igpmetric
;
736 existm
= exist
->extra
->igpmetric
;
741 "%s: %s wins over %s due to IGP metric %d < %d",
742 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
749 "%s: %s loses to %s due to IGP metric %d > %d",
750 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
754 /* 9. Same IGP metric. Compare the cluster list length as
755 representative of IGP hops metric. Rewrite the metric value
756 pair (newm, existm) with the cluster list length. Prefer the
757 path with smaller cluster list length. */
758 if (newm
== existm
) {
759 if (peer_sort(new->peer
) == BGP_PEER_IBGP
760 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
761 && (mpath_cfg
== NULL
763 mpath_cfg
->ibgp_flags
,
764 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
765 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
766 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
771 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
772 pfx_buf
, new_buf
, exist_buf
,
780 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
781 pfx_buf
, new_buf
, exist_buf
,
788 /* 10. confed-external vs. confed-internal */
789 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
790 if (new_sort
== BGP_PEER_CONFED
791 && exist_sort
== BGP_PEER_IBGP
) {
794 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
795 pfx_buf
, new_buf
, exist_buf
);
799 if (exist_sort
== BGP_PEER_CONFED
800 && new_sort
== BGP_PEER_IBGP
) {
803 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
804 pfx_buf
, new_buf
, exist_buf
);
809 /* 11. Maximum path check. */
810 if (newm
== existm
) {
811 /* If one path has a label but the other does not, do not treat
812 * them as equals for multipath
814 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
816 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
819 "%s: %s and %s cannot be multipath, one has a label while the other does not",
820 pfx_buf
, new_buf
, exist_buf
);
821 } else if (bgp_flag_check(bgp
,
822 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
825 * For the two paths, all comparison steps till IGP
827 * have succeeded - including AS_PATH hop count. Since
829 * bestpath as-path multipath-relax' knob is on, we
831 * an exact match of AS_PATH. Thus, mark the paths are
833 * That will trigger both these paths to get into the
841 "%s: %s and %s are equal via multipath-relax",
842 pfx_buf
, new_buf
, exist_buf
);
843 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
844 if (aspath_cmp(new->attr
->aspath
,
845 exist
->attr
->aspath
)) {
850 "%s: %s and %s are equal via matching aspaths",
851 pfx_buf
, new_buf
, exist_buf
);
853 } else if (new->peer
->as
== exist
->peer
->as
) {
858 "%s: %s and %s are equal via same remote-as",
859 pfx_buf
, new_buf
, exist_buf
);
863 * TODO: If unequal cost ibgp multipath is enabled we can
864 * mark the paths as equal here instead of returning
869 "%s: %s wins over %s after IGP metric comparison",
870 pfx_buf
, new_buf
, exist_buf
);
873 "%s: %s loses to %s after IGP metric comparison",
874 pfx_buf
, new_buf
, exist_buf
);
879 /* 12. If both paths are external, prefer the path that was received
880 first (the oldest one). This step minimizes route-flap, since a
881 newer path won't displace an older one, even if it was the
882 preferred route based on the additional decision criteria below. */
883 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
884 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
885 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
888 "%s: %s wins over %s due to oldest external",
889 pfx_buf
, new_buf
, exist_buf
);
893 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
896 "%s: %s loses to %s due to oldest external",
897 pfx_buf
, new_buf
, exist_buf
);
902 /* 13. Router-ID comparision. */
903 /* If one of the paths is "stale", the corresponding peer router-id will
904 * be 0 and would always win over the other path. If originator id is
905 * used for the comparision, it will decide which path is better.
907 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
908 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
910 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
911 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
912 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
914 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
916 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
919 "%s: %s wins over %s due to Router-ID comparison",
920 pfx_buf
, new_buf
, exist_buf
);
924 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
927 "%s: %s loses to %s due to Router-ID comparison",
928 pfx_buf
, new_buf
, exist_buf
);
932 /* 14. Cluster length comparision. */
933 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
934 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
936 if (new_cluster
< exist_cluster
) {
939 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
940 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
945 if (new_cluster
> exist_cluster
) {
948 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
949 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
954 /* 15. Neighbor address comparision. */
955 /* Do this only if neither path is "stale" as stale paths do not have
956 * valid peer information (as the connection may or may not be up).
958 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
961 "%s: %s wins over %s due to latter path being STALE",
962 pfx_buf
, new_buf
, exist_buf
);
966 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
969 "%s: %s loses to %s due to former path being STALE",
970 pfx_buf
, new_buf
, exist_buf
);
974 /* locally configured routes to advertise do not have su_remote */
975 if (new->peer
->su_remote
== NULL
)
977 if (exist
->peer
->su_remote
== NULL
)
980 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
985 "%s: %s loses to %s due to Neighor IP comparison",
986 pfx_buf
, new_buf
, exist_buf
);
993 "%s: %s wins over %s due to Neighor IP comparison",
994 pfx_buf
, new_buf
, exist_buf
);
999 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1000 pfx_buf
, new_buf
, exist_buf
);
1005 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1006 * is preferred, or 0 if they are the same (usually will only occur if
1007 * multipath is enabled
1008 * This version is compatible with */
1009 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
1010 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
1015 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
1029 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1030 struct attr
*attr
, afi_t afi
,
1033 struct bgp_filter
*filter
;
1035 filter
= &peer
->filter
[afi
][safi
];
1037 #define FILTER_EXIST_WARN(F, f, filter) \
1038 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1039 zlog_warn("%s: Could not find configured input %s-list %s!", \
1040 peer->host, #f, F##_IN_NAME(filter));
1042 if (DISTRIBUTE_IN_NAME(filter
)) {
1043 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1045 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1049 if (PREFIX_LIST_IN_NAME(filter
)) {
1050 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1052 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1056 if (FILTER_LIST_IN_NAME(filter
)) {
1057 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1059 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1064 return FILTER_PERMIT
;
1065 #undef FILTER_EXIST_WARN
1068 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1069 struct attr
*attr
, afi_t afi
,
1072 struct bgp_filter
*filter
;
1074 filter
= &peer
->filter
[afi
][safi
];
1076 #define FILTER_EXIST_WARN(F, f, filter) \
1077 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1078 zlog_warn("%s: Could not find configured output %s-list %s!", \
1079 peer->host, #f, F##_OUT_NAME(filter));
1081 if (DISTRIBUTE_OUT_NAME(filter
)) {
1082 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1084 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1088 if (PREFIX_LIST_OUT_NAME(filter
)) {
1089 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1091 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1096 if (FILTER_LIST_OUT_NAME(filter
)) {
1097 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1099 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1104 return FILTER_PERMIT
;
1105 #undef FILTER_EXIST_WARN
1108 /* If community attribute includes no_export then return 1. */
1109 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1111 if (attr
->community
) {
1112 /* NO_ADVERTISE check. */
1113 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1116 /* NO_EXPORT check. */
1117 if (peer
->sort
== BGP_PEER_EBGP
1118 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1121 /* NO_EXPORT_SUBCONFED check. */
1122 if (peer
->sort
== BGP_PEER_EBGP
1123 || peer
->sort
== BGP_PEER_CONFED
)
1124 if (community_include(attr
->community
,
1125 COMMUNITY_NO_EXPORT_SUBCONFED
))
1131 /* Route reflection loop check. */
1132 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1134 struct in_addr cluster_id
;
1136 if (attr
->cluster
) {
1137 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1138 cluster_id
= peer
->bgp
->cluster_id
;
1140 cluster_id
= peer
->bgp
->router_id
;
1142 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1148 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1149 struct attr
*attr
, afi_t afi
, safi_t safi
,
1150 const char *rmap_name
)
1152 struct bgp_filter
*filter
;
1153 struct bgp_info info
;
1154 route_map_result_t ret
;
1155 struct route_map
*rmap
= NULL
;
1157 filter
= &peer
->filter
[afi
][safi
];
1159 /* Apply default weight value. */
1160 if (peer
->weight
[afi
][safi
])
1161 attr
->weight
= peer
->weight
[afi
][safi
];
1164 rmap
= route_map_lookup_by_name(rmap_name
);
1169 if (ROUTE_MAP_IN_NAME(filter
)) {
1170 rmap
= ROUTE_MAP_IN(filter
);
1177 /* Route map apply. */
1179 memset(&info
, 0, sizeof(struct bgp_info
));
1180 /* Duplicate current value to new strucutre for modification. */
1184 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1186 /* Apply BGP route map to the attribute. */
1187 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1189 peer
->rmap_type
= 0;
1191 if (ret
== RMAP_DENYMATCH
)
1197 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1198 struct attr
*attr
, afi_t afi
, safi_t safi
,
1199 const char *rmap_name
)
1201 struct bgp_info info
;
1202 route_map_result_t ret
;
1203 struct route_map
*rmap
= NULL
;
1207 * So if we get to this point and have no rmap_name
1208 * we want to just show the output as it currently
1214 /* Apply default weight value. */
1215 if (peer
->weight
[afi
][safi
])
1216 attr
->weight
= peer
->weight
[afi
][safi
];
1218 rmap
= route_map_lookup_by_name(rmap_name
);
1221 * If we have a route map name and we do not find
1222 * the routemap that means we have an implicit
1228 memset(&info
, 0, sizeof(struct bgp_info
));
1229 /* Route map apply. */
1230 /* Duplicate current value to new strucutre for modification. */
1234 rmap_type
= peer
->rmap_type
;
1235 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1237 /* Apply BGP route map to the attribute. */
1238 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1240 peer
->rmap_type
= rmap_type
;
1242 if (ret
== RMAP_DENYMATCH
)
1244 * caller has multiple error paths with bgp_attr_flush()
1251 /* If this is an EBGP peer with remove-private-AS */
1252 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1253 struct peer
*peer
, struct attr
*attr
)
1255 if (peer
->sort
== BGP_PEER_EBGP
1256 && (peer_af_flag_check(peer
, afi
, safi
,
1257 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1258 || peer_af_flag_check(peer
, afi
, safi
,
1259 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1260 || peer_af_flag_check(peer
, afi
, safi
,
1261 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1262 || peer_af_flag_check(peer
, afi
, safi
,
1263 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1264 // Take action on the entire aspath
1265 if (peer_af_flag_check(peer
, afi
, safi
,
1266 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1267 || peer_af_flag_check(peer
, afi
, safi
,
1268 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1269 if (peer_af_flag_check(
1271 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1272 attr
->aspath
= aspath_replace_private_asns(
1273 attr
->aspath
, bgp
->as
);
1275 // The entire aspath consists of private ASNs so create
1277 else if (aspath_private_as_check(attr
->aspath
))
1278 attr
->aspath
= aspath_empty_get();
1280 // There are some public and some private ASNs, remove
1283 attr
->aspath
= aspath_remove_private_asns(
1287 // 'all' was not specified so the entire aspath must be private
1289 // for us to do anything
1290 else if (aspath_private_as_check(attr
->aspath
)) {
1291 if (peer_af_flag_check(
1293 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1294 attr
->aspath
= aspath_replace_private_asns(
1295 attr
->aspath
, bgp
->as
);
1297 attr
->aspath
= aspath_empty_get();
1302 /* If this is an EBGP peer with as-override */
1303 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1304 struct peer
*peer
, struct attr
*attr
)
1306 if (peer
->sort
== BGP_PEER_EBGP
1307 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1308 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1309 attr
->aspath
= aspath_replace_specific_asn(
1310 attr
->aspath
, peer
->as
, bgp
->as
);
1314 void bgp_attr_add_gshut_community(struct attr
*attr
)
1316 struct community
*old
;
1317 struct community
*new;
1318 struct community
*merge
;
1319 struct community
*gshut
;
1321 old
= attr
->community
;
1322 gshut
= community_str2com("graceful-shutdown");
1327 merge
= community_merge(community_dup(old
), gshut
);
1329 if (old
->refcnt
== 0)
1330 community_free(old
);
1332 new = community_uniq_sort(merge
);
1333 community_free(merge
);
1335 new = community_dup(gshut
);
1338 community_free(gshut
);
1339 attr
->community
= new;
1340 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1342 /* When we add the graceful-shutdown community we must also
1343 * lower the local-preference */
1344 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1345 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1349 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1351 if (family
== AF_INET
) {
1352 attr
->nexthop
.s_addr
= 0;
1353 attr
->mp_nexthop_global_in
.s_addr
= 0;
1355 if (family
== AF_INET6
)
1356 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1357 if (family
== AF_EVPN
)
1358 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1361 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1362 struct update_subgroup
*subgrp
, struct prefix
*p
,
1365 struct bgp_filter
*filter
;
1368 struct peer
*onlypeer
;
1370 struct attr
*riattr
;
1371 char buf
[PREFIX_STRLEN
];
1377 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1379 if (DISABLE_BGP_ANNOUNCE
)
1382 afi
= SUBGRP_AFI(subgrp
);
1383 safi
= SUBGRP_SAFI(subgrp
);
1384 peer
= SUBGRP_PEER(subgrp
);
1386 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1387 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1390 filter
= &peer
->filter
[afi
][safi
];
1391 bgp
= SUBGRP_INST(subgrp
);
1392 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1395 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1396 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1397 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1400 * direct and direct_ext type routes originate internally even
1401 * though they can have peer pointers that reference other
1404 prefix2str(p
, buf
, PREFIX_STRLEN
);
1405 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1411 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1412 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1413 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1414 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1416 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1421 /* With addpath we may be asked to TX all kinds of paths so make sure
1423 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1424 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1425 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1429 /* If this is not the bestpath then check to see if there is an enabled
1431 * feature that requires us to advertise it */
1432 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1433 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1438 /* Aggregate-address suppress check. */
1439 if (ri
->extra
&& ri
->extra
->suppress
)
1440 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1445 * If we are doing VRF 2 VRF leaking via the import
1446 * statement, we want to prevent the route going
1447 * off box as that the RT and RD created are localy
1448 * significant and globaly useless.
1450 if (safi
== SAFI_MPLS_VPN
&& ri
->extra
&& ri
->extra
->num_labels
1451 && ri
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1454 /* If it's labeled safi, make sure the route has a valid label. */
1455 if (safi
== SAFI_LABELED_UNICAST
) {
1456 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1457 if (!bgp_is_valid_label(&label
)) {
1458 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1459 zlog_debug("u%" PRIu64
":s%" PRIu64
1460 " %s/%d is filtered - no label (%p)",
1461 subgrp
->update_group
->id
, subgrp
->id
,
1462 inet_ntop(p
->family
, &p
->u
.prefix
,
1463 buf
, SU_ADDRSTRLEN
),
1464 p
->prefixlen
, &label
);
1469 /* Do not send back route to sender. */
1470 if (onlypeer
&& from
== onlypeer
) {
1474 /* Do not send the default route in the BGP table if the neighbor is
1475 * configured for default-originate */
1476 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1477 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1478 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1480 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1484 /* Transparency check. */
1485 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1486 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1491 /* If community is not disabled check the no-export and local. */
1492 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1493 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1495 "subgrpannouncecheck: community filter check fail");
1499 /* If the attribute has originator-id and it is same as remote
1501 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1502 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1503 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1505 "%s [Update:SEND] %s originator-id is same as "
1508 prefix2str(p
, buf
, sizeof(buf
)));
1512 /* ORF prefix-list filter check */
1513 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1514 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1515 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1516 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1517 if (peer
->orf_plist
[afi
][safi
]) {
1518 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1520 if (bgp_debug_update(NULL
, p
,
1521 subgrp
->update_group
, 0))
1523 "%s [Update:SEND] %s is filtered via ORF",
1531 /* Output filter check. */
1532 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1533 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1534 zlog_debug("%s [Update:SEND] %s is filtered",
1535 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1539 #ifdef BGP_SEND_ASPATH_CHECK
1540 /* AS path loop check. */
1541 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1542 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1544 "%s [Update:SEND] suppress announcement to peer AS %u "
1545 "that is part of AS path.",
1546 onlypeer
->host
, onlypeer
->as
);
1549 #endif /* BGP_SEND_ASPATH_CHECK */
1551 /* If we're a CONFED we need to loop check the CONFED ID too */
1552 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1553 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1554 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1556 "%s [Update:SEND] suppress announcement to peer AS %u"
1558 peer
->host
, bgp
->confed_id
);
1563 /* Route-Reflect check. */
1564 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1569 /* IBGP reflection check. */
1570 if (reflect
&& !samepeer_safe
) {
1571 /* A route from a Client peer. */
1572 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1573 PEER_FLAG_REFLECTOR_CLIENT
)) {
1574 /* Reflect to all the Non-Client peers and also to the
1575 Client peers other than the originator. Originator
1577 is already done. So there is noting to do. */
1578 /* no bgp client-to-client reflection check. */
1579 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1580 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1581 PEER_FLAG_REFLECTOR_CLIENT
))
1584 /* A route from a Non-client peer. Reflect to all other
1586 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1587 PEER_FLAG_REFLECTOR_CLIENT
))
1592 /* For modify attribute, copy it to temporary structure. */
1593 bgp_attr_dup(attr
, riattr
);
1595 /* If local-preference is not set. */
1596 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1597 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1598 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1599 attr
->local_pref
= bgp
->default_local_pref
;
1602 /* If originator-id is not set and the route is to be reflected,
1603 set the originator id */
1605 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1606 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1607 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1610 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1612 if (peer
->sort
== BGP_PEER_EBGP
1613 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1614 if (from
!= bgp
->peer_self
&& !transparent
1615 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1616 PEER_FLAG_MED_UNCHANGED
))
1618 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1621 /* Since the nexthop attribute can vary per peer, it is not explicitly
1623 * in announce check, only certain flags and length (or number of
1625 * -- for IPv6/MP_REACH) are set here in order to guide the update
1627 * code in setting the nexthop(s) on a per peer basis in
1629 * Typically, the source nexthop in the attribute is preserved but in
1631 * scenarios where we know it will always be overwritten, we reset the
1632 * nexthop to "0" in an attempt to achieve better Update packing. An
1633 * example of this is when a prefix from each of 2 IBGP peers needs to
1635 * announced to an EBGP peer (and they have the same attributes barring
1639 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1641 #define NEXTHOP_IS_V6 \
1642 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1643 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1644 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1645 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1647 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1649 * the peer (group) is configured to receive link-local nexthop
1651 * and it is available in the prefix OR we're not reflecting the route
1653 * the peer (group) to whom we're going to announce is on a shared
1655 * and this is either a self-originated route or the peer is EBGP.
1657 if (NEXTHOP_IS_V6
) {
1658 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1659 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1660 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1661 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1662 || (!reflect
&& peer
->shared_network
1663 && (from
== bgp
->peer_self
1664 || peer
->sort
== BGP_PEER_EBGP
))) {
1665 attr
->mp_nexthop_len
=
1666 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1669 /* Clear off link-local nexthop in source, whenever it is not
1671 * ensure more prefixes share the same attribute for
1674 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1675 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1676 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1679 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1680 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1682 /* Route map & unsuppress-map apply. */
1683 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1684 struct bgp_info info
;
1685 struct bgp_info_extra dummy_info_extra
;
1686 struct attr dummy_attr
;
1688 memset(&info
, 0, sizeof(struct bgp_info
));
1693 memcpy(&dummy_info_extra
, ri
->extra
,
1694 sizeof(struct bgp_info_extra
));
1695 info
.extra
= &dummy_info_extra
;
1698 /* don't confuse inbound and outbound setting */
1699 RESET_FLAG(attr
->rmap_change_flags
);
1702 * The route reflector is not allowed to modify the attributes
1703 * of the reflected IBGP routes unless explicitly allowed.
1705 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1706 && !bgp_flag_check(bgp
,
1707 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1708 bgp_attr_dup(&dummy_attr
, attr
);
1709 info
.attr
= &dummy_attr
;
1712 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1714 if (ri
->extra
&& ri
->extra
->suppress
)
1715 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1718 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1721 peer
->rmap_type
= 0;
1723 if (ret
== RMAP_DENYMATCH
) {
1724 bgp_attr_flush(attr
);
1729 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1730 if (peer
->sort
== BGP_PEER_IBGP
1731 || peer
->sort
== BGP_PEER_CONFED
) {
1732 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1733 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1735 bgp_attr_add_gshut_community(attr
);
1739 /* After route-map has been applied, we check to see if the nexthop to
1740 * be carried in the attribute (that is used for the announcement) can
1741 * be cleared off or not. We do this in all cases where we would be
1742 * setting the nexthop to "ourselves". For IPv6, we only need to
1744 * the global nexthop here; the link-local nexthop would have been
1746 * already, and if not, it is required by the update formation code.
1747 * Also see earlier comments in this function.
1750 * If route-map has performed some operation on the nexthop or the peer
1751 * configuration says to pass it unchanged, we cannot reset the nexthop
1752 * here, so only attempt to do it if these aren't true. Note that the
1753 * route-map handler itself might have cleared the nexthop, if for
1755 * it is configured as 'peer-address'.
1757 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1758 riattr
->rmap_change_flags
)
1760 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1761 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1762 /* We can reset the nexthop, if setting (or forcing) it to
1764 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1765 PEER_FLAG_NEXTHOP_SELF
)
1766 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1767 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1769 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1770 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1771 subgroup_announce_reset_nhop(
1772 (peer_cap_enhe(peer
, afi
, safi
)
1776 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1777 /* Can also reset the nexthop if announcing to EBGP, but
1779 * no peer in the subgroup is on a shared subnet.
1780 * Note: 3rd party nexthop currently implemented for
1783 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1785 subgroup_announce_reset_nhop(
1786 (peer_cap_enhe(peer
, afi
, safi
)
1790 } else if (CHECK_FLAG(ri
->flags
, BGP_INFO_ANNC_NH_SELF
)) {
1792 * This flag is used for leaked vpn-vrf routes
1794 int family
= p
->family
;
1796 if (peer_cap_enhe(peer
, afi
, safi
))
1799 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1801 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1802 __func__
, family2str(family
));
1803 subgroup_announce_reset_nhop(family
, attr
);
1806 /* If IPv6/MP and nexthop does not have any override and happens
1808 * be a link-local address, reset it so that we don't pass along
1810 * source's link-local IPv6 address to recipients who may not be
1812 * the same interface.
1814 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1815 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1816 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1823 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1824 struct bgp_maxpaths_cfg
*mpath_cfg
,
1825 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1827 struct bgp_info
*new_select
;
1828 struct bgp_info
*old_select
;
1829 struct bgp_info
*ri
;
1830 struct bgp_info
*ri1
;
1831 struct bgp_info
*ri2
;
1832 struct bgp_info
*nextri
= NULL
;
1833 int paths_eq
, do_mpath
, debug
;
1834 struct list mp_list
;
1835 char pfx_buf
[PREFIX2STR_BUFFER
];
1836 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1838 bgp_mp_list_init(&mp_list
);
1840 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1842 debug
= bgp_debug_bestpath(&rn
->p
);
1845 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1847 /* bgp deterministic-med */
1849 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1851 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1852 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1853 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1855 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1856 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1858 if (BGP_INFO_HOLDDOWN(ri1
))
1860 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1861 if (ri1
->peer
->status
!= Established
)
1866 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1867 if (CHECK_FLAG(ri2
->flags
,
1868 BGP_INFO_DMED_CHECK
))
1870 if (BGP_INFO_HOLDDOWN(ri2
))
1873 && ri2
->peer
!= bgp
->peer_self
1876 PEER_STATUS_NSF_WAIT
))
1877 if (ri2
->peer
->status
1881 if (aspath_cmp_left(ri1
->attr
->aspath
,
1883 || aspath_cmp_left_confed(
1885 ri2
->attr
->aspath
)) {
1886 if (bgp_info_cmp(bgp
, ri2
,
1892 bgp_info_unset_flag(
1894 BGP_INFO_DMED_SELECTED
);
1900 BGP_INFO_DMED_CHECK
);
1904 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1905 bgp_info_set_flag(rn
, new_select
,
1906 BGP_INFO_DMED_SELECTED
);
1909 bgp_info_path_with_addpath_rx_str(new_select
,
1911 zlog_debug("%s: %s is the bestpath from AS %u",
1913 aspath_get_first_as(
1914 new_select
->attr
->aspath
));
1919 /* Check old selected route and new selected route. */
1922 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1924 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1927 if (BGP_INFO_HOLDDOWN(ri
)) {
1928 /* reap REMOVED routes, if needs be
1929 * selected route must stay for a while longer though
1931 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1932 && (ri
!= old_select
))
1933 bgp_info_reap(rn
, ri
);
1936 zlog_debug("%s: ri %p in holddown", __func__
,
1942 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1943 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1944 if (ri
->peer
->status
!= Established
) {
1948 "%s: ri %p non self peer %s not estab state",
1949 __func__
, ri
, ri
->peer
->host
);
1954 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1955 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1956 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1958 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1962 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1964 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1965 debug
, pfx_buf
, afi
, safi
)) {
1970 /* Now that we know which path is the bestpath see if any of the other
1972 * qualify as multipaths
1976 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1978 sprintf(path_buf
, "NONE");
1980 "%s: After path selection, newbest is %s oldbest was %s",
1982 old_select
? old_select
->peer
->host
: "NONE");
1985 if (do_mpath
&& new_select
) {
1986 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1990 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1992 if (ri
== new_select
) {
1995 "%s: %s is the bestpath, add to the multipath list",
1997 bgp_mp_list_add(&mp_list
, ri
);
2001 if (BGP_INFO_HOLDDOWN(ri
))
2004 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
2005 && !CHECK_FLAG(ri
->peer
->sflags
,
2006 PEER_STATUS_NSF_WAIT
))
2007 if (ri
->peer
->status
!= Established
)
2010 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
2013 "%s: %s has the same nexthop as the bestpath, skip it",
2018 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
2019 debug
, pfx_buf
, afi
, safi
);
2024 "%s: %s is equivalent to the bestpath, add to the multipath list",
2026 bgp_mp_list_add(&mp_list
, ri
);
2031 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
2032 bgp_info_mpath_aggregate_update(new_select
, old_select
);
2033 bgp_mp_list_clear(&mp_list
);
2035 result
->old
= old_select
;
2036 result
->new = new_select
;
2042 * A new route/change in bestpath of an existing route. Evaluate the path
2043 * for advertisement to the subgroup.
2045 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2046 struct bgp_info
*selected
,
2047 struct bgp_node
*rn
,
2048 uint32_t addpath_tx_id
)
2051 struct peer
*onlypeer
;
2057 afi
= SUBGRP_AFI(subgrp
);
2058 safi
= SUBGRP_SAFI(subgrp
);
2059 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2062 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2063 char buf_prefix
[PREFIX_STRLEN
];
2064 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2065 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2069 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2070 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2071 PEER_STATUS_ORF_WAIT_REFRESH
))
2074 memset(&attr
, 0, sizeof(struct attr
));
2075 /* It's initialized in bgp_announce_check() */
2077 /* Announcement to the subgroup. If the route is filtered withdraw it.
2080 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2081 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2083 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2084 selected
->addpath_tx_id
);
2087 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2089 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2096 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2097 * This is called at the end of route processing.
2099 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2101 struct bgp_info
*ri
;
2103 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2104 if (BGP_INFO_HOLDDOWN(ri
))
2106 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2107 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2112 * Has the route changed from the RIB's perspective? This is invoked only
2113 * if the route selection returns the same best route as earlier - to
2114 * determine if we need to update zebra or not.
2116 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2118 struct bgp_info
*mpinfo
;
2120 /* If this is multipath, check all selected paths for any nexthop
2121 * change or attribute change. Some attribute changes (e.g., community)
2122 * aren't of relevance to the RIB, but we'll update zebra to ensure
2123 * we handle the case of BGP nexthop change. This is the behavior
2124 * when the best path has an attribute change anyway.
2126 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2127 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2131 * If this is multipath, check all selected paths for any nexthop change
2133 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2134 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2135 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2136 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2140 /* Nothing has changed from the RIB's perspective. */
2144 struct bgp_process_queue
{
2146 STAILQ_HEAD(, bgp_node
) pqueue
;
2147 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2149 unsigned int queued
;
2153 * old_select = The old best path
2154 * new_select = the new best path
2156 * if (!old_select && new_select)
2157 * We are sending new information on.
2159 * if (old_select && new_select) {
2160 * if (new_select != old_select)
2161 * We have a new best path send a change
2163 * We've received a update with new attributes that needs
2167 * if (old_select && !new_select)
2168 * We have no eligible route that we can announce or the rn
2171 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2172 afi_t afi
, safi_t safi
)
2174 struct bgp_info
*new_select
;
2175 struct bgp_info
*old_select
;
2176 struct bgp_info_pair old_and_new
;
2177 char pfx_buf
[PREFIX2STR_BUFFER
];
2180 /* Is it end of initial update? (after startup) */
2182 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2183 sizeof(bgp
->update_delay_zebra_resume_time
));
2185 bgp
->main_zebra_update_hold
= 0;
2186 FOREACH_AFI_SAFI (afi
, safi
) {
2187 if (bgp_fibupd_safi(safi
))
2188 bgp_zebra_announce_table(bgp
, afi
, safi
);
2190 bgp
->main_peers_update_hold
= 0;
2192 bgp_start_routeadv(bgp
);
2196 struct prefix
*p
= &rn
->p
;
2198 debug
= bgp_debug_bestpath(&rn
->p
);
2200 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2201 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2202 afi2str(afi
), safi2str(safi
));
2205 /* Best path selection. */
2206 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2208 old_select
= old_and_new
.old
;
2209 new_select
= old_and_new
.new;
2211 /* Do we need to allocate or free labels?
2212 * Right now, since we only deal with per-prefix labels, it is not
2213 * necessary to do this upon changes to best path except if the label
2216 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2219 || bgp_label_index_differs(new_select
, old_select
)
2220 || new_select
->sub_type
!= old_select
->sub_type
) {
2221 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2222 && new_select
->attr
->flag
2224 BGP_ATTR_PREFIX_SID
)
2225 && new_select
->attr
->label_index
2226 != BGP_INVALID_LABEL_INDEX
) {
2229 BGP_NODE_REGISTERED_FOR_LABEL
))
2230 bgp_unregister_for_label(rn
);
2231 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2233 bgp_set_valid_label(&rn
->local_label
);
2235 bgp_register_for_label(rn
, new_select
);
2237 } else if (CHECK_FLAG(rn
->flags
,
2238 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2239 bgp_unregister_for_label(rn
);
2241 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2242 bgp_unregister_for_label(rn
);
2246 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2248 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2249 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2250 old_select
, new_select
);
2253 /* If best route remains the same and this is not due to user-initiated
2254 * clear, see exactly what needs to be done.
2256 if (old_select
&& old_select
== new_select
2257 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2258 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2259 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2260 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2262 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2263 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2265 if (bgp_fibupd_safi(safi
)
2266 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2268 if (new_select
->type
== ZEBRA_ROUTE_BGP
2269 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2270 || new_select
->sub_type
2271 == BGP_ROUTE_IMPORTED
))
2273 bgp_zebra_announce(rn
, p
, old_select
,
2277 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2278 bgp_zebra_clear_route_change_flags(rn
);
2280 /* If there is a change of interest to peers, reannounce the
2282 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2283 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2284 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2286 /* unicast routes must also be annouced to
2287 * labeled-unicast update-groups */
2288 if (safi
== SAFI_UNICAST
)
2289 group_announce_route(bgp
, afi
,
2290 SAFI_LABELED_UNICAST
, rn
,
2293 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2294 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2297 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2301 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2303 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2305 /* bestpath has changed; bump version */
2306 if (old_select
|| new_select
) {
2307 bgp_bump_version(rn
);
2309 if (!bgp
->t_rmap_def_originate_eval
) {
2313 update_group_refresh_default_originate_route_map
,
2314 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2315 &bgp
->t_rmap_def_originate_eval
);
2320 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2323 zlog_debug("%s: setting SELECTED flag", __func__
);
2324 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2325 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2326 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2330 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2331 if (old_select
!= new_select
) {
2333 vnc_import_bgp_exterior_del_route(bgp
, p
,
2335 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2338 vnc_import_bgp_exterior_add_route(bgp
, p
,
2340 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2346 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2348 /* unicast routes must also be annouced to labeled-unicast update-groups
2350 if (safi
== SAFI_UNICAST
)
2351 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2355 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2356 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2357 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2358 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2359 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2360 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2362 /* if this is an evpn imported type-5 prefix,
2363 * we need to withdraw the route first to clear
2364 * the nh neigh and the RMAC entry.
2367 is_route_parent_evpn(old_select
))
2368 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2370 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2372 /* Withdraw the route from the kernel. */
2373 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2374 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2375 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2376 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2378 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2382 /* advertise/withdraw type-5 routes */
2383 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2384 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2385 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2387 /* apply the route-map */
2388 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2391 ret
= route_map_apply(
2392 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2393 &rn
->p
, RMAP_BGP
, new_select
);
2394 if (ret
== RMAP_MATCH
)
2395 bgp_evpn_advertise_type5_route(
2396 bgp
, &rn
->p
, new_select
->attr
,
2399 bgp_evpn_advertise_type5_route(bgp
,
2405 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2406 (!old_select
->extra
|| !old_select
->extra
->parent
))
2407 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2410 /* Clear any route change flags. */
2411 bgp_zebra_clear_route_change_flags(rn
);
2413 /* Reap old select bgp_info, if it has been removed */
2414 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2415 bgp_info_reap(rn
, old_select
);
2417 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2421 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2423 struct bgp_process_queue
*pqnode
= data
;
2424 struct bgp
*bgp
= pqnode
->bgp
;
2425 struct bgp_table
*table
;
2426 struct bgp_node
*rn
;
2429 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2430 bgp_process_main_one(bgp
, NULL
, 0, 0);
2431 /* should always have dedicated wq call */
2432 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2436 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2437 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2438 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2439 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2440 table
= bgp_node_table(rn
);
2441 /* note, new RNs may be added as part of processing */
2442 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2444 bgp_unlock_node(rn
);
2445 bgp_table_unlock(table
);
2451 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2453 struct bgp_process_queue
*pqnode
= data
;
2455 bgp_unlock(pqnode
->bgp
);
2457 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2460 void bgp_process_queue_init(void)
2462 if (!bm
->process_main_queue
) {
2463 bm
->process_main_queue
=
2464 work_queue_new(bm
->master
, "process_main_queue");
2466 if (!bm
->process_main_queue
) {
2467 zlog_err("%s: Failed to allocate work queue", __func__
);
2472 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2473 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2474 bm
->process_main_queue
->spec
.max_retries
= 0;
2475 bm
->process_main_queue
->spec
.hold
= 50;
2476 /* Use a higher yield value of 50ms for main queue processing */
2477 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2480 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2482 struct bgp_process_queue
*pqnode
;
2484 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2485 sizeof(struct bgp_process_queue
));
2487 /* unlocked in bgp_processq_del */
2488 pqnode
->bgp
= bgp_lock(bgp
);
2489 STAILQ_INIT(&pqnode
->pqueue
);
2494 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2496 #define ARBITRARY_PROCESS_QLEN 10000
2497 struct work_queue
*wq
= bm
->process_main_queue
;
2498 struct bgp_process_queue
*pqnode
;
2499 int pqnode_reuse
= 0;
2501 /* already scheduled for processing? */
2502 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2508 /* Add route nodes to an existing work queue item until reaching the
2509 limit only if is from the same BGP view and it's not an EOIU marker
2511 if (work_queue_item_count(wq
)) {
2512 struct work_queue_item
*item
= work_queue_last_item(wq
);
2513 pqnode
= item
->data
;
2515 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2516 || pqnode
->bgp
!= bgp
2517 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2518 pqnode
= bgp_processq_alloc(bgp
);
2522 pqnode
= bgp_processq_alloc(bgp
);
2523 /* all unlocked in bgp_process_wq */
2524 bgp_table_lock(bgp_node_table(rn
));
2526 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2529 /* can't be enqueued twice */
2530 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2531 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2535 work_queue_add(wq
, pqnode
);
2540 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2542 struct bgp_process_queue
*pqnode
;
2544 if (bm
->process_main_queue
== NULL
)
2547 pqnode
= bgp_processq_alloc(bgp
);
2549 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2550 work_queue_add(bm
->process_main_queue
, pqnode
);
2553 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2557 peer
= THREAD_ARG(thread
);
2558 peer
->t_pmax_restart
= NULL
;
2560 if (bgp_debug_neighbor_events(peer
))
2562 "%s Maximum-prefix restart timer expired, restore peering",
2565 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2566 zlog_debug("%s: %s peer_clear failed",
2567 __PRETTY_FUNCTION__
, peer
->host
);
2572 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2576 iana_safi_t pkt_safi
;
2578 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2581 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2582 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2583 PEER_STATUS_PREFIX_LIMIT
)
2588 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2590 afi_safi_print(afi
, safi
), peer
->host
,
2591 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2592 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2594 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2595 PEER_FLAG_MAX_PREFIX_WARNING
))
2598 /* Convert AFI, SAFI to values for packet. */
2599 pkt_afi
= afi_int2iana(afi
);
2600 pkt_safi
= safi_int2iana(safi
);
2604 ndata
[0] = (pkt_afi
>> 8);
2606 ndata
[2] = pkt_safi
;
2607 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2608 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2609 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2610 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2612 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2613 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2614 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2618 /* Dynamic peers will just close their connection. */
2619 if (peer_dynamic_neighbor(peer
))
2622 /* restart timer start */
2623 if (peer
->pmax_restart
[afi
][safi
]) {
2624 peer
->v_pmax_restart
=
2625 peer
->pmax_restart
[afi
][safi
] * 60;
2627 if (bgp_debug_neighbor_events(peer
))
2629 "%s Maximum-prefix restart timer started for %d secs",
2630 peer
->host
, peer
->v_pmax_restart
);
2632 BGP_TIMER_ON(peer
->t_pmax_restart
,
2633 bgp_maximum_prefix_restart_timer
,
2634 peer
->v_pmax_restart
);
2639 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2640 PEER_STATUS_PREFIX_LIMIT
);
2642 if (peer
->pcount
[afi
][safi
]
2643 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2644 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2645 PEER_STATUS_PREFIX_THRESHOLD
)
2650 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2651 afi_safi_print(afi
, safi
), peer
->host
,
2652 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2653 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2654 PEER_STATUS_PREFIX_THRESHOLD
);
2656 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2657 PEER_STATUS_PREFIX_THRESHOLD
);
2661 /* Unconditionally remove the route from the RIB, without taking
2662 * damping into consideration (eg, because the session went down)
2664 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2665 afi_t afi
, safi_t safi
)
2667 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2669 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2670 bgp_info_delete(rn
, ri
); /* keep historical info */
2672 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2675 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2676 struct peer
*peer
, afi_t afi
, safi_t safi
,
2677 struct prefix_rd
*prd
)
2679 /* apply dampening, if result is suppressed, we'll be retaining
2680 * the bgp_info in the RIB for historical reference.
2682 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2683 && peer
->sort
== BGP_PEER_EBGP
)
2684 if ((bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2685 == BGP_DAMP_SUPPRESSED
) {
2686 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2692 if (safi
== SAFI_MPLS_VPN
) {
2693 struct bgp_node
*prn
= NULL
;
2694 struct bgp_table
*table
= NULL
;
2696 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2697 (struct prefix
*)prd
);
2699 table
= (struct bgp_table
*)(prn
->info
);
2701 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2702 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2704 bgp_unlock_node(prn
);
2706 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2707 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2709 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2710 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2716 /* If this is an EVPN route, process for un-import. */
2717 if (safi
== SAFI_EVPN
)
2718 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2720 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2723 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2724 struct peer
*peer
, struct attr
*attr
,
2725 struct bgp_node
*rn
)
2727 struct bgp_info
*new;
2729 /* Make new BGP info. */
2730 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2732 new->instance
= instance
;
2733 new->sub_type
= sub_type
;
2736 new->uptime
= bgp_clock();
2738 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2742 static void overlay_index_update(struct attr
*attr
,
2743 struct eth_segment_id
*eth_s_id
,
2744 union gw_addr
*gw_ip
)
2749 if (eth_s_id
== NULL
) {
2750 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2751 sizeof(struct eth_segment_id
));
2753 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2754 sizeof(struct eth_segment_id
));
2756 if (gw_ip
== NULL
) {
2757 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2759 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2760 sizeof(union gw_addr
));
2764 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2765 struct eth_segment_id
*eth_s_id
,
2766 union gw_addr
*gw_ip
)
2768 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2769 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2772 if (afi
!= AFI_L2VPN
)
2775 memset(&temp
, 0, 16);
2776 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2777 info_gw_ip
= (union gw_addr
*)&temp
;
2778 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2781 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2782 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2785 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2787 info_gw_ip_remote
= gw_ip
;
2788 if (eth_s_id
== NULL
)
2789 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2791 info_eth_s_id_remote
= eth_s_id
;
2792 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2794 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2795 sizeof(struct eth_segment_id
));
2798 /* Check if received nexthop is valid or not. */
2799 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2804 /* Only validated for unicast and multicast currently. */
2805 /* Also valid for EVPN where the nexthop is an IP address. */
2806 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2809 /* If NEXT_HOP is present, validate it. */
2810 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2811 if (attr
->nexthop
.s_addr
== 0
2812 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2813 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2817 /* If MP_NEXTHOP is present, validate it. */
2818 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2819 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2820 * it is not an IPv6 link-local address.
2822 if (attr
->mp_nexthop_len
) {
2823 switch (attr
->mp_nexthop_len
) {
2824 case BGP_ATTR_NHLEN_IPV4
:
2825 case BGP_ATTR_NHLEN_VPNV4
:
2826 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2827 || IPV4_CLASS_DE(ntohl(
2828 attr
->mp_nexthop_global_in
.s_addr
))
2829 || bgp_nexthop_self(bgp
,
2830 attr
->mp_nexthop_global_in
));
2833 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2834 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2835 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2836 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2837 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2838 || IN6_IS_ADDR_MULTICAST(
2839 &attr
->mp_nexthop_global
));
2851 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2852 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2853 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2854 uint32_t num_labels
, int soft_reconfig
,
2855 struct bgp_route_evpn
*evpn
)
2858 int aspath_loop_count
= 0;
2859 struct bgp_node
*rn
;
2861 struct attr new_attr
;
2862 struct attr
*attr_new
;
2863 struct bgp_info
*ri
;
2864 struct bgp_info
*new;
2865 struct bgp_info_extra
*extra
;
2867 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2869 int do_loop_check
= 1;
2870 int has_valid_label
= 0;
2872 int vnc_implicit_withdraw
= 0;
2876 memset(&new_attr
, 0, sizeof(struct attr
));
2877 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2878 new_attr
.label
= MPLS_INVALID_LABEL
;
2881 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2882 /* TODO: Check to see if we can get rid of "is_valid_label" */
2883 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2884 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2886 has_valid_label
= bgp_is_valid_label(label
);
2888 /* When peer's soft reconfiguration enabled. Record input packet in
2891 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2892 && peer
!= bgp
->peer_self
)
2893 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2895 /* Check previously received route. */
2896 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2897 if (ri
->peer
== peer
&& ri
->type
== type
2898 && ri
->sub_type
== sub_type
2899 && ri
->addpath_rx_id
== addpath_id
)
2902 /* AS path local-as loop check. */
2903 if (peer
->change_local_as
) {
2904 if (peer
->allowas_in
[afi
][safi
])
2905 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2906 else if (!CHECK_FLAG(peer
->flags
,
2907 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2908 aspath_loop_count
= 1;
2910 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2911 > aspath_loop_count
) {
2912 reason
= "as-path contains our own AS;";
2917 /* If the peer is configured for "allowas-in origin" and the last ASN in
2919 * as-path is our ASN then we do not need to call aspath_loop_check
2921 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2922 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2925 /* AS path loop check. */
2926 if (do_loop_check
) {
2927 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2928 > peer
->allowas_in
[afi
][safi
]
2929 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2930 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2931 > peer
->allowas_in
[afi
][safi
])) {
2932 reason
= "as-path contains our own AS;";
2937 /* Route reflector originator ID check. */
2938 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2939 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2940 reason
= "originator is us;";
2944 /* Route reflector cluster ID check. */
2945 if (bgp_cluster_filter(peer
, attr
)) {
2946 reason
= "reflected from the same cluster;";
2950 /* Apply incoming filter. */
2951 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2956 bgp_attr_dup(&new_attr
, attr
);
2958 /* Apply incoming route-map.
2959 * NB: new_attr may now contain newly allocated values from route-map
2961 * commands, so we need bgp_attr_flush in the error paths, until we
2963 * the attr (which takes over the memory references) */
2964 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2966 reason
= "route-map;";
2967 bgp_attr_flush(&new_attr
);
2971 if (peer
->sort
== BGP_PEER_EBGP
) {
2973 /* If we receive the graceful-shutdown community from an eBGP
2974 * peer we must lower local-preference */
2975 if (new_attr
.community
2976 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2977 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2978 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2980 /* If graceful-shutdown is configured then add the GSHUT
2981 * community to all paths received from eBGP peers */
2982 } else if (bgp_flag_check(peer
->bgp
,
2983 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2984 bgp_attr_add_gshut_community(&new_attr
);
2988 /* next hop check. */
2989 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2990 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2991 reason
= "martian or self next-hop;";
2992 bgp_attr_flush(&new_attr
);
2996 attr_new
= bgp_attr_intern(&new_attr
);
2998 /* If the update is implicit withdraw. */
3000 ri
->uptime
= bgp_clock();
3001 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
3003 /* Same attribute comes in. */
3004 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
3005 && attrhash_cmp(ri
->attr
, attr_new
)
3006 && (!has_valid_label
3007 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
3008 num_labels
* sizeof(mpls_label_t
))
3010 && (overlay_index_equal(
3011 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3012 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3013 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3014 BGP_CONFIG_DAMPENING
)
3015 && peer
->sort
== BGP_PEER_EBGP
3016 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3017 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3018 bgp_debug_rdpfxpath2str(
3019 afi
, safi
, prd
, p
, label
,
3020 num_labels
, addpath_id
? 1 : 0,
3021 addpath_id
, pfx_buf
,
3023 zlog_debug("%s rcvd %s", peer
->host
,
3027 if (bgp_damp_update(ri
, rn
, afi
, safi
)
3028 != BGP_DAMP_SUPPRESSED
) {
3029 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
3031 bgp_process(bgp
, rn
, afi
, safi
);
3033 } else /* Duplicate - odd */
3035 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3036 if (!peer
->rcvd_attr_printed
) {
3038 "%s rcvd UPDATE w/ attr: %s",
3040 peer
->rcvd_attr_str
);
3041 peer
->rcvd_attr_printed
= 1;
3044 bgp_debug_rdpfxpath2str(
3045 afi
, safi
, prd
, p
, label
,
3046 num_labels
, addpath_id
? 1 : 0,
3047 addpath_id
, pfx_buf
,
3050 "%s rcvd %s...duplicate ignored",
3051 peer
->host
, pfx_buf
);
3054 /* graceful restart STALE flag unset. */
3055 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3056 bgp_info_unset_flag(rn
, ri
,
3058 bgp_process(bgp
, rn
, afi
, safi
);
3062 bgp_unlock_node(rn
);
3063 bgp_attr_unintern(&attr_new
);
3068 /* Withdraw/Announce before we fully processed the withdraw */
3069 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3070 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3071 bgp_debug_rdpfxpath2str(
3072 afi
, safi
, prd
, p
, label
, num_labels
,
3073 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3076 "%s rcvd %s, flapped quicker than processing",
3077 peer
->host
, pfx_buf
);
3080 bgp_info_restore(rn
, ri
);
3083 /* Received Logging. */
3084 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3085 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3086 num_labels
, addpath_id
? 1 : 0,
3087 addpath_id
, pfx_buf
,
3089 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3092 /* graceful restart STALE flag unset. */
3093 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3094 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3096 /* The attribute is changed. */
3097 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3099 /* implicit withdraw, decrement aggregate and pcount here.
3100 * only if update is accepted, they'll increment below.
3102 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3104 /* Update bgp route dampening information. */
3105 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3106 && peer
->sort
== BGP_PEER_EBGP
) {
3107 /* This is implicit withdraw so we should update
3110 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3111 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3114 if (safi
== SAFI_MPLS_VPN
) {
3115 struct bgp_node
*prn
= NULL
;
3116 struct bgp_table
*table
= NULL
;
3118 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3119 (struct prefix
*)prd
);
3121 table
= (struct bgp_table
*)(prn
->info
);
3123 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3124 bgp
, prd
, table
, p
, ri
);
3126 bgp_unlock_node(prn
);
3128 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3129 && (safi
== SAFI_UNICAST
)) {
3130 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3132 * Implicit withdraw case.
3134 ++vnc_implicit_withdraw
;
3135 vnc_import_bgp_del_route(bgp
, p
, ri
);
3136 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3141 /* Special handling for EVPN update of an existing route. If the
3142 * extended community attribute has changed, we need to
3144 * the route using its existing extended community. It will be
3145 * subsequently processed for import with the new extended
3148 if (safi
== SAFI_EVPN
&& !same_attr
) {
3150 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3152 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3155 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3156 attr_new
->ecommunity
);
3158 if (bgp_debug_update(peer
, p
, NULL
, 1))
3160 "Change in EXT-COMM, existing %s new %s",
3162 ri
->attr
->ecommunity
),
3164 attr_new
->ecommunity
));
3165 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3171 /* Update to new attribute. */
3172 bgp_attr_unintern(&ri
->attr
);
3173 ri
->attr
= attr_new
;
3175 /* Update MPLS label */
3176 if (has_valid_label
) {
3177 extra
= bgp_info_extra_get(ri
);
3178 memcpy(&extra
->label
, label
,
3179 num_labels
* sizeof(mpls_label_t
));
3180 extra
->num_labels
= num_labels
;
3181 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3182 bgp_set_valid_label(&extra
->label
[0]);
3186 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3187 && (safi
== SAFI_UNICAST
)) {
3188 if (vnc_implicit_withdraw
) {
3190 * Add back the route with its new attributes
3192 * The route is still selected, until the route
3194 * queued by bgp_process actually runs. We have
3196 * update to the VNC side immediately to avoid
3198 * configuration changes (e.g., route-map
3200 * trigger re-importation of the entire RIB.
3202 vnc_import_bgp_add_route(bgp
, p
, ri
);
3203 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3207 /* Update Overlay Index */
3208 if (afi
== AFI_L2VPN
) {
3209 overlay_index_update(
3210 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3211 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3214 /* Update bgp route dampening information. */
3215 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3216 && peer
->sort
== BGP_PEER_EBGP
) {
3217 /* Now we do normal update dampening. */
3218 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3219 if (ret
== BGP_DAMP_SUPPRESSED
) {
3220 bgp_unlock_node(rn
);
3225 /* Nexthop reachability check - for unicast and
3226 * labeled-unicast.. */
3227 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3228 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3229 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3230 && !CHECK_FLAG(peer
->flags
,
3231 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3233 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3238 struct bgp
*bgp_nexthop
= bgp
;
3240 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3241 bgp_nexthop
= ri
->extra
->bgp_orig
;
3243 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3244 ri
, NULL
, connected
)
3245 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3246 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3248 if (BGP_DEBUG(nht
, NHT
)) {
3249 char buf1
[INET6_ADDRSTRLEN
];
3251 (const void *)&attr_new
3253 buf1
, INET6_ADDRSTRLEN
);
3254 zlog_debug("%s(%s): NH unresolved",
3255 __FUNCTION__
, buf1
);
3257 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3260 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3263 if (safi
== SAFI_MPLS_VPN
) {
3264 struct bgp_node
*prn
= NULL
;
3265 struct bgp_table
*table
= NULL
;
3267 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3268 (struct prefix
*)prd
);
3270 table
= (struct bgp_table
*)(prn
->info
);
3272 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3273 bgp
, prd
, table
, p
, ri
);
3275 bgp_unlock_node(prn
);
3279 /* If this is an EVPN route and some attribute has changed,
3281 * route for import. If the extended community has changed, we
3283 * have done the un-import earlier and the import would result
3285 * route getting injected into appropriate L2 VNIs. If it is
3287 * some other attribute change, the import will result in
3289 * the attributes for the route in the VNI(s).
3291 if (safi
== SAFI_EVPN
&& !same_attr
)
3292 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3294 /* Process change. */
3295 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3297 bgp_process(bgp
, rn
, afi
, safi
);
3298 bgp_unlock_node(rn
);
3300 if (SAFI_UNICAST
== safi
3301 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3302 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3304 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3306 if ((SAFI_MPLS_VPN
== safi
)
3307 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3309 vpn_leak_to_vrf_update(bgp
, ri
);
3313 if (SAFI_MPLS_VPN
== safi
) {
3314 mpls_label_t label_decoded
= decode_label(label
);
3316 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3317 type
, sub_type
, &label_decoded
);
3319 if (SAFI_ENCAP
== safi
) {
3320 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3321 type
, sub_type
, NULL
);
3326 } // End of implicit withdraw
3328 /* Received Logging. */
3329 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3330 if (!peer
->rcvd_attr_printed
) {
3331 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3332 peer
->rcvd_attr_str
);
3333 peer
->rcvd_attr_printed
= 1;
3336 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3337 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3339 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3342 /* Make new BGP info. */
3343 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3345 /* Update MPLS label */
3346 if (has_valid_label
) {
3347 extra
= bgp_info_extra_get(new);
3348 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3349 extra
->num_labels
= num_labels
;
3350 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3351 bgp_set_valid_label(&extra
->label
[0]);
3354 /* Update Overlay Index */
3355 if (afi
== AFI_L2VPN
) {
3356 overlay_index_update(new->attr
,
3357 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3358 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3360 /* Nexthop reachability check. */
3361 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3362 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3363 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3364 && !CHECK_FLAG(peer
->flags
,
3365 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3366 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3371 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3372 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3373 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3375 if (BGP_DEBUG(nht
, NHT
)) {
3376 char buf1
[INET6_ADDRSTRLEN
];
3378 (const void *)&attr_new
->nexthop
,
3379 buf1
, INET6_ADDRSTRLEN
);
3380 zlog_debug("%s(%s): NH unresolved",
3381 __FUNCTION__
, buf1
);
3383 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3386 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3389 new->addpath_rx_id
= addpath_id
;
3391 /* Increment prefix */
3392 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3394 /* Register new BGP information. */
3395 bgp_info_add(rn
, new);
3397 /* route_node_get lock */
3398 bgp_unlock_node(rn
);
3401 if (safi
== SAFI_MPLS_VPN
) {
3402 struct bgp_node
*prn
= NULL
;
3403 struct bgp_table
*table
= NULL
;
3405 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3407 table
= (struct bgp_table
*)(prn
->info
);
3409 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3410 bgp
, prd
, table
, p
, new);
3412 bgp_unlock_node(prn
);
3416 /* If maximum prefix count is configured and current prefix
3418 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3421 /* If this is an EVPN route, process for import. */
3422 if (safi
== SAFI_EVPN
)
3423 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3425 /* Process change. */
3426 bgp_process(bgp
, rn
, afi
, safi
);
3428 if (SAFI_UNICAST
== safi
3429 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3430 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3431 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3433 if ((SAFI_MPLS_VPN
== safi
)
3434 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3436 vpn_leak_to_vrf_update(bgp
, new);
3439 if (SAFI_MPLS_VPN
== safi
) {
3440 mpls_label_t label_decoded
= decode_label(label
);
3442 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3443 sub_type
, &label_decoded
);
3445 if (SAFI_ENCAP
== safi
) {
3446 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3453 /* This BGP update is filtered. Log the reason then update BGP
3456 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3457 if (!peer
->rcvd_attr_printed
) {
3458 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3459 peer
->rcvd_attr_str
);
3460 peer
->rcvd_attr_printed
= 1;
3463 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3464 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3466 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3467 peer
->host
, pfx_buf
, reason
);
3471 /* If this is an EVPN route, un-import it as it is now filtered.
3473 if (safi
== SAFI_EVPN
)
3474 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3476 if (SAFI_UNICAST
== safi
3477 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3478 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3480 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3482 if ((SAFI_MPLS_VPN
== safi
)
3483 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3485 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3488 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3491 bgp_unlock_node(rn
);
3495 * Filtered update is treated as an implicit withdrawal (see
3497 * a few lines above)
3499 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3500 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3508 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3509 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3510 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3511 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3514 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3515 struct bgp_node
*rn
;
3516 struct bgp_info
*ri
;
3519 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3520 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3528 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3530 /* If peer is soft reconfiguration enabled. Record input packet for
3531 * further calculation.
3533 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3534 * routes that are filtered. This tanks out Quagga RS pretty badly due
3536 * the iteration over all RS clients.
3537 * Since we need to remove the entry from adj_in anyway, do that first
3539 * if there was no entry, we don't need to do anything more.
3541 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3542 && peer
!= bgp
->peer_self
)
3543 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3544 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3545 bgp_debug_rdpfxpath2str(
3546 afi
, safi
, prd
, p
, label
, num_labels
,
3547 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3550 "%s withdrawing route %s not in adj-in",
3551 peer
->host
, pfx_buf
);
3553 bgp_unlock_node(rn
);
3557 /* Lookup withdrawn route. */
3558 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3559 if (ri
->peer
== peer
&& ri
->type
== type
3560 && ri
->sub_type
== sub_type
3561 && ri
->addpath_rx_id
== addpath_id
)
3565 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3566 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3567 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3569 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3573 /* Withdraw specified route from routing table. */
3574 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3575 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3576 if (SAFI_UNICAST
== safi
3577 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3578 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3579 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3581 if ((SAFI_MPLS_VPN
== safi
)
3582 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3584 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3586 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3587 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3588 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3590 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3593 /* Unlock bgp_node_get() lock. */
3594 bgp_unlock_node(rn
);
3599 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3602 struct update_subgroup
*subgrp
;
3603 subgrp
= peer_subgroup(peer
, afi
, safi
);
3604 subgroup_default_originate(subgrp
, withdraw
);
3609 * bgp_stop_announce_route_timer
3611 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3613 if (!paf
->t_announce_route
)
3616 THREAD_TIMER_OFF(paf
->t_announce_route
);
3620 * bgp_announce_route_timer_expired
3622 * Callback that is invoked when the route announcement timer for a
3625 static int bgp_announce_route_timer_expired(struct thread
*t
)
3627 struct peer_af
*paf
;
3630 paf
= THREAD_ARG(t
);
3633 if (peer
->status
!= Established
)
3636 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3639 peer_af_announce_route(paf
, 1);
3644 * bgp_announce_route
3646 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3648 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3650 struct peer_af
*paf
;
3651 struct update_subgroup
*subgrp
;
3653 paf
= peer_af_find(peer
, afi
, safi
);
3656 subgrp
= PAF_SUBGRP(paf
);
3659 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3660 * or a refresh has already been triggered.
3662 if (!subgrp
|| paf
->t_announce_route
)
3666 * Start a timer to stagger/delay the announce. This serves
3667 * two purposes - announcement can potentially be combined for
3668 * multiple peers and the announcement doesn't happen in the
3671 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3672 (subgrp
->peer_count
== 1)
3673 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3674 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3675 &paf
->t_announce_route
);
3679 * Announce routes from all AF tables to a peer.
3681 * This should ONLY be called when there is a need to refresh the
3682 * routes to the peer based on a policy change for this peer alone
3683 * or a route refresh request received from the peer.
3684 * The operation will result in splitting the peer from its existing
3685 * subgroups and putting it in new subgroups.
3687 void bgp_announce_route_all(struct peer
*peer
)
3692 FOREACH_AFI_SAFI (afi
, safi
)
3693 bgp_announce_route(peer
, afi
, safi
);
3696 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3697 struct bgp_table
*table
,
3698 struct prefix_rd
*prd
)
3701 struct bgp_node
*rn
;
3702 struct bgp_adj_in
*ain
;
3705 table
= peer
->bgp
->rib
[afi
][safi
];
3707 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3708 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3709 if (ain
->peer
!= peer
)
3712 struct bgp_info
*ri
= rn
->info
;
3713 uint32_t num_labels
= 0;
3714 mpls_label_t
*label_pnt
= NULL
;
3716 if (ri
&& ri
->extra
)
3717 num_labels
= ri
->extra
->num_labels
;
3719 label_pnt
= &ri
->extra
->label
[0];
3721 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3722 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3723 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3724 num_labels
, 1, NULL
);
3727 bgp_unlock_node(rn
);
3733 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3735 struct bgp_node
*rn
;
3736 struct bgp_table
*table
;
3738 if (peer
->status
!= Established
)
3741 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3742 && (safi
!= SAFI_EVPN
))
3743 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3745 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3746 rn
= bgp_route_next(rn
))
3747 if ((table
= rn
->info
) != NULL
) {
3748 struct prefix_rd prd
;
3749 prd
.family
= AF_UNSPEC
;
3751 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3753 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3759 struct bgp_clear_node_queue
{
3760 struct bgp_node
*rn
;
3763 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3765 struct bgp_clear_node_queue
*cnq
= data
;
3766 struct bgp_node
*rn
= cnq
->rn
;
3767 struct peer
*peer
= wq
->spec
.data
;
3768 struct bgp_info
*ri
;
3770 afi_t afi
= bgp_node_table(rn
)->afi
;
3771 safi_t safi
= bgp_node_table(rn
)->safi
;
3776 /* It is possible that we have multiple paths for a prefix from a peer
3777 * if that peer is using AddPath.
3779 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3780 if (ri
->peer
!= peer
)
3783 /* graceful restart STALE flag set. */
3784 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3785 && peer
->nsf
[afi
][safi
]
3786 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3787 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3788 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3790 /* If this is an EVPN route, process for
3792 if (safi
== SAFI_EVPN
)
3793 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3795 /* Handle withdraw for VRF route-leaking and L3VPN */
3796 if (SAFI_UNICAST
== safi
3797 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3798 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3799 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3802 if (SAFI_MPLS_VPN
== safi
&&
3803 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3804 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3807 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3813 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3815 struct bgp_clear_node_queue
*cnq
= data
;
3816 struct bgp_node
*rn
= cnq
->rn
;
3817 struct bgp_table
*table
= bgp_node_table(rn
);
3819 bgp_unlock_node(rn
);
3820 bgp_table_unlock(table
);
3821 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3824 static void bgp_clear_node_complete(struct work_queue
*wq
)
3826 struct peer
*peer
= wq
->spec
.data
;
3828 /* Tickle FSM to start moving again */
3829 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3831 peer_unlock(peer
); /* bgp_clear_route */
3834 static void bgp_clear_node_queue_init(struct peer
*peer
)
3836 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3838 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3839 #undef CLEAR_QUEUE_NAME_LEN
3841 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3843 zlog_err("%s: Failed to allocate work queue", __func__
);
3846 peer
->clear_node_queue
->spec
.hold
= 10;
3847 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3848 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3849 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3850 peer
->clear_node_queue
->spec
.max_retries
= 0;
3852 /* we only 'lock' this peer reference when the queue is actually active
3854 peer
->clear_node_queue
->spec
.data
= peer
;
3857 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3858 struct bgp_table
*table
)
3860 struct bgp_node
*rn
;
3861 int force
= bm
->process_main_queue
? 0 : 1;
3864 table
= peer
->bgp
->rib
[afi
][safi
];
3866 /* If still no table => afi/safi isn't configured at all or smth. */
3870 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3871 struct bgp_info
*ri
, *next
;
3872 struct bgp_adj_in
*ain
;
3873 struct bgp_adj_in
*ain_next
;
3875 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3876 * queued for every clearing peer, regardless of whether it is
3877 * relevant to the peer at hand.
3879 * Overview: There are 3 different indices which need to be
3880 * scrubbed, potentially, when a peer is removed:
3882 * 1 peer's routes visible via the RIB (ie accepted routes)
3883 * 2 peer's routes visible by the (optional) peer's adj-in index
3884 * 3 other routes visible by the peer's adj-out index
3886 * 3 there is no hurry in scrubbing, once the struct peer is
3887 * removed from bgp->peer, we could just GC such deleted peer's
3888 * adj-outs at our leisure.
3890 * 1 and 2 must be 'scrubbed' in some way, at least made
3891 * invisible via RIB index before peer session is allowed to be
3892 * brought back up. So one needs to know when such a 'search' is
3897 * - there'd be a single global queue or a single RIB walker
3898 * - rather than tracking which route_nodes still need to be
3899 * examined on a peer basis, we'd track which peers still
3902 * Given that our per-peer prefix-counts now should be reliable,
3903 * this may actually be achievable. It doesn't seem to be a huge
3904 * problem at this time,
3906 * It is possible that we have multiple paths for a prefix from
3908 * if that peer is using AddPath.
3912 ain_next
= ain
->next
;
3914 if (ain
->peer
== peer
) {
3915 bgp_adj_in_remove(rn
, ain
);
3916 bgp_unlock_node(rn
);
3922 for (ri
= rn
->info
; ri
; ri
= next
) {
3924 if (ri
->peer
!= peer
)
3928 bgp_info_reap(rn
, ri
);
3930 struct bgp_clear_node_queue
*cnq
;
3932 /* both unlocked in bgp_clear_node_queue_del */
3933 bgp_table_lock(bgp_node_table(rn
));
3936 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3937 sizeof(struct bgp_clear_node_queue
));
3939 work_queue_add(peer
->clear_node_queue
, cnq
);
3947 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3949 struct bgp_node
*rn
;
3950 struct bgp_table
*table
;
3952 if (peer
->clear_node_queue
== NULL
)
3953 bgp_clear_node_queue_init(peer
);
3955 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3956 * Idle until it receives a Clearing_Completed event. This protects
3957 * against peers which flap faster than we can we clear, which could
3960 * a) race with routes from the new session being installed before
3961 * clear_route_node visits the node (to delete the route of that
3963 * b) resource exhaustion, clear_route_node likely leads to an entry
3964 * on the process_main queue. Fast-flapping could cause that queue
3968 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3969 * the unlock will happen upon work-queue completion; other wise, the
3970 * unlock happens at the end of this function.
3972 if (!peer
->clear_node_queue
->thread
)
3975 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3976 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3978 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3979 rn
= bgp_route_next(rn
))
3980 if ((table
= rn
->info
) != NULL
)
3981 bgp_clear_route_table(peer
, afi
, safi
, table
);
3983 /* unlock if no nodes got added to the clear-node-queue. */
3984 if (!peer
->clear_node_queue
->thread
)
3988 void bgp_clear_route_all(struct peer
*peer
)
3993 FOREACH_AFI_SAFI (afi
, safi
)
3994 bgp_clear_route(peer
, afi
, safi
);
3997 rfapiProcessPeerDown(peer
);
4001 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4003 struct bgp_table
*table
;
4004 struct bgp_node
*rn
;
4005 struct bgp_adj_in
*ain
;
4006 struct bgp_adj_in
*ain_next
;
4008 table
= peer
->bgp
->rib
[afi
][safi
];
4010 /* It is possible that we have multiple paths for a prefix from a peer
4011 * if that peer is using AddPath.
4013 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4017 ain_next
= ain
->next
;
4019 if (ain
->peer
== peer
) {
4020 bgp_adj_in_remove(rn
, ain
);
4021 bgp_unlock_node(rn
);
4029 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4031 struct bgp_node
*rn
;
4032 struct bgp_info
*ri
;
4033 struct bgp_table
*table
;
4035 if (safi
== SAFI_MPLS_VPN
) {
4036 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4037 rn
= bgp_route_next(rn
)) {
4038 struct bgp_node
*rm
;
4039 struct bgp_info
*ri
;
4041 /* look for neighbor in tables */
4042 if ((table
= rn
->info
) == NULL
)
4045 for (rm
= bgp_table_top(table
); rm
;
4046 rm
= bgp_route_next(rm
))
4047 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4048 if (ri
->peer
!= peer
)
4050 if (!CHECK_FLAG(ri
->flags
,
4054 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4059 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4060 rn
= bgp_route_next(rn
))
4061 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4062 if (ri
->peer
!= peer
)
4064 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4066 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4072 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4075 struct bgp_node
*rn
;
4076 struct bgp_info
*ri
;
4077 struct bgp_info
*next
;
4079 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4080 for (ri
= rn
->info
; ri
; ri
= next
) {
4082 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4083 && ri
->type
== ZEBRA_ROUTE_BGP
4084 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4085 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4086 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4088 if (bgp_fibupd_safi(safi
))
4089 bgp_zebra_withdraw(&rn
->p
, ri
,
4091 bgp_info_reap(rn
, ri
);
4096 /* Delete all kernel routes. */
4097 void bgp_cleanup_routes(struct bgp
*bgp
)
4100 struct bgp_node
*rn
;
4102 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4103 if (afi
== AFI_L2VPN
)
4105 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4108 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4110 if (afi
!= AFI_L2VPN
) {
4112 safi
= SAFI_MPLS_VPN
;
4113 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4114 rn
= bgp_route_next(rn
)) {
4116 bgp_cleanup_table(bgp
,
4117 (struct bgp_table
*)(rn
->info
),
4119 bgp_table_finish((struct bgp_table
**)&(
4122 bgp_unlock_node(rn
);
4126 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4127 rn
= bgp_route_next(rn
)) {
4129 bgp_cleanup_table(bgp
,
4130 (struct bgp_table
*)(rn
->info
),
4132 bgp_table_finish((struct bgp_table
**)&(
4135 bgp_unlock_node(rn
);
4140 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4141 rn
= bgp_route_next(rn
)) {
4143 bgp_cleanup_table(bgp
,
4144 (struct bgp_table
*)(rn
->info
),
4146 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4148 bgp_unlock_node(rn
);
4153 void bgp_reset(void)
4156 bgp_zclient_reset();
4157 access_list_reset();
4158 prefix_list_reset();
4161 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4163 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4164 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4165 PEER_CAP_ADDPATH_AF_TX_RCV
));
4168 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4170 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4171 struct bgp_nlri
*packet
)
4180 int addpath_encoded
;
4181 uint32_t addpath_id
;
4184 lim
= pnt
+ packet
->length
;
4186 safi
= packet
->safi
;
4188 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4190 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4191 syntactic validity. If the field is syntactically incorrect,
4192 then the Error Subcode is set to Invalid Network Field. */
4193 for (; pnt
< lim
; pnt
+= psize
) {
4194 /* Clear prefix structure. */
4195 memset(&p
, 0, sizeof(struct prefix
));
4197 if (addpath_encoded
) {
4199 /* When packet overflow occurs return immediately. */
4200 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4203 addpath_id
= ntohl(*((uint32_t *)pnt
));
4204 pnt
+= BGP_ADDPATH_ID_LEN
;
4207 /* Fetch prefix length. */
4208 p
.prefixlen
= *pnt
++;
4209 /* afi/safi validity already verified by caller,
4210 * bgp_update_receive */
4211 p
.family
= afi2family(afi
);
4213 /* Prefix length check. */
4214 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4216 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
4217 peer
->host
, p
.prefixlen
, packet
->afi
);
4221 /* Packet size overflow check. */
4222 psize
= PSIZE(p
.prefixlen
);
4224 /* When packet overflow occur return immediately. */
4225 if (pnt
+ psize
> lim
) {
4227 "%s [Error] Update packet error (prefix length %d overflows packet)",
4228 peer
->host
, p
.prefixlen
);
4232 /* Defensive coding, double-check the psize fits in a struct
4234 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4236 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4237 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4241 /* Fetch prefix from NLRI packet. */
4242 memcpy(p
.u
.val
, pnt
, psize
);
4244 /* Check address. */
4245 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4246 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4247 /* From RFC4271 Section 6.3:
4249 * If a prefix in the NLRI field is semantically
4251 * (e.g., an unexpected multicast IP address),
4253 * be logged locally, and the prefix SHOULD be
4257 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4258 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4263 /* Check address. */
4264 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4265 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4269 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4271 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4276 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4280 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4282 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4289 /* Normal process. */
4291 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4292 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4293 NULL
, NULL
, 0, 0, NULL
);
4295 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4296 safi
, ZEBRA_ROUTE_BGP
,
4297 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4300 /* Address family configuration mismatch or maximum-prefix count
4306 /* Packet length consistency check. */
4309 "%s [Error] Update packet error (prefix length mismatch with total length)",
4317 static struct bgp_static
*bgp_static_new(void)
4319 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4322 static void bgp_static_free(struct bgp_static
*bgp_static
)
4324 if (bgp_static
->rmap
.name
)
4325 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4326 if (bgp_static
->eth_s_id
)
4327 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4328 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4331 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4332 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4334 struct bgp_node
*rn
;
4335 struct bgp_info
*ri
;
4336 struct bgp_info
*new;
4337 struct bgp_info info
;
4339 struct attr
*attr_new
;
4342 int vnc_implicit_withdraw
= 0;
4349 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4351 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4353 attr
.nexthop
= bgp_static
->igpnexthop
;
4354 attr
.med
= bgp_static
->igpmetric
;
4355 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4357 if (bgp_static
->atomic
)
4358 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4360 /* Store label index, if required. */
4361 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4362 attr
.label_index
= bgp_static
->label_index
;
4363 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4366 /* Apply route-map. */
4367 if (bgp_static
->rmap
.name
) {
4368 struct attr attr_tmp
= attr
;
4370 memset(&info
, 0, sizeof(struct bgp_info
));
4371 info
.peer
= bgp
->peer_self
;
4372 info
.attr
= &attr_tmp
;
4374 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4376 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4378 bgp
->peer_self
->rmap_type
= 0;
4380 if (ret
== RMAP_DENYMATCH
) {
4381 /* Free uninterned attribute. */
4382 bgp_attr_flush(&attr_tmp
);
4384 /* Unintern original. */
4385 aspath_unintern(&attr
.aspath
);
4386 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4390 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4391 bgp_attr_add_gshut_community(&attr_tmp
);
4393 attr_new
= bgp_attr_intern(&attr_tmp
);
4396 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4397 bgp_attr_add_gshut_community(&attr
);
4399 attr_new
= bgp_attr_intern(&attr
);
4402 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4403 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4404 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4408 if (attrhash_cmp(ri
->attr
, attr_new
)
4409 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4410 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4411 bgp_unlock_node(rn
);
4412 bgp_attr_unintern(&attr_new
);
4413 aspath_unintern(&attr
.aspath
);
4416 /* The attribute is changed. */
4417 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4419 /* Rewrite BGP route information. */
4420 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4421 bgp_info_restore(rn
, ri
);
4423 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4425 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4426 && (safi
== SAFI_UNICAST
)) {
4427 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4429 * Implicit withdraw case.
4430 * We have to do this before ri is
4433 ++vnc_implicit_withdraw
;
4434 vnc_import_bgp_del_route(bgp
, p
, ri
);
4435 vnc_import_bgp_exterior_del_route(
4440 bgp_attr_unintern(&ri
->attr
);
4441 ri
->attr
= attr_new
;
4442 ri
->uptime
= bgp_clock();
4444 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4445 && (safi
== SAFI_UNICAST
)) {
4446 if (vnc_implicit_withdraw
) {
4447 vnc_import_bgp_add_route(bgp
, p
, ri
);
4448 vnc_import_bgp_exterior_add_route(
4454 /* Nexthop reachability check. */
4455 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4456 && (safi
== SAFI_UNICAST
4457 || safi
== SAFI_LABELED_UNICAST
)) {
4459 struct bgp
*bgp_nexthop
= bgp
;
4461 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4462 bgp_nexthop
= ri
->extra
->bgp_orig
;
4464 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4466 bgp_info_set_flag(rn
, ri
,
4469 if (BGP_DEBUG(nht
, NHT
)) {
4470 char buf1
[INET6_ADDRSTRLEN
];
4471 inet_ntop(p
->family
,
4475 "%s(%s): Route not in table, not advertising",
4476 __FUNCTION__
, buf1
);
4478 bgp_info_unset_flag(rn
, ri
,
4482 /* Delete the NHT structure if any, if we're
4484 * enabling/disabling import check. We
4485 * deregister the route
4486 * from NHT to avoid overloading NHT and the
4487 * process interaction
4489 bgp_unlink_nexthop(ri
);
4490 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4492 /* Process change. */
4493 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4494 bgp_process(bgp
, rn
, afi
, safi
);
4496 if (SAFI_UNICAST
== safi
4497 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4499 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4500 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4504 bgp_unlock_node(rn
);
4505 aspath_unintern(&attr
.aspath
);
4510 /* Make new BGP info. */
4511 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4513 /* Nexthop reachability check. */
4514 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4515 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4516 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4517 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4519 if (BGP_DEBUG(nht
, NHT
)) {
4520 char buf1
[INET6_ADDRSTRLEN
];
4521 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4524 "%s(%s): Route not in table, not advertising",
4525 __FUNCTION__
, buf1
);
4527 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4530 /* Delete the NHT structure if any, if we're toggling between
4531 * enabling/disabling import check. We deregister the route
4532 * from NHT to avoid overloading NHT and the process interaction
4534 bgp_unlink_nexthop(new);
4536 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4539 /* Aggregate address increment. */
4540 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4542 /* Register new BGP information. */
4543 bgp_info_add(rn
, new);
4545 /* route_node_get lock */
4546 bgp_unlock_node(rn
);
4548 /* Process change. */
4549 bgp_process(bgp
, rn
, afi
, safi
);
4551 if (SAFI_UNICAST
== safi
4552 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4553 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4554 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4557 /* Unintern original. */
4558 aspath_unintern(&attr
.aspath
);
4561 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4564 struct bgp_node
*rn
;
4565 struct bgp_info
*ri
;
4567 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4569 /* Check selected route and self inserted route. */
4570 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4571 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4572 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4575 /* Withdraw static BGP route from routing table. */
4577 if (SAFI_UNICAST
== safi
4578 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4579 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4580 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4582 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4583 bgp_unlink_nexthop(ri
);
4584 bgp_info_delete(rn
, ri
);
4585 bgp_process(bgp
, rn
, afi
, safi
);
4588 /* Unlock bgp_node_lookup. */
4589 bgp_unlock_node(rn
);
4593 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4595 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4596 afi_t afi
, safi_t safi
,
4597 struct prefix_rd
*prd
)
4599 struct bgp_node
*rn
;
4600 struct bgp_info
*ri
;
4602 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4604 /* Check selected route and self inserted route. */
4605 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4606 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4607 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4610 /* Withdraw static BGP route from routing table. */
4613 rfapiProcessWithdraw(
4614 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4615 1); /* Kill, since it is an administrative change */
4617 if (SAFI_MPLS_VPN
== safi
4618 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4619 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4621 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4622 bgp_info_delete(rn
, ri
);
4623 bgp_process(bgp
, rn
, afi
, safi
);
4626 /* Unlock bgp_node_lookup. */
4627 bgp_unlock_node(rn
);
4630 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4631 struct bgp_static
*bgp_static
, afi_t afi
,
4634 struct bgp_node
*rn
;
4635 struct bgp_info
*new;
4636 struct attr
*attr_new
;
4637 struct attr attr
= {0};
4638 struct bgp_info
*ri
;
4640 mpls_label_t label
= 0;
4642 uint32_t num_labels
= 0;
4647 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4649 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4652 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4654 attr
.nexthop
= bgp_static
->igpnexthop
;
4655 attr
.med
= bgp_static
->igpmetric
;
4656 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4658 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4659 || (safi
== SAFI_ENCAP
)) {
4660 if (afi
== AFI_IP
) {
4661 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4662 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4665 if (afi
== AFI_L2VPN
) {
4666 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4668 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4669 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4670 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4671 sizeof(struct in6_addr
));
4672 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4673 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4674 struct bgp_encap_type_vxlan bet
;
4675 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4676 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4677 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4679 if (bgp_static
->router_mac
) {
4680 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4683 /* Apply route-map. */
4684 if (bgp_static
->rmap
.name
) {
4685 struct attr attr_tmp
= attr
;
4686 struct bgp_info info
;
4689 info
.peer
= bgp
->peer_self
;
4690 info
.attr
= &attr_tmp
;
4692 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4694 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4696 bgp
->peer_self
->rmap_type
= 0;
4698 if (ret
== RMAP_DENYMATCH
) {
4699 /* Free uninterned attribute. */
4700 bgp_attr_flush(&attr_tmp
);
4702 /* Unintern original. */
4703 aspath_unintern(&attr
.aspath
);
4704 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4709 attr_new
= bgp_attr_intern(&attr_tmp
);
4711 attr_new
= bgp_attr_intern(&attr
);
4714 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4715 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4716 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4721 memset(&add
, 0, sizeof(union gw_addr
));
4722 if (attrhash_cmp(ri
->attr
, attr_new
)
4723 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4724 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4725 bgp_unlock_node(rn
);
4726 bgp_attr_unintern(&attr_new
);
4727 aspath_unintern(&attr
.aspath
);
4730 /* The attribute is changed. */
4731 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4733 /* Rewrite BGP route information. */
4734 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4735 bgp_info_restore(rn
, ri
);
4737 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4738 bgp_attr_unintern(&ri
->attr
);
4739 ri
->attr
= attr_new
;
4740 ri
->uptime
= bgp_clock();
4743 label
= decode_label(&ri
->extra
->label
[0]);
4746 /* Process change. */
4747 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4748 bgp_process(bgp
, rn
, afi
, safi
);
4750 if (SAFI_MPLS_VPN
== safi
4751 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4752 vpn_leak_to_vrf_update(bgp
, ri
);
4755 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4756 ri
->attr
, afi
, safi
, ri
->type
,
4757 ri
->sub_type
, &label
);
4759 bgp_unlock_node(rn
);
4760 aspath_unintern(&attr
.aspath
);
4766 /* Make new BGP info. */
4767 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4769 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4770 new->extra
= bgp_info_extra_new();
4772 new->extra
->label
[0] = bgp_static
->label
;
4773 new->extra
->num_labels
= num_labels
;
4776 label
= decode_label(&bgp_static
->label
);
4779 /* Aggregate address increment. */
4780 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4782 /* Register new BGP information. */
4783 bgp_info_add(rn
, new);
4784 /* route_node_get lock */
4785 bgp_unlock_node(rn
);
4787 /* Process change. */
4788 bgp_process(bgp
, rn
, afi
, safi
);
4790 if (SAFI_MPLS_VPN
== safi
4791 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4792 vpn_leak_to_vrf_update(bgp
, new);
4795 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4796 safi
, new->type
, new->sub_type
, &label
);
4799 /* Unintern original. */
4800 aspath_unintern(&attr
.aspath
);
4803 /* Configure static BGP network. When user don't run zebra, static
4804 route should be installed as valid. */
4805 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4806 const char *ip_str
, afi_t afi
, safi_t safi
,
4807 const char *rmap
, int backdoor
, uint32_t label_index
)
4809 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4812 struct bgp_static
*bgp_static
;
4813 struct bgp_node
*rn
;
4814 uint8_t need_update
= 0;
4816 /* Convert IP prefix string to struct prefix. */
4817 ret
= str2prefix(ip_str
, &p
);
4819 vty_out(vty
, "%% Malformed prefix\n");
4820 return CMD_WARNING_CONFIG_FAILED
;
4822 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4823 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4824 return CMD_WARNING_CONFIG_FAILED
;
4831 /* Set BGP static route configuration. */
4832 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4835 vty_out(vty
, "%% Can't find static route specified\n");
4836 return CMD_WARNING_CONFIG_FAILED
;
4839 bgp_static
= rn
->info
;
4841 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4842 && (label_index
!= bgp_static
->label_index
)) {
4844 "%% label-index doesn't match static route\n");
4845 return CMD_WARNING_CONFIG_FAILED
;
4848 if ((rmap
&& bgp_static
->rmap
.name
)
4849 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4851 "%% route-map name doesn't match static route\n");
4852 return CMD_WARNING_CONFIG_FAILED
;
4855 /* Update BGP RIB. */
4856 if (!bgp_static
->backdoor
)
4857 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4859 /* Clear configuration. */
4860 bgp_static_free(bgp_static
);
4862 bgp_unlock_node(rn
);
4863 bgp_unlock_node(rn
);
4866 /* Set BGP static route configuration. */
4867 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4870 /* Configuration change. */
4871 bgp_static
= rn
->info
;
4873 /* Label index cannot be changed. */
4874 if (bgp_static
->label_index
!= label_index
) {
4875 vty_out(vty
, "%% cannot change label-index\n");
4876 return CMD_WARNING_CONFIG_FAILED
;
4879 /* Check previous routes are installed into BGP. */
4880 if (bgp_static
->valid
4881 && bgp_static
->backdoor
!= backdoor
)
4884 bgp_static
->backdoor
= backdoor
;
4887 if (bgp_static
->rmap
.name
)
4888 XFREE(MTYPE_ROUTE_MAP_NAME
,
4889 bgp_static
->rmap
.name
);
4890 bgp_static
->rmap
.name
=
4891 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4892 bgp_static
->rmap
.map
=
4893 route_map_lookup_by_name(rmap
);
4895 if (bgp_static
->rmap
.name
)
4896 XFREE(MTYPE_ROUTE_MAP_NAME
,
4897 bgp_static
->rmap
.name
);
4898 bgp_static
->rmap
.name
= NULL
;
4899 bgp_static
->rmap
.map
= NULL
;
4900 bgp_static
->valid
= 0;
4902 bgp_unlock_node(rn
);
4904 /* New configuration. */
4905 bgp_static
= bgp_static_new();
4906 bgp_static
->backdoor
= backdoor
;
4907 bgp_static
->valid
= 0;
4908 bgp_static
->igpmetric
= 0;
4909 bgp_static
->igpnexthop
.s_addr
= 0;
4910 bgp_static
->label_index
= label_index
;
4913 if (bgp_static
->rmap
.name
)
4914 XFREE(MTYPE_ROUTE_MAP_NAME
,
4915 bgp_static
->rmap
.name
);
4916 bgp_static
->rmap
.name
=
4917 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4918 bgp_static
->rmap
.map
=
4919 route_map_lookup_by_name(rmap
);
4921 rn
->info
= bgp_static
;
4924 bgp_static
->valid
= 1;
4926 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4928 if (!bgp_static
->backdoor
)
4929 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4935 void bgp_static_add(struct bgp
*bgp
)
4939 struct bgp_node
*rn
;
4940 struct bgp_node
*rm
;
4941 struct bgp_table
*table
;
4942 struct bgp_static
*bgp_static
;
4944 FOREACH_AFI_SAFI (afi
, safi
)
4945 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4946 rn
= bgp_route_next(rn
)) {
4947 if (rn
->info
== NULL
)
4950 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4951 || (safi
== SAFI_EVPN
)) {
4954 for (rm
= bgp_table_top(table
); rm
;
4955 rm
= bgp_route_next(rm
)) {
4956 bgp_static
= rm
->info
;
4957 bgp_static_update_safi(bgp
, &rm
->p
,
4962 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4968 /* Called from bgp_delete(). Delete all static routes from the BGP
4970 void bgp_static_delete(struct bgp
*bgp
)
4974 struct bgp_node
*rn
;
4975 struct bgp_node
*rm
;
4976 struct bgp_table
*table
;
4977 struct bgp_static
*bgp_static
;
4979 FOREACH_AFI_SAFI (afi
, safi
)
4980 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4981 rn
= bgp_route_next(rn
)) {
4982 if (rn
->info
== NULL
)
4985 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4986 || (safi
== SAFI_EVPN
)) {
4989 for (rm
= bgp_table_top(table
); rm
;
4990 rm
= bgp_route_next(rm
)) {
4991 bgp_static
= rm
->info
;
4992 bgp_static_withdraw_safi(
4993 bgp
, &rm
->p
, AFI_IP
, safi
,
4994 (struct prefix_rd
*)&rn
->p
);
4995 bgp_static_free(bgp_static
);
4997 bgp_unlock_node(rn
);
5000 bgp_static
= rn
->info
;
5001 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5002 bgp_static_free(bgp_static
);
5004 bgp_unlock_node(rn
);
5009 void bgp_static_redo_import_check(struct bgp
*bgp
)
5013 struct bgp_node
*rn
;
5014 struct bgp_node
*rm
;
5015 struct bgp_table
*table
;
5016 struct bgp_static
*bgp_static
;
5018 /* Use this flag to force reprocessing of the route */
5019 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5020 FOREACH_AFI_SAFI (afi
, safi
) {
5021 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5022 rn
= bgp_route_next(rn
)) {
5023 if (rn
->info
== NULL
)
5026 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5027 || (safi
== SAFI_EVPN
)) {
5030 for (rm
= bgp_table_top(table
); rm
;
5031 rm
= bgp_route_next(rm
)) {
5032 bgp_static
= rm
->info
;
5033 bgp_static_update_safi(bgp
, &rm
->p
,
5038 bgp_static
= rn
->info
;
5039 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5044 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5047 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5050 struct bgp_table
*table
;
5051 struct bgp_node
*rn
;
5052 struct bgp_info
*ri
;
5054 table
= bgp
->rib
[afi
][safi
];
5055 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5056 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5057 if (ri
->peer
== bgp
->peer_self
5058 && ((ri
->type
== ZEBRA_ROUTE_BGP
5059 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5060 || (ri
->type
!= ZEBRA_ROUTE_BGP
5062 == BGP_ROUTE_REDISTRIBUTE
))) {
5063 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5065 bgp_unlink_nexthop(ri
);
5066 bgp_info_delete(rn
, ri
);
5067 bgp_process(bgp
, rn
, afi
, safi
);
5074 * Purge all networks and redistributed routes from routing table.
5075 * Invoked upon the instance going down.
5077 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5082 FOREACH_AFI_SAFI (afi
, safi
)
5083 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5088 * Currently this is used to set static routes for VPN and ENCAP.
5089 * I think it can probably be factored with bgp_static_set.
5091 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5092 const char *ip_str
, const char *rd_str
,
5093 const char *label_str
, const char *rmap_str
,
5094 int evpn_type
, const char *esi
, const char *gwip
,
5095 const char *ethtag
, const char *routermac
)
5097 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5100 struct prefix_rd prd
;
5101 struct bgp_node
*prn
;
5102 struct bgp_node
*rn
;
5103 struct bgp_table
*table
;
5104 struct bgp_static
*bgp_static
;
5105 mpls_label_t label
= MPLS_INVALID_LABEL
;
5106 struct prefix gw_ip
;
5108 /* validate ip prefix */
5109 ret
= str2prefix(ip_str
, &p
);
5111 vty_out(vty
, "%% Malformed prefix\n");
5112 return CMD_WARNING_CONFIG_FAILED
;
5115 if ((afi
== AFI_L2VPN
)
5116 && (bgp_build_evpn_prefix(evpn_type
,
5117 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5118 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5119 return CMD_WARNING_CONFIG_FAILED
;
5122 ret
= str2prefix_rd(rd_str
, &prd
);
5124 vty_out(vty
, "%% Malformed rd\n");
5125 return CMD_WARNING_CONFIG_FAILED
;
5129 unsigned long label_val
;
5130 label_val
= strtoul(label_str
, NULL
, 10);
5131 encode_label(label_val
, &label
);
5134 if (safi
== SAFI_EVPN
) {
5135 if (esi
&& str2esi(esi
, NULL
) == 0) {
5136 vty_out(vty
, "%% Malformed ESI\n");
5137 return CMD_WARNING_CONFIG_FAILED
;
5139 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5140 vty_out(vty
, "%% Malformed Router MAC\n");
5141 return CMD_WARNING_CONFIG_FAILED
;
5144 memset(&gw_ip
, 0, sizeof(struct prefix
));
5145 ret
= str2prefix(gwip
, &gw_ip
);
5147 vty_out(vty
, "%% Malformed GatewayIp\n");
5148 return CMD_WARNING_CONFIG_FAILED
;
5150 if ((gw_ip
.family
== AF_INET
5151 && is_evpn_prefix_ipaddr_v6(
5152 (struct prefix_evpn
*)&p
))
5153 || (gw_ip
.family
== AF_INET6
5154 && is_evpn_prefix_ipaddr_v4(
5155 (struct prefix_evpn
*)&p
))) {
5157 "%% GatewayIp family differs with IP prefix\n");
5158 return CMD_WARNING_CONFIG_FAILED
;
5162 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5163 if (prn
->info
== NULL
)
5164 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5166 bgp_unlock_node(prn
);
5169 rn
= bgp_node_get(table
, &p
);
5172 vty_out(vty
, "%% Same network configuration exists\n");
5173 bgp_unlock_node(rn
);
5175 /* New configuration. */
5176 bgp_static
= bgp_static_new();
5177 bgp_static
->backdoor
= 0;
5178 bgp_static
->valid
= 0;
5179 bgp_static
->igpmetric
= 0;
5180 bgp_static
->igpnexthop
.s_addr
= 0;
5181 bgp_static
->label
= label
;
5182 bgp_static
->prd
= prd
;
5185 if (bgp_static
->rmap
.name
)
5186 XFREE(MTYPE_ROUTE_MAP_NAME
,
5187 bgp_static
->rmap
.name
);
5188 bgp_static
->rmap
.name
=
5189 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5190 bgp_static
->rmap
.map
=
5191 route_map_lookup_by_name(rmap_str
);
5194 if (safi
== SAFI_EVPN
) {
5196 bgp_static
->eth_s_id
=
5198 sizeof(struct eth_segment_id
));
5199 str2esi(esi
, bgp_static
->eth_s_id
);
5202 bgp_static
->router_mac
=
5203 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5204 (void)prefix_str2mac(routermac
,
5205 bgp_static
->router_mac
);
5208 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5210 rn
->info
= bgp_static
;
5212 bgp_static
->valid
= 1;
5213 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5219 /* Configure static BGP network. */
5220 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5221 const char *ip_str
, const char *rd_str
,
5222 const char *label_str
, int evpn_type
, const char *esi
,
5223 const char *gwip
, const char *ethtag
)
5225 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5228 struct prefix_rd prd
;
5229 struct bgp_node
*prn
;
5230 struct bgp_node
*rn
;
5231 struct bgp_table
*table
;
5232 struct bgp_static
*bgp_static
;
5233 mpls_label_t label
= MPLS_INVALID_LABEL
;
5235 /* Convert IP prefix string to struct prefix. */
5236 ret
= str2prefix(ip_str
, &p
);
5238 vty_out(vty
, "%% Malformed prefix\n");
5239 return CMD_WARNING_CONFIG_FAILED
;
5242 if ((afi
== AFI_L2VPN
)
5243 && (bgp_build_evpn_prefix(evpn_type
,
5244 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5245 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5246 return CMD_WARNING_CONFIG_FAILED
;
5248 ret
= str2prefix_rd(rd_str
, &prd
);
5250 vty_out(vty
, "%% Malformed rd\n");
5251 return CMD_WARNING_CONFIG_FAILED
;
5255 unsigned long label_val
;
5256 label_val
= strtoul(label_str
, NULL
, 10);
5257 encode_label(label_val
, &label
);
5260 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5261 if (prn
->info
== NULL
)
5262 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5264 bgp_unlock_node(prn
);
5267 rn
= bgp_node_lookup(table
, &p
);
5270 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5272 bgp_static
= rn
->info
;
5273 bgp_static_free(bgp_static
);
5275 bgp_unlock_node(rn
);
5276 bgp_unlock_node(rn
);
5278 vty_out(vty
, "%% Can't find the route\n");
5283 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5284 const char *rmap_name
)
5286 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5287 struct bgp_rmap
*rmap
;
5289 rmap
= &bgp
->table_map
[afi
][safi
];
5292 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5293 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5294 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5297 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5302 if (bgp_fibupd_safi(safi
))
5303 bgp_zebra_announce_table(bgp
, afi
, safi
);
5308 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5309 const char *rmap_name
)
5311 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5312 struct bgp_rmap
*rmap
;
5314 rmap
= &bgp
->table_map
[afi
][safi
];
5316 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5320 if (bgp_fibupd_safi(safi
))
5321 bgp_zebra_announce_table(bgp
, afi
, safi
);
5326 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5329 if (bgp
->table_map
[afi
][safi
].name
) {
5330 vty_out(vty
, " table-map %s\n",
5331 bgp
->table_map
[afi
][safi
].name
);
5335 DEFUN (bgp_table_map
,
5338 "BGP table to RIB route download filter\n"
5339 "Name of the route map\n")
5342 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5343 argv
[idx_word
]->arg
);
5345 DEFUN (no_bgp_table_map
,
5346 no_bgp_table_map_cmd
,
5347 "no table-map WORD",
5349 "BGP table to RIB route download filter\n"
5350 "Name of the route map\n")
5353 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5354 argv
[idx_word
]->arg
);
5360 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5361 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5362 backdoor$backdoor}]",
5364 "Specify a network to announce via BGP\n"
5369 "Route-map to modify the attributes\n"
5370 "Name of the route map\n"
5371 "Label index to associate with the prefix\n"
5372 "Label index value\n"
5373 "Specify a BGP backdoor route\n")
5375 char addr_prefix_str
[BUFSIZ
];
5380 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5383 vty_out(vty
, "%% Inconsistent address and mask\n");
5384 return CMD_WARNING_CONFIG_FAILED
;
5388 return bgp_static_set(
5389 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5390 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5391 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5394 DEFPY(ipv6_bgp_network
,
5395 ipv6_bgp_network_cmd
,
5396 "[no] network X:X::X:X/M$prefix \
5397 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5399 "Specify a network to announce via BGP\n"
5401 "Route-map to modify the attributes\n"
5402 "Name of the route map\n"
5403 "Label index to associate with the prefix\n"
5404 "Label index value\n")
5406 return bgp_static_set(
5407 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5408 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5411 /* Aggreagete address:
5413 advertise-map Set condition to advertise attribute
5414 as-set Generate AS set path information
5415 attribute-map Set attributes of aggregate
5416 route-map Set parameters of aggregate
5417 summary-only Filter more specific routes from updates
5418 suppress-map Conditionally filter more specific routes from updates
5421 struct bgp_aggregate
{
5422 /* Summary-only flag. */
5423 uint8_t summary_only
;
5425 /* AS set generation. */
5428 /* Route-map for aggregated route. */
5429 struct route_map
*map
;
5431 /* Suppress-count. */
5432 unsigned long count
;
5434 /* SAFI configuration. */
5438 static struct bgp_aggregate
*bgp_aggregate_new(void)
5440 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5443 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5445 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5448 static int bgp_aggregate_info_same(struct bgp_info
*ri
, struct aspath
*aspath
,
5449 struct community
*comm
)
5451 static struct aspath
*ae
= NULL
;
5454 ae
= aspath_empty();
5459 if (!aspath_cmp(ri
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5462 if (!community_cmp(ri
->attr
->community
, comm
))
5468 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5469 struct prefix
*p
, uint8_t origin
,
5470 struct aspath
*aspath
,
5471 struct community
*community
,
5472 uint8_t atomic_aggregate
,
5473 struct bgp_aggregate
*aggregate
)
5475 struct bgp_node
*rn
;
5476 struct bgp_table
*table
;
5477 struct bgp_info
*ri
, *new;
5479 table
= bgp
->rib
[afi
][safi
];
5481 rn
= bgp_node_get(table
, p
);
5483 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5484 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5485 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5488 if (aggregate
->count
> 0) {
5490 * If the aggregate information has not changed
5491 * no need to re-install it again.
5493 if (bgp_aggregate_info_same(rn
->info
, aspath
, community
)) {
5494 bgp_unlock_node(rn
);
5497 aspath_free(aspath
);
5499 community_free(community
);
5505 * Mark the old as unusable
5508 bgp_info_delete(rn
, ri
);
5511 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5512 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5513 community
, aggregate
->as_set
,
5516 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5518 bgp_info_add(rn
, new);
5519 bgp_process(bgp
, rn
, afi
, safi
);
5521 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5522 if (ri
->peer
== bgp
->peer_self
5523 && ri
->type
== ZEBRA_ROUTE_BGP
5524 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5527 /* Withdraw static BGP route from routing table. */
5529 bgp_info_delete(rn
, ri
);
5530 bgp_process(bgp
, rn
, afi
, safi
);
5534 bgp_unlock_node(rn
);
5537 /* Update an aggregate as routes are added/removed from the BGP table */
5538 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5539 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5540 struct bgp_info
*del
,
5541 struct bgp_aggregate
*aggregate
)
5543 struct bgp_table
*table
;
5544 struct bgp_node
*top
;
5545 struct bgp_node
*rn
;
5547 struct aspath
*aspath
= NULL
;
5548 struct aspath
*asmerge
= NULL
;
5549 struct community
*community
= NULL
;
5550 struct community
*commerge
= NULL
;
5551 struct bgp_info
*ri
;
5552 unsigned long match
= 0;
5553 uint8_t atomic_aggregate
= 0;
5555 /* ORIGIN attribute: If at least one route among routes that are
5556 aggregated has ORIGIN with the value INCOMPLETE, then the
5557 aggregated route must have the ORIGIN attribute with the value
5558 INCOMPLETE. Otherwise, if at least one route among routes that
5559 are aggregated has ORIGIN with the value EGP, then the aggregated
5560 route must have the origin attribute with the value EGP. In all
5561 other case the value of the ORIGIN attribute of the aggregated
5562 route is INTERNAL. */
5563 origin
= BGP_ORIGIN_IGP
;
5565 table
= bgp
->rib
[afi
][safi
];
5567 top
= bgp_node_get(table
, p
);
5568 for (rn
= bgp_node_get(table
, p
); rn
;
5569 rn
= bgp_route_next_until(rn
, top
)) {
5570 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5575 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5576 if (BGP_INFO_HOLDDOWN(ri
))
5579 if (del
&& ri
== del
)
5583 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5584 atomic_aggregate
= 1;
5586 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5590 * summary-only aggregate route suppress
5591 * aggregated route announcements.
5593 if (aggregate
->summary_only
) {
5594 (bgp_info_extra_get(ri
))->suppress
++;
5595 bgp_info_set_flag(rn
, ri
,
5596 BGP_INFO_ATTR_CHANGED
);
5603 * If at least one route among routes that are
5604 * aggregated has ORIGIN with the value INCOMPLETE,
5605 * then the aggregated route MUST have the ORIGIN
5606 * attribute with the value INCOMPLETE. Otherwise, if
5607 * at least one route among routes that are aggregated
5608 * has ORIGIN with the value EGP, then the aggregated
5609 * route MUST have the ORIGIN attribute with the value
5612 if (origin
< ri
->attr
->origin
)
5613 origin
= ri
->attr
->origin
;
5615 if (!aggregate
->as_set
)
5619 * as-set aggregate route generate origin, as path,
5620 * and community aggregation.
5623 asmerge
= aspath_aggregate(aspath
,
5625 aspath_free(aspath
);
5628 aspath
= aspath_dup(ri
->attr
->aspath
);
5630 if (!ri
->attr
->community
)
5634 commerge
= community_merge(community
,
5635 ri
->attr
->community
);
5636 community
= community_uniq_sort(commerge
);
5637 community_free(commerge
);
5639 community
= community_dup(ri
->attr
->community
);
5642 bgp_process(bgp
, rn
, afi
, safi
);
5644 bgp_unlock_node(top
);
5649 if (aggregate
->summary_only
)
5650 (bgp_info_extra_get(rinew
))->suppress
++;
5652 if (origin
< rinew
->attr
->origin
)
5653 origin
= rinew
->attr
->origin
;
5655 if (aggregate
->as_set
) {
5657 asmerge
= aspath_aggregate(aspath
,
5658 rinew
->attr
->aspath
);
5659 aspath_free(aspath
);
5662 aspath
= aspath_dup(rinew
->attr
->aspath
);
5664 if (rinew
->attr
->community
) {
5666 commerge
= community_merge(
5668 rinew
->attr
->community
);
5670 community_uniq_sort(commerge
);
5671 community_free(commerge
);
5673 community
= community_dup(
5674 rinew
->attr
->community
);
5679 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5680 atomic_aggregate
, aggregate
);
5682 if (aggregate
->count
== 0) {
5684 aspath_free(aspath
);
5686 community_free(community
);
5690 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5691 safi_t safi
, struct bgp_aggregate
*aggregate
)
5693 struct bgp_table
*table
;
5694 struct bgp_node
*top
;
5695 struct bgp_node
*rn
;
5696 struct bgp_info
*ri
;
5697 unsigned long match
;
5699 table
= bgp
->rib
[afi
][safi
];
5701 /* If routes exists below this node, generate aggregate routes. */
5702 top
= bgp_node_get(table
, p
);
5703 for (rn
= bgp_node_get(table
, p
); rn
;
5704 rn
= bgp_route_next_until(rn
, top
)) {
5705 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5709 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5710 if (BGP_INFO_HOLDDOWN(ri
))
5713 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5716 if (aggregate
->summary_only
&& ri
->extra
) {
5717 ri
->extra
->suppress
--;
5719 if (ri
->extra
->suppress
== 0) {
5721 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5728 /* If this node was suppressed, process the change. */
5730 bgp_process(bgp
, rn
, afi
, safi
);
5732 bgp_unlock_node(top
);
5735 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5736 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5738 struct bgp_node
*child
;
5739 struct bgp_node
*rn
;
5740 struct bgp_aggregate
*aggregate
;
5741 struct bgp_table
*table
;
5743 table
= bgp
->aggregate
[afi
][safi
];
5745 /* No aggregates configured. */
5746 if (bgp_table_top_nolock(table
) == NULL
)
5749 if (p
->prefixlen
== 0)
5752 if (BGP_INFO_HOLDDOWN(ri
))
5755 child
= bgp_node_get(table
, p
);
5757 /* Aggregate address configuration check. */
5758 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5759 if ((aggregate
= rn
->info
) != NULL
5760 && rn
->p
.prefixlen
< p
->prefixlen
) {
5761 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5762 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5765 bgp_unlock_node(child
);
5768 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5769 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5771 struct bgp_node
*child
;
5772 struct bgp_node
*rn
;
5773 struct bgp_aggregate
*aggregate
;
5774 struct bgp_table
*table
;
5776 table
= bgp
->aggregate
[afi
][safi
];
5778 /* No aggregates configured. */
5779 if (bgp_table_top_nolock(table
) == NULL
)
5782 if (p
->prefixlen
== 0)
5785 child
= bgp_node_get(table
, p
);
5787 /* Aggregate address configuration check. */
5788 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5789 if ((aggregate
= rn
->info
) != NULL
5790 && rn
->p
.prefixlen
< p
->prefixlen
) {
5791 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5792 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5795 bgp_unlock_node(child
);
5798 /* Aggregate route attribute. */
5799 #define AGGREGATE_SUMMARY_ONLY 1
5800 #define AGGREGATE_AS_SET 1
5802 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5803 afi_t afi
, safi_t safi
)
5805 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5808 struct bgp_node
*rn
;
5809 struct bgp_aggregate
*aggregate
;
5811 /* Convert string to prefix structure. */
5812 ret
= str2prefix(prefix_str
, &p
);
5814 vty_out(vty
, "Malformed prefix\n");
5815 return CMD_WARNING_CONFIG_FAILED
;
5819 /* Old configuration check. */
5820 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5823 "%% There is no aggregate-address configuration.\n");
5824 return CMD_WARNING_CONFIG_FAILED
;
5827 aggregate
= rn
->info
;
5828 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5829 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
, 0, aggregate
);
5831 /* Unlock aggregate address configuration. */
5833 bgp_aggregate_free(aggregate
);
5834 bgp_unlock_node(rn
);
5835 bgp_unlock_node(rn
);
5840 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5841 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5843 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5846 struct bgp_node
*rn
;
5847 struct bgp_aggregate
*aggregate
;
5849 /* Convert string to prefix structure. */
5850 ret
= str2prefix(prefix_str
, &p
);
5852 vty_out(vty
, "Malformed prefix\n");
5853 return CMD_WARNING_CONFIG_FAILED
;
5857 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5858 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5859 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5861 return CMD_WARNING_CONFIG_FAILED
;
5864 /* Old configuration check. */
5865 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5868 vty_out(vty
, "There is already same aggregate network.\n");
5869 /* try to remove the old entry */
5870 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5872 vty_out(vty
, "Error deleting aggregate.\n");
5873 bgp_unlock_node(rn
);
5874 return CMD_WARNING_CONFIG_FAILED
;
5878 /* Make aggregate address structure. */
5879 aggregate
= bgp_aggregate_new();
5880 aggregate
->summary_only
= summary_only
;
5881 aggregate
->as_set
= as_set
;
5882 aggregate
->safi
= safi
;
5883 rn
->info
= aggregate
;
5885 /* Aggregate address insert into BGP routing table. */
5886 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
5891 DEFUN (aggregate_address
,
5892 aggregate_address_cmd
,
5893 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5894 "Configure BGP aggregate entries\n"
5895 "Aggregate prefix\n"
5896 "Generate AS set path information\n"
5897 "Filter more specific routes from updates\n"
5898 "Filter more specific routes from updates\n"
5899 "Generate AS set path information\n")
5902 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5903 char *prefix
= argv
[idx
]->arg
;
5905 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5907 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5908 ? AGGREGATE_SUMMARY_ONLY
5911 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5912 summary_only
, as_set
);
5915 DEFUN (aggregate_address_mask
,
5916 aggregate_address_mask_cmd
,
5917 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5918 "Configure BGP aggregate entries\n"
5919 "Aggregate address\n"
5921 "Generate AS set path information\n"
5922 "Filter more specific routes from updates\n"
5923 "Filter more specific routes from updates\n"
5924 "Generate AS set path information\n")
5927 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5928 char *prefix
= argv
[idx
]->arg
;
5929 char *mask
= argv
[idx
+ 1]->arg
;
5931 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5933 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5934 ? AGGREGATE_SUMMARY_ONLY
5937 char prefix_str
[BUFSIZ
];
5938 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5941 vty_out(vty
, "%% Inconsistent address and mask\n");
5942 return CMD_WARNING_CONFIG_FAILED
;
5945 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5946 summary_only
, as_set
);
5949 DEFUN (no_aggregate_address
,
5950 no_aggregate_address_cmd
,
5951 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5953 "Configure BGP aggregate entries\n"
5954 "Aggregate prefix\n"
5955 "Generate AS set path information\n"
5956 "Filter more specific routes from updates\n"
5957 "Filter more specific routes from updates\n"
5958 "Generate AS set path information\n")
5961 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5962 char *prefix
= argv
[idx
]->arg
;
5963 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5966 DEFUN (no_aggregate_address_mask
,
5967 no_aggregate_address_mask_cmd
,
5968 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5970 "Configure BGP aggregate entries\n"
5971 "Aggregate address\n"
5973 "Generate AS set path information\n"
5974 "Filter more specific routes from updates\n"
5975 "Filter more specific routes from updates\n"
5976 "Generate AS set path information\n")
5979 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5980 char *prefix
= argv
[idx
]->arg
;
5981 char *mask
= argv
[idx
+ 1]->arg
;
5983 char prefix_str
[BUFSIZ
];
5984 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5987 vty_out(vty
, "%% Inconsistent address and mask\n");
5988 return CMD_WARNING_CONFIG_FAILED
;
5991 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5994 DEFUN (ipv6_aggregate_address
,
5995 ipv6_aggregate_address_cmd
,
5996 "aggregate-address X:X::X:X/M [summary-only]",
5997 "Configure BGP aggregate entries\n"
5998 "Aggregate prefix\n"
5999 "Filter more specific routes from updates\n")
6002 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6003 char *prefix
= argv
[idx
]->arg
;
6004 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6005 ? AGGREGATE_SUMMARY_ONLY
6007 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6011 DEFUN (no_ipv6_aggregate_address
,
6012 no_ipv6_aggregate_address_cmd
,
6013 "no aggregate-address X:X::X:X/M [summary-only]",
6015 "Configure BGP aggregate entries\n"
6016 "Aggregate prefix\n"
6017 "Filter more specific routes from updates\n")
6020 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6021 char *prefix
= argv
[idx
]->arg
;
6022 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6025 /* Redistribute route treatment. */
6026 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6027 const union g_addr
*nexthop
, ifindex_t ifindex
,
6028 enum nexthop_types_t nhtype
, uint32_t metric
,
6029 uint8_t type
, unsigned short instance
,
6032 struct bgp_info
*new;
6033 struct bgp_info
*bi
;
6034 struct bgp_info info
;
6035 struct bgp_node
*bn
;
6037 struct attr
*new_attr
;
6040 struct bgp_redist
*red
;
6042 /* Make default attribute. */
6043 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6046 case NEXTHOP_TYPE_IFINDEX
:
6048 case NEXTHOP_TYPE_IPV4
:
6049 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6050 attr
.nexthop
= nexthop
->ipv4
;
6052 case NEXTHOP_TYPE_IPV6
:
6053 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6054 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6055 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6057 case NEXTHOP_TYPE_BLACKHOLE
:
6058 switch (p
->family
) {
6060 attr
.nexthop
.s_addr
= INADDR_ANY
;
6063 memset(&attr
.mp_nexthop_global
, 0,
6064 sizeof(attr
.mp_nexthop_global
));
6065 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6070 attr
.nh_ifindex
= ifindex
;
6073 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6076 afi
= family2afi(p
->family
);
6078 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6080 struct attr attr_new
;
6082 /* Copy attribute for modification. */
6083 bgp_attr_dup(&attr_new
, &attr
);
6085 if (red
->redist_metric_flag
)
6086 attr_new
.med
= red
->redist_metric
;
6088 /* Apply route-map. */
6089 if (red
->rmap
.name
) {
6090 memset(&info
, 0, sizeof(struct bgp_info
));
6091 info
.peer
= bgp
->peer_self
;
6092 info
.attr
= &attr_new
;
6094 SET_FLAG(bgp
->peer_self
->rmap_type
,
6095 PEER_RMAP_TYPE_REDISTRIBUTE
);
6097 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6100 bgp
->peer_self
->rmap_type
= 0;
6102 if (ret
== RMAP_DENYMATCH
) {
6103 /* Free uninterned attribute. */
6104 bgp_attr_flush(&attr_new
);
6106 /* Unintern original. */
6107 aspath_unintern(&attr
.aspath
);
6108 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6113 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6114 bgp_attr_add_gshut_community(&attr_new
);
6116 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6117 SAFI_UNICAST
, p
, NULL
);
6119 new_attr
= bgp_attr_intern(&attr_new
);
6121 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6122 if (bi
->peer
== bgp
->peer_self
6123 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6127 /* Ensure the (source route) type is updated. */
6129 if (attrhash_cmp(bi
->attr
, new_attr
)
6130 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6131 bgp_attr_unintern(&new_attr
);
6132 aspath_unintern(&attr
.aspath
);
6133 bgp_unlock_node(bn
);
6136 /* The attribute is changed. */
6137 bgp_info_set_flag(bn
, bi
,
6138 BGP_INFO_ATTR_CHANGED
);
6140 /* Rewrite BGP route information. */
6141 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6142 bgp_info_restore(bn
, bi
);
6144 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6146 bgp_attr_unintern(&bi
->attr
);
6147 bi
->attr
= new_attr
;
6148 bi
->uptime
= bgp_clock();
6150 /* Process change. */
6151 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6153 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6154 bgp_unlock_node(bn
);
6155 aspath_unintern(&attr
.aspath
);
6157 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6159 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6161 vpn_leak_from_vrf_update(
6162 bgp_get_default(), bgp
, bi
);
6168 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6169 bgp
->peer_self
, new_attr
, bn
);
6170 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6172 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6173 bgp_info_add(bn
, new);
6174 bgp_unlock_node(bn
);
6175 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6177 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6178 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6180 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6184 /* Unintern original. */
6185 aspath_unintern(&attr
.aspath
);
6188 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6189 unsigned short instance
)
6192 struct bgp_node
*rn
;
6193 struct bgp_info
*ri
;
6194 struct bgp_redist
*red
;
6196 afi
= family2afi(p
->family
);
6198 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6200 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6201 SAFI_UNICAST
, p
, NULL
);
6203 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6204 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6208 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6209 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6211 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6214 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6215 bgp_info_delete(rn
, ri
);
6216 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6218 bgp_unlock_node(rn
);
6222 /* Withdraw specified route type's route. */
6223 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6224 unsigned short instance
)
6226 struct bgp_node
*rn
;
6227 struct bgp_info
*ri
;
6228 struct bgp_table
*table
;
6230 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6232 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6233 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6234 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6235 && ri
->instance
== instance
)
6239 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6240 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6242 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6245 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6247 bgp_info_delete(rn
, ri
);
6248 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6253 /* Static function to display route. */
6254 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6258 uint32_t destination
;
6261 if (p
->family
== AF_INET
) {
6263 len
= vty_out(vty
, "%s",
6264 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6266 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6268 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6269 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6270 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6271 || p
->u
.prefix4
.s_addr
== 0) {
6272 /* When mask is natural,
6273 mask is not displayed. */
6275 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6277 json_object_string_add(json
, "prefix",
6278 inet_ntop(p
->family
,
6281 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6283 } else if (p
->family
== AF_ETHERNET
) {
6284 prefix2str(p
, buf
, PREFIX_STRLEN
);
6285 len
= vty_out(vty
, "%s", buf
);
6286 } else if (p
->family
== AF_EVPN
) {
6290 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6293 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6294 } else if (p
->family
== AF_FLOWSPEC
) {
6295 route_vty_out_flowspec(vty
, p
, NULL
,
6297 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6298 NLRI_STRING_FORMAT_MIN
, json
);
6303 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6310 vty_out(vty
, "\n%*s", 20, " ");
6312 vty_out(vty
, "%*s", len
, " ");
6316 enum bgp_display_type
{
6320 /* Print the short form route status for a bgp_info */
6321 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6322 json_object
*json_path
)
6326 /* Route status display. */
6327 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6328 json_object_boolean_true_add(json_path
, "removed");
6330 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6331 json_object_boolean_true_add(json_path
, "stale");
6333 if (binfo
->extra
&& binfo
->extra
->suppress
)
6334 json_object_boolean_true_add(json_path
, "suppressed");
6336 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6337 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6338 json_object_boolean_true_add(json_path
, "valid");
6341 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6342 json_object_boolean_true_add(json_path
, "history");
6344 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6345 json_object_boolean_true_add(json_path
, "damped");
6347 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6348 json_object_boolean_true_add(json_path
, "bestpath");
6350 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6351 json_object_boolean_true_add(json_path
, "multipath");
6353 /* Internal route. */
6354 if ((binfo
->peer
->as
)
6355 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6356 json_object_string_add(json_path
, "pathFrom",
6359 json_object_string_add(json_path
, "pathFrom",
6365 /* Route status display. */
6366 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6368 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6370 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6372 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6373 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6379 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6381 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6383 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6385 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6390 /* Internal route. */
6391 if (binfo
->peer
&& (binfo
->peer
->as
)
6392 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6398 /* called from terminal list command */
6399 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6400 int display
, safi_t safi
, json_object
*json_paths
)
6403 json_object
*json_path
= NULL
;
6404 json_object
*json_nexthops
= NULL
;
6405 json_object
*json_nexthop_global
= NULL
;
6406 json_object
*json_nexthop_ll
= NULL
;
6407 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6408 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6411 bool nexthop_othervrf
= false;
6412 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6413 const char *nexthop_vrfname
= "Default";
6416 json_path
= json_object_new_object();
6418 /* short status lead text */
6419 route_vty_short_status_out(vty
, binfo
, json_path
);
6422 /* print prefix and mask */
6424 route_vty_out_route(p
, vty
, json_path
);
6426 vty_out(vty
, "%*s", 17, " ");
6428 route_vty_out_route(p
, vty
, json_path
);
6431 /* Print attribute */
6435 json_object_array_add(json_paths
, json_path
);
6443 * If vrf id of nexthop is different from that of prefix,
6444 * set up printable string to append
6446 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6447 const char *self
= "";
6452 nexthop_othervrf
= true;
6453 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6455 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6456 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6457 "@%s%s", VRFID_NONE_STR
, self
);
6459 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6460 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6462 if (binfo
->extra
->bgp_orig
->inst_type
!=
6463 BGP_INSTANCE_TYPE_DEFAULT
)
6465 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6467 const char *self
= "";
6472 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6476 * For ENCAP and EVPN routes, nexthop address family is not
6477 * neccessarily the same as the prefix address family.
6478 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6479 * EVPN routes are also exchanged with a MP nexthop. Currently,
6481 * is only IPv4, the value will be present in either
6483 * attr->mp_nexthop_global_in
6485 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6488 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6492 sprintf(nexthop
, "%s",
6493 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6497 sprintf(nexthop
, "%s",
6498 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6502 sprintf(nexthop
, "?");
6507 json_nexthop_global
= json_object_new_object();
6509 json_object_string_add(json_nexthop_global
, "afi",
6510 (af
== AF_INET
) ? "ip" : "ipv6");
6511 json_object_string_add(json_nexthop_global
,
6512 (af
== AF_INET
) ? "ip" : "ipv6",
6514 json_object_boolean_true_add(json_nexthop_global
,
6517 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6518 } else if (safi
== SAFI_EVPN
) {
6520 json_nexthop_global
= json_object_new_object();
6522 json_object_string_add(json_nexthop_global
, "ip",
6523 inet_ntoa(attr
->nexthop
));
6524 json_object_string_add(json_nexthop_global
, "afi",
6526 json_object_boolean_true_add(json_nexthop_global
,
6529 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6531 } else if (safi
== SAFI_FLOWSPEC
) {
6532 if (attr
->nexthop
.s_addr
!= 0) {
6534 json_nexthop_global
= json_object_new_object();
6535 json_object_string_add(
6536 json_nexthop_global
, "ip",
6537 inet_ntoa(attr
->nexthop
));
6538 json_object_string_add(json_nexthop_global
,
6540 json_object_boolean_true_add(json_nexthop_global
,
6543 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6546 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6548 json_nexthop_global
= json_object_new_object();
6550 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6551 json_object_string_add(
6552 json_nexthop_global
, "ip",
6553 inet_ntoa(attr
->mp_nexthop_global_in
));
6555 json_object_string_add(
6556 json_nexthop_global
, "ip",
6557 inet_ntoa(attr
->nexthop
));
6559 json_object_string_add(json_nexthop_global
, "afi",
6561 json_object_boolean_true_add(json_nexthop_global
,
6566 snprintf(buf
, sizeof(buf
), "%s%s",
6567 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6568 vty_out(vty
, "%-16s", buf
);
6573 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6578 json_nexthop_global
= json_object_new_object();
6579 json_object_string_add(
6580 json_nexthop_global
, "ip",
6581 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6583 json_object_string_add(json_nexthop_global
, "afi",
6585 json_object_string_add(json_nexthop_global
, "scope",
6588 /* We display both LL & GL if both have been
6590 if ((attr
->mp_nexthop_len
== 32)
6591 || (binfo
->peer
->conf_if
)) {
6592 json_nexthop_ll
= json_object_new_object();
6593 json_object_string_add(
6594 json_nexthop_ll
, "ip",
6596 &attr
->mp_nexthop_local
, buf
,
6598 json_object_string_add(json_nexthop_ll
, "afi",
6600 json_object_string_add(json_nexthop_ll
, "scope",
6603 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6604 &attr
->mp_nexthop_local
)
6606 && !attr
->mp_nexthop_prefer_global
)
6607 json_object_boolean_true_add(
6608 json_nexthop_ll
, "used");
6610 json_object_boolean_true_add(
6611 json_nexthop_global
, "used");
6613 json_object_boolean_true_add(
6614 json_nexthop_global
, "used");
6616 /* Display LL if LL/Global both in table unless
6617 * prefer-global is set */
6618 if (((attr
->mp_nexthop_len
== 32)
6619 && !attr
->mp_nexthop_prefer_global
)
6620 || (binfo
->peer
->conf_if
)) {
6621 if (binfo
->peer
->conf_if
) {
6622 len
= vty_out(vty
, "%s",
6623 binfo
->peer
->conf_if
);
6624 len
= 16 - len
; /* len of IPv6
6630 vty_out(vty
, "\n%*s", 36, " ");
6632 vty_out(vty
, "%*s", len
, " ");
6638 &attr
->mp_nexthop_local
,
6644 vty_out(vty
, "\n%*s", 36, " ");
6646 vty_out(vty
, "%*s", len
, " ");
6652 &attr
->mp_nexthop_global
, buf
,
6658 vty_out(vty
, "\n%*s", 36, " ");
6660 vty_out(vty
, "%*s", len
, " ");
6666 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6668 json_object_int_add(json_path
, "med", attr
->med
);
6670 vty_out(vty
, "%10u", attr
->med
);
6671 else if (!json_paths
)
6675 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6677 json_object_int_add(json_path
, "localpref",
6680 vty_out(vty
, "%7u", attr
->local_pref
);
6681 else if (!json_paths
)
6685 json_object_int_add(json_path
, "weight", attr
->weight
);
6687 vty_out(vty
, "%7u ", attr
->weight
);
6691 json_object_string_add(
6692 json_path
, "peerId",
6693 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6699 json_object_string_add(json_path
, "aspath",
6702 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6707 json_object_string_add(json_path
, "origin",
6708 bgp_origin_long_str
[attr
->origin
]);
6710 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6714 json_object_boolean_true_add(json_path
,
6715 "announceNexthopSelf");
6716 if (nexthop_othervrf
) {
6717 json_object_string_add(json_path
, "nhVrfName",
6720 json_object_int_add(json_path
, "nhVrfId",
6721 ((nexthop_vrfid
== VRF_UNKNOWN
)
6723 : (int)nexthop_vrfid
));
6728 if (json_nexthop_global
|| json_nexthop_ll
) {
6729 json_nexthops
= json_object_new_array();
6731 if (json_nexthop_global
)
6732 json_object_array_add(json_nexthops
,
6733 json_nexthop_global
);
6735 if (json_nexthop_ll
)
6736 json_object_array_add(json_nexthops
,
6739 json_object_object_add(json_path
, "nexthops",
6743 json_object_array_add(json_paths
, json_path
);
6747 /* prints an additional line, indented, with VNC info, if
6749 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6750 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6755 /* called from terminal list command */
6756 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6757 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6759 json_object
*json_status
= NULL
;
6760 json_object
*json_net
= NULL
;
6762 /* Route status display. */
6764 json_status
= json_object_new_object();
6765 json_net
= json_object_new_object();
6772 /* print prefix and mask */
6774 json_object_string_add(
6775 json_net
, "addrPrefix",
6776 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6778 route_vty_out_route(p
, vty
, NULL
);
6780 /* Print attribute */
6783 if (p
->family
== AF_INET
6784 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6785 || safi
== SAFI_EVPN
6786 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6787 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6788 || safi
== SAFI_EVPN
)
6789 json_object_string_add(
6790 json_net
, "nextHop",
6792 attr
->mp_nexthop_global_in
));
6794 json_object_string_add(
6795 json_net
, "nextHop",
6796 inet_ntoa(attr
->nexthop
));
6797 } else if (p
->family
== AF_INET6
6798 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6801 json_object_string_add(
6802 json_net
, "netHopGloabal",
6804 &attr
->mp_nexthop_global
, buf
,
6809 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6810 json_object_int_add(json_net
, "metric",
6813 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6814 json_object_int_add(json_net
, "localPref",
6817 json_object_int_add(json_net
, "weight", attr
->weight
);
6821 json_object_string_add(json_net
, "asPath",
6825 json_object_string_add(json_net
, "bgpOriginCode",
6826 bgp_origin_str
[attr
->origin
]);
6828 if (p
->family
== AF_INET
6829 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6830 || safi
== SAFI_EVPN
6831 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6832 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6833 || safi
== SAFI_EVPN
)
6834 vty_out(vty
, "%-16s",
6836 attr
->mp_nexthop_global_in
));
6838 vty_out(vty
, "%-16s",
6839 inet_ntoa(attr
->nexthop
));
6840 } else if (p
->family
== AF_INET6
6841 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6848 &attr
->mp_nexthop_global
, buf
,
6852 vty_out(vty
, "\n%*s", 36, " ");
6854 vty_out(vty
, "%*s", len
, " ");
6857 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6858 vty_out(vty
, "%10u", attr
->med
);
6862 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6863 vty_out(vty
, "%7u", attr
->local_pref
);
6867 vty_out(vty
, "%7u ", attr
->weight
);
6871 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6874 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6878 json_object_boolean_true_add(json_status
, "*");
6879 json_object_boolean_true_add(json_status
, ">");
6880 json_object_object_add(json_net
, "appliedStatusSymbols",
6882 char buf_cut
[BUFSIZ
];
6883 json_object_object_add(
6885 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6891 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6892 struct bgp_info
*binfo
, int display
, safi_t safi
,
6895 json_object
*json_out
= NULL
;
6897 mpls_label_t label
= MPLS_INVALID_LABEL
;
6903 json_out
= json_object_new_object();
6905 /* short status lead text */
6906 route_vty_short_status_out(vty
, binfo
, json_out
);
6908 /* print prefix and mask */
6911 route_vty_out_route(p
, vty
, NULL
);
6913 vty_out(vty
, "%*s", 17, " ");
6916 /* Print attribute */
6919 if (((p
->family
== AF_INET
)
6920 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6921 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6922 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6923 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6924 || safi
== SAFI_EVPN
) {
6926 json_object_string_add(
6927 json_out
, "mpNexthopGlobalIn",
6929 attr
->mp_nexthop_global_in
));
6931 vty_out(vty
, "%-16s",
6933 attr
->mp_nexthop_global_in
));
6936 json_object_string_add(
6937 json_out
, "nexthop",
6938 inet_ntoa(attr
->nexthop
));
6940 vty_out(vty
, "%-16s",
6941 inet_ntoa(attr
->nexthop
));
6943 } else if (((p
->family
== AF_INET6
)
6944 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6945 || (safi
== SAFI_EVPN
6946 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6947 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6951 if (attr
->mp_nexthop_len
6952 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6954 json_object_string_add(
6955 json_out
, "mpNexthopGlobalIn",
6958 &attr
->mp_nexthop_global
,
6959 buf_a
, sizeof(buf_a
)));
6964 &attr
->mp_nexthop_global
,
6965 buf_a
, sizeof(buf_a
)));
6966 } else if (attr
->mp_nexthop_len
6967 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6970 &attr
->mp_nexthop_global
,
6971 buf_a
, sizeof(buf_a
));
6973 &attr
->mp_nexthop_local
,
6974 buf_b
, sizeof(buf_b
));
6975 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6976 json_object_string_add(
6978 "mpNexthopGlobalLocal", buf_c
);
6980 vty_out(vty
, "%s(%s)",
6983 &attr
->mp_nexthop_global
,
6984 buf_a
, sizeof(buf_a
)),
6987 &attr
->mp_nexthop_local
,
6988 buf_b
, sizeof(buf_b
)));
6993 label
= decode_label(&binfo
->extra
->label
[0]);
6995 if (bgp_is_valid_label(&label
)) {
6997 json_object_int_add(json_out
, "notag", label
);
6998 json_object_array_add(json
, json_out
);
7000 vty_out(vty
, "notag/%d", label
);
7006 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7007 struct bgp_info
*binfo
, int display
,
7008 json_object
*json_paths
)
7012 json_object
*json_path
= NULL
;
7015 json_path
= json_object_new_object();
7020 /* short status lead text */
7021 route_vty_short_status_out(vty
, binfo
, json_path
);
7023 /* print prefix and mask */
7025 route_vty_out_route(p
, vty
, NULL
);
7027 vty_out(vty
, "%*s", 17, " ");
7029 /* Print attribute */
7033 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7037 vty_out(vty
, "%-16s",
7038 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7042 vty_out(vty
, "%s(%s)",
7043 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7045 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7052 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7054 vty_out(vty
, "%s", str
);
7055 XFREE(MTYPE_TMP
, str
);
7057 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7059 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7060 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7063 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7066 if (attr
->ecommunity
) {
7068 struct ecommunity_val
*routermac
= ecommunity_lookup(
7069 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7070 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7072 mac
= ecom_mac2str((char *)routermac
->val
);
7074 vty_out(vty
, "/%s", (char *)mac
);
7075 XFREE(MTYPE_TMP
, mac
);
7083 /* dampening route */
7084 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7085 struct bgp_info
*binfo
, int display
, safi_t safi
,
7086 uint8_t use_json
, json_object
*json
)
7090 char timebuf
[BGP_UPTIME_LEN
];
7092 /* short status lead text */
7093 route_vty_short_status_out(vty
, binfo
, json
);
7095 /* print prefix and mask */
7098 route_vty_out_route(p
, vty
, NULL
);
7100 vty_out(vty
, "%*s", 17, " ");
7103 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7107 vty_out(vty
, "\n%*s", 34, " ");
7110 json_object_int_add(json
, "peerHost", len
);
7112 vty_out(vty
, "%*s", len
, " ");
7116 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7119 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7123 /* Print attribute */
7129 json_object_string_add(json
, "asPath",
7132 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7137 json_object_string_add(json
, "origin",
7138 bgp_origin_str
[attr
->origin
]);
7140 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7147 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7148 struct bgp_info
*binfo
, int display
, safi_t safi
,
7149 uint8_t use_json
, json_object
*json
)
7152 struct bgp_damp_info
*bdi
;
7153 char timebuf
[BGP_UPTIME_LEN
];
7159 bdi
= binfo
->extra
->damp_info
;
7161 /* short status lead text */
7162 route_vty_short_status_out(vty
, binfo
, json
);
7164 /* print prefix and mask */
7167 route_vty_out_route(p
, vty
, NULL
);
7169 vty_out(vty
, "%*s", 17, " ");
7172 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7176 vty_out(vty
, "\n%*s", 33, " ");
7179 json_object_int_add(json
, "peerHost", len
);
7181 vty_out(vty
, "%*s", len
, " ");
7184 len
= vty_out(vty
, "%d", bdi
->flap
);
7191 json_object_int_add(json
, "bdiFlap", len
);
7193 vty_out(vty
, "%*s", len
, " ");
7197 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7200 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7201 BGP_UPTIME_LEN
, 0, NULL
));
7203 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7204 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7206 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7207 BGP_UPTIME_LEN
, use_json
, json
);
7210 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7215 vty_out(vty
, "%*s ", 8, " ");
7218 /* Print attribute */
7224 json_object_string_add(json
, "asPath",
7227 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7232 json_object_string_add(json
, "origin",
7233 bgp_origin_str
[attr
->origin
]);
7235 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7241 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7242 int *first
, const char *header
,
7243 json_object
*json_adv_to
)
7245 char buf1
[INET6_ADDRSTRLEN
];
7246 json_object
*json_peer
= NULL
;
7249 /* 'advertised-to' is a dictionary of peers we have advertised
7251 * prefix too. The key is the peer's IP or swpX, the value is
7253 * hostname if we know it and "" if not.
7255 json_peer
= json_object_new_object();
7258 json_object_string_add(json_peer
, "hostname",
7262 json_object_object_add(json_adv_to
, peer
->conf_if
,
7265 json_object_object_add(
7267 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7271 vty_out(vty
, "%s", header
);
7276 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7278 vty_out(vty
, " %s(%s)", peer
->hostname
,
7281 vty_out(vty
, " %s(%s)", peer
->hostname
,
7282 sockunion2str(&peer
->su
, buf1
,
7286 vty_out(vty
, " %s", peer
->conf_if
);
7289 sockunion2str(&peer
->su
, buf1
,
7295 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7296 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7297 json_object
*json_paths
)
7299 char buf
[INET6_ADDRSTRLEN
];
7301 char buf2
[EVPN_ROUTE_STRLEN
];
7303 int sockunion_vty_out(struct vty
*, union sockunion
*);
7305 json_object
*json_bestpath
= NULL
;
7306 json_object
*json_cluster_list
= NULL
;
7307 json_object
*json_cluster_list_list
= NULL
;
7308 json_object
*json_ext_community
= NULL
;
7309 json_object
*json_last_update
= NULL
;
7310 json_object
*json_pmsi
= NULL
;
7311 json_object
*json_nexthop_global
= NULL
;
7312 json_object
*json_nexthop_ll
= NULL
;
7313 json_object
*json_nexthops
= NULL
;
7314 json_object
*json_path
= NULL
;
7315 json_object
*json_peer
= NULL
;
7316 json_object
*json_string
= NULL
;
7317 json_object
*json_adv_to
= NULL
;
7319 struct listnode
*node
, *nnode
;
7321 int addpath_capable
;
7323 unsigned int first_as
;
7324 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7329 json_path
= json_object_new_object();
7330 json_peer
= json_object_new_object();
7331 json_nexthop_global
= json_object_new_object();
7334 if (!json_paths
&& safi
== SAFI_EVPN
) {
7337 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7338 vty_out(vty
, " Route %s", buf2
);
7340 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7341 bgp_evpn_label2str(binfo
->extra
->label
,
7342 binfo
->extra
->num_labels
, tag_buf
,
7344 vty_out(vty
, " VNI %s", tag_buf
);
7347 if (binfo
->extra
&& binfo
->extra
->parent
) {
7348 struct bgp_info
*parent_ri
;
7349 struct bgp_node
*rn
, *prn
;
7351 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7352 rn
= parent_ri
->net
;
7353 if (rn
&& rn
->prn
) {
7355 vty_out(vty
, " Imported from %s:%s\n",
7357 (struct prefix_rd
*)&prn
->p
,
7358 buf1
, sizeof(buf1
)),
7367 /* Line1 display AS-path, Aggregator */
7370 if (!attr
->aspath
->json
)
7371 aspath_str_update(attr
->aspath
, true);
7372 json_object_lock(attr
->aspath
->json
);
7373 json_object_object_add(json_path
, "aspath",
7374 attr
->aspath
->json
);
7376 if (attr
->aspath
->segments
)
7377 aspath_print_vty(vty
, " %s",
7380 vty_out(vty
, " Local");
7384 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7386 json_object_boolean_true_add(json_path
,
7389 vty_out(vty
, ", (removed)");
7392 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7394 json_object_boolean_true_add(json_path
,
7397 vty_out(vty
, ", (stale)");
7400 if (CHECK_FLAG(attr
->flag
,
7401 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7403 json_object_int_add(json_path
, "aggregatorAs",
7404 attr
->aggregator_as
);
7405 json_object_string_add(
7406 json_path
, "aggregatorId",
7407 inet_ntoa(attr
->aggregator_addr
));
7409 vty_out(vty
, ", (aggregated by %u %s)",
7410 attr
->aggregator_as
,
7411 inet_ntoa(attr
->aggregator_addr
));
7415 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7416 PEER_FLAG_REFLECTOR_CLIENT
)) {
7418 json_object_boolean_true_add(
7419 json_path
, "rxedFromRrClient");
7421 vty_out(vty
, ", (Received from a RR-client)");
7424 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7425 PEER_FLAG_RSERVER_CLIENT
)) {
7427 json_object_boolean_true_add(
7428 json_path
, "rxedFromRsClient");
7430 vty_out(vty
, ", (Received from a RS-client)");
7433 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7435 json_object_boolean_true_add(
7436 json_path
, "dampeningHistoryEntry");
7438 vty_out(vty
, ", (history entry)");
7439 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7441 json_object_boolean_true_add(
7442 json_path
, "dampeningSuppressed");
7444 vty_out(vty
, ", (suppressed due to dampening)");
7450 /* Line2 display Next-hop, Neighbor, Router-id */
7451 /* Display the nexthop */
7452 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7453 || p
->family
== AF_EVPN
)
7454 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7455 || safi
== SAFI_EVPN
7456 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7457 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7458 || safi
== SAFI_EVPN
) {
7460 json_object_string_add(
7461 json_nexthop_global
, "ip",
7463 attr
->mp_nexthop_global_in
));
7467 attr
->mp_nexthop_global_in
));
7470 json_object_string_add(
7471 json_nexthop_global
, "ip",
7472 inet_ntoa(attr
->nexthop
));
7475 inet_ntoa(attr
->nexthop
));
7479 json_object_string_add(json_nexthop_global
,
7483 json_object_string_add(
7484 json_nexthop_global
, "ip",
7486 &attr
->mp_nexthop_global
, buf
,
7488 json_object_string_add(json_nexthop_global
,
7490 json_object_string_add(json_nexthop_global
,
7495 &attr
->mp_nexthop_global
, buf
,
7500 /* Display the IGP cost or 'inaccessible' */
7501 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7503 json_object_boolean_false_add(
7504 json_nexthop_global
, "accessible");
7506 vty_out(vty
, " (inaccessible)");
7508 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7510 json_object_int_add(
7511 json_nexthop_global
, "metric",
7512 binfo
->extra
->igpmetric
);
7514 vty_out(vty
, " (metric %u)",
7515 binfo
->extra
->igpmetric
);
7518 /* IGP cost is 0, display this only for json */
7521 json_object_int_add(json_nexthop_global
,
7526 json_object_boolean_true_add(
7527 json_nexthop_global
, "accessible");
7530 /* Display peer "from" output */
7531 /* This path was originated locally */
7532 if (binfo
->peer
== bgp
->peer_self
) {
7534 if (safi
== SAFI_EVPN
7535 || (p
->family
== AF_INET
7536 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7538 json_object_string_add(
7539 json_peer
, "peerId", "0.0.0.0");
7541 vty_out(vty
, " from 0.0.0.0 ");
7544 json_object_string_add(json_peer
,
7547 vty_out(vty
, " from :: ");
7551 json_object_string_add(
7552 json_peer
, "routerId",
7553 inet_ntoa(bgp
->router_id
));
7555 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7558 /* We RXed this path from one of our peers */
7562 json_object_string_add(
7563 json_peer
, "peerId",
7564 sockunion2str(&binfo
->peer
->su
, buf
,
7566 json_object_string_add(
7567 json_peer
, "routerId",
7569 &binfo
->peer
->remote_id
, buf1
,
7572 if (binfo
->peer
->hostname
)
7573 json_object_string_add(
7574 json_peer
, "hostname",
7575 binfo
->peer
->hostname
);
7577 if (binfo
->peer
->domainname
)
7578 json_object_string_add(
7579 json_peer
, "domainname",
7580 binfo
->peer
->domainname
);
7582 if (binfo
->peer
->conf_if
)
7583 json_object_string_add(
7584 json_peer
, "interface",
7585 binfo
->peer
->conf_if
);
7587 if (binfo
->peer
->conf_if
) {
7588 if (binfo
->peer
->hostname
7591 BGP_FLAG_SHOW_HOSTNAME
))
7592 vty_out(vty
, " from %s(%s)",
7593 binfo
->peer
->hostname
,
7594 binfo
->peer
->conf_if
);
7596 vty_out(vty
, " from %s",
7597 binfo
->peer
->conf_if
);
7599 if (binfo
->peer
->hostname
7602 BGP_FLAG_SHOW_HOSTNAME
))
7603 vty_out(vty
, " from %s(%s)",
7604 binfo
->peer
->hostname
,
7607 vty_out(vty
, " from %s",
7616 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7617 vty_out(vty
, " (%s)",
7618 inet_ntoa(attr
->originator_id
));
7620 vty_out(vty
, " (%s)",
7623 &binfo
->peer
->remote_id
,
7624 buf1
, sizeof(buf1
)));
7629 * Note when vrfid of nexthop is different from that of prefix
7631 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7632 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7637 if (binfo
->extra
->bgp_orig
->inst_type
==
7638 BGP_INSTANCE_TYPE_DEFAULT
)
7642 vn
= binfo
->extra
->bgp_orig
->name
;
7644 json_object_string_add(json_path
, "nhVrfName",
7647 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7648 json_object_int_add(json_path
,
7651 json_object_int_add(json_path
,
7652 "nhVrfId", (int)nexthop_vrfid
);
7655 if (nexthop_vrfid
== VRF_UNKNOWN
)
7656 vty_out(vty
, " vrf ?");
7658 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7664 json_object_boolean_true_add(json_path
,
7665 "announceNexthopSelf");
7667 vty_out(vty
, " announce-nh-self");
7674 /* display the link-local nexthop */
7675 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7677 json_nexthop_ll
= json_object_new_object();
7678 json_object_string_add(
7679 json_nexthop_ll
, "ip",
7681 &attr
->mp_nexthop_local
, buf
,
7683 json_object_string_add(json_nexthop_ll
, "afi",
7685 json_object_string_add(json_nexthop_ll
, "scope",
7688 json_object_boolean_true_add(json_nexthop_ll
,
7691 if (!attr
->mp_nexthop_prefer_global
)
7692 json_object_boolean_true_add(
7693 json_nexthop_ll
, "used");
7695 json_object_boolean_true_add(
7696 json_nexthop_global
, "used");
7698 vty_out(vty
, " (%s) %s\n",
7700 &attr
->mp_nexthop_local
, buf
,
7702 attr
->mp_nexthop_prefer_global
7707 /* If we do not have a link-local nexthop then we must flag the
7711 json_object_boolean_true_add(
7712 json_nexthop_global
, "used");
7715 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7716 * Int/Ext/Local, Atomic, best */
7718 json_object_string_add(
7719 json_path
, "origin",
7720 bgp_origin_long_str
[attr
->origin
]);
7722 vty_out(vty
, " Origin %s",
7723 bgp_origin_long_str
[attr
->origin
]);
7725 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7727 json_object_int_add(json_path
, "med",
7730 vty_out(vty
, ", metric %u", attr
->med
);
7733 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7735 json_object_int_add(json_path
, "localpref",
7738 vty_out(vty
, ", localpref %u",
7742 if (attr
->weight
!= 0) {
7744 json_object_int_add(json_path
, "weight",
7747 vty_out(vty
, ", weight %u", attr
->weight
);
7750 if (attr
->tag
!= 0) {
7752 json_object_int_add(json_path
, "tag",
7755 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7759 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7761 json_object_boolean_false_add(json_path
,
7764 vty_out(vty
, ", invalid");
7765 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7767 json_object_boolean_true_add(json_path
,
7770 vty_out(vty
, ", valid");
7773 if (binfo
->peer
!= bgp
->peer_self
) {
7774 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7775 if (CHECK_FLAG(bgp
->config
,
7776 BGP_CONFIG_CONFEDERATION
)) {
7778 json_object_string_add(
7783 ", confed-internal");
7786 json_object_string_add(
7790 vty_out(vty
, ", internal");
7793 if (bgp_confederation_peers_check(
7794 bgp
, binfo
->peer
->as
)) {
7796 json_object_string_add(
7801 ", confed-external");
7804 json_object_string_add(
7808 vty_out(vty
, ", external");
7811 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7813 json_object_boolean_true_add(json_path
,
7815 json_object_boolean_true_add(json_path
,
7818 vty_out(vty
, ", aggregated, local");
7820 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7822 json_object_boolean_true_add(json_path
,
7825 vty_out(vty
, ", sourced");
7828 json_object_boolean_true_add(json_path
,
7830 json_object_boolean_true_add(json_path
,
7833 vty_out(vty
, ", sourced, local");
7837 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7839 json_object_boolean_true_add(json_path
,
7842 vty_out(vty
, ", atomic-aggregate");
7845 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7846 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7847 && bgp_info_mpath_count(binfo
))) {
7849 json_object_boolean_true_add(json_path
,
7852 vty_out(vty
, ", multipath");
7855 // Mark the bestpath(s)
7856 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7857 first_as
= aspath_get_first_as(attr
->aspath
);
7862 json_object_new_object();
7863 json_object_int_add(json_bestpath
,
7864 "bestpathFromAs", first_as
);
7867 vty_out(vty
, ", bestpath-from-AS %u",
7871 ", bestpath-from-AS Local");
7875 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7879 json_object_new_object();
7880 json_object_boolean_true_add(json_bestpath
,
7883 vty_out(vty
, ", best");
7887 json_object_object_add(json_path
, "bestpath",
7893 /* Line 4 display Community */
7894 if (attr
->community
) {
7896 if (!attr
->community
->json
)
7897 community_str(attr
->community
, true);
7898 json_object_lock(attr
->community
->json
);
7899 json_object_object_add(json_path
, "community",
7900 attr
->community
->json
);
7902 vty_out(vty
, " Community: %s\n",
7903 attr
->community
->str
);
7907 /* Line 5 display Extended-community */
7908 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7910 json_ext_community
= json_object_new_object();
7911 json_object_string_add(json_ext_community
,
7913 attr
->ecommunity
->str
);
7914 json_object_object_add(json_path
,
7915 "extendedCommunity",
7916 json_ext_community
);
7918 vty_out(vty
, " Extended Community: %s\n",
7919 attr
->ecommunity
->str
);
7923 /* Line 6 display Large community */
7924 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7926 if (!attr
->lcommunity
->json
)
7927 lcommunity_str(attr
->lcommunity
, true);
7928 json_object_lock(attr
->lcommunity
->json
);
7929 json_object_object_add(json_path
,
7931 attr
->lcommunity
->json
);
7933 vty_out(vty
, " Large Community: %s\n",
7934 attr
->lcommunity
->str
);
7938 /* Line 7 display Originator, Cluster-id */
7939 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7940 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7942 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7944 json_object_string_add(
7945 json_path
, "originatorId",
7946 inet_ntoa(attr
->originator_id
));
7948 vty_out(vty
, " Originator: %s",
7949 inet_ntoa(attr
->originator_id
));
7952 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7957 json_object_new_object();
7958 json_cluster_list_list
=
7959 json_object_new_array();
7962 i
< attr
->cluster
->length
/ 4;
7964 json_string
= json_object_new_string(
7968 json_object_array_add(
7969 json_cluster_list_list
,
7973 /* struct cluster_list does not have
7975 * aspath and community do. Add this
7978 json_object_string_add(json_cluster_list,
7979 "string", attr->cluster->str);
7981 json_object_object_add(
7982 json_cluster_list
, "list",
7983 json_cluster_list_list
);
7984 json_object_object_add(
7985 json_path
, "clusterList",
7988 vty_out(vty
, ", Cluster list: ");
7991 i
< attr
->cluster
->length
/ 4;
8005 if (binfo
->extra
&& binfo
->extra
->damp_info
)
8006 bgp_damp_info_vty(vty
, binfo
, json_path
);
8009 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8010 && safi
!= SAFI_EVPN
) {
8011 mpls_label_t label
=
8012 label_pton(&binfo
->extra
->label
[0]);
8014 json_object_int_add(json_path
, "remoteLabel",
8017 vty_out(vty
, " Remote label: %d\n", label
);
8021 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8023 json_object_int_add(json_path
, "labelIndex",
8026 vty_out(vty
, " Label Index: %d\n",
8030 /* Line 8 display Addpath IDs */
8031 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8033 json_object_int_add(json_path
, "addpathRxId",
8034 binfo
->addpath_rx_id
);
8035 json_object_int_add(json_path
, "addpathTxId",
8036 binfo
->addpath_tx_id
);
8038 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8039 binfo
->addpath_rx_id
,
8040 binfo
->addpath_tx_id
);
8044 /* If we used addpath to TX a non-bestpath we need to display
8045 * "Advertised to" on a path-by-path basis */
8046 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8049 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8051 bgp_addpath_encode_tx(peer
, afi
, safi
);
8052 has_adj
= bgp_adj_out_lookup(
8053 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8055 if ((addpath_capable
&& has_adj
)
8056 || (!addpath_capable
&& has_adj
8057 && CHECK_FLAG(binfo
->flags
,
8058 BGP_INFO_SELECTED
))) {
8059 if (json_path
&& !json_adv_to
)
8061 json_object_new_object();
8063 route_vty_out_advertised_to(
8072 json_object_object_add(json_path
,
8083 /* Line 9 display Uptime */
8084 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8086 json_last_update
= json_object_new_object();
8087 json_object_int_add(json_last_update
, "epoch", tbuf
);
8088 json_object_string_add(json_last_update
, "string",
8090 json_object_object_add(json_path
, "lastUpdate",
8093 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8095 /* Line 10 display PMSI tunnel attribute, if present */
8096 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8097 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8098 attr
->pmsi_tnl_type
,
8099 PMSI_TNLTYPE_STR_DEFAULT
);
8102 json_pmsi
= json_object_new_object();
8103 json_object_string_add(json_pmsi
,
8105 json_object_object_add(json_path
, "pmsi",
8108 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8114 /* We've constructed the json object for this path, add it to the json
8118 if (json_nexthop_global
|| json_nexthop_ll
) {
8119 json_nexthops
= json_object_new_array();
8121 if (json_nexthop_global
)
8122 json_object_array_add(json_nexthops
,
8123 json_nexthop_global
);
8125 if (json_nexthop_ll
)
8126 json_object_array_add(json_nexthops
,
8129 json_object_object_add(json_path
, "nexthops",
8133 json_object_object_add(json_path
, "peer", json_peer
);
8134 json_object_array_add(json_paths
, json_path
);
8139 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8140 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8141 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8143 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8144 const char *prefix_list_str
, afi_t afi
,
8145 safi_t safi
, enum bgp_show_type type
);
8146 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8147 const char *filter
, afi_t afi
, safi_t safi
,
8148 enum bgp_show_type type
);
8149 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8150 const char *rmap_str
, afi_t afi
, safi_t safi
,
8151 enum bgp_show_type type
);
8152 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8153 const char *com
, int exact
, afi_t afi
,
8155 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8156 const char *prefix
, afi_t afi
, safi_t safi
,
8157 enum bgp_show_type type
);
8158 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8159 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8160 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8161 const char *comstr
, int exact
, afi_t afi
,
8162 safi_t safi
, uint8_t use_json
);
8165 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8166 struct bgp_table
*table
, enum bgp_show_type type
,
8167 void *output_arg
, uint8_t use_json
, char *rd
,
8168 int is_last
, unsigned long *output_cum
,
8169 unsigned long *total_cum
,
8170 unsigned long *json_header_depth
)
8172 struct bgp_info
*ri
;
8173 struct bgp_node
*rn
;
8176 unsigned long output_count
= 0;
8177 unsigned long total_count
= 0;
8181 json_object
*json_paths
= NULL
;
8184 if (output_cum
&& *output_cum
!= 0)
8187 if (use_json
&& !*json_header_depth
) {
8189 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8190 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8191 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8192 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8194 table
->version
, inet_ntoa(bgp
->router_id
));
8195 *json_header_depth
= 2;
8197 vty_out(vty
, " \"routeDistinguishers\" : {");
8198 ++*json_header_depth
;
8200 json_paths
= json_object_new_object();
8203 if (use_json
&& rd
) {
8204 vty_out(vty
, " \"%s\" : { ", rd
);
8207 /* Start processing of routes. */
8208 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8209 if (rn
->info
== NULL
)
8214 json_paths
= json_object_new_array();
8218 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8220 if (type
== bgp_show_type_flap_statistics
8221 || type
== bgp_show_type_flap_neighbor
8222 || type
== bgp_show_type_dampend_paths
8223 || type
== bgp_show_type_damp_neighbor
) {
8224 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8227 if (type
== bgp_show_type_regexp
) {
8228 regex_t
*regex
= output_arg
;
8230 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8234 if (type
== bgp_show_type_prefix_list
) {
8235 struct prefix_list
*plist
= output_arg
;
8237 if (prefix_list_apply(plist
, &rn
->p
)
8241 if (type
== bgp_show_type_filter_list
) {
8242 struct as_list
*as_list
= output_arg
;
8244 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8245 != AS_FILTER_PERMIT
)
8248 if (type
== bgp_show_type_route_map
) {
8249 struct route_map
*rmap
= output_arg
;
8250 struct bgp_info binfo
;
8251 struct attr dummy_attr
;
8254 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8256 binfo
.peer
= ri
->peer
;
8257 binfo
.attr
= &dummy_attr
;
8259 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8261 if (ret
== RMAP_DENYMATCH
)
8264 if (type
== bgp_show_type_neighbor
8265 || type
== bgp_show_type_flap_neighbor
8266 || type
== bgp_show_type_damp_neighbor
) {
8267 union sockunion
*su
= output_arg
;
8269 if (ri
->peer
== NULL
8270 || ri
->peer
->su_remote
== NULL
8271 || !sockunion_same(ri
->peer
->su_remote
, su
))
8274 if (type
== bgp_show_type_cidr_only
) {
8275 uint32_t destination
;
8277 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8278 if (IN_CLASSC(destination
)
8279 && rn
->p
.prefixlen
== 24)
8281 if (IN_CLASSB(destination
)
8282 && rn
->p
.prefixlen
== 16)
8284 if (IN_CLASSA(destination
)
8285 && rn
->p
.prefixlen
== 8)
8288 if (type
== bgp_show_type_prefix_longer
) {
8289 struct prefix
*p
= output_arg
;
8291 if (!prefix_match(p
, &rn
->p
))
8294 if (type
== bgp_show_type_community_all
) {
8295 if (!ri
->attr
->community
)
8298 if (type
== bgp_show_type_community
) {
8299 struct community
*com
= output_arg
;
8301 if (!ri
->attr
->community
8302 || !community_match(ri
->attr
->community
,
8306 if (type
== bgp_show_type_community_exact
) {
8307 struct community
*com
= output_arg
;
8309 if (!ri
->attr
->community
8310 || !community_cmp(ri
->attr
->community
, com
))
8313 if (type
== bgp_show_type_community_list
) {
8314 struct community_list
*list
= output_arg
;
8316 if (!community_list_match(ri
->attr
->community
,
8320 if (type
== bgp_show_type_community_list_exact
) {
8321 struct community_list
*list
= output_arg
;
8323 if (!community_list_exact_match(
8324 ri
->attr
->community
, list
))
8327 if (type
== bgp_show_type_lcommunity
) {
8328 struct lcommunity
*lcom
= output_arg
;
8330 if (!ri
->attr
->lcommunity
8331 || !lcommunity_match(ri
->attr
->lcommunity
,
8335 if (type
== bgp_show_type_lcommunity_list
) {
8336 struct community_list
*list
= output_arg
;
8338 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8342 if (type
== bgp_show_type_lcommunity_all
) {
8343 if (!ri
->attr
->lcommunity
)
8346 if (type
== bgp_show_type_dampend_paths
8347 || type
== bgp_show_type_damp_neighbor
) {
8348 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8349 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8353 if (!use_json
&& header
) {
8354 vty_out(vty
, "BGP table version is %" PRIu64
8355 ", local router ID is %s, vrf id ",
8357 inet_ntoa(bgp
->router_id
));
8358 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8359 vty_out(vty
, "%s", VRFID_NONE_STR
);
8361 vty_out(vty
, "%u", bgp
->vrf_id
);
8363 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8364 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8365 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8366 if (type
== bgp_show_type_dampend_paths
8367 || type
== bgp_show_type_damp_neighbor
)
8368 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8369 else if (type
== bgp_show_type_flap_statistics
8370 || type
== bgp_show_type_flap_neighbor
)
8371 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8373 vty_out(vty
, BGP_SHOW_HEADER
);
8376 if (rd
!= NULL
&& !display
&& !output_count
) {
8379 "Route Distinguisher: %s\n",
8382 if (type
== bgp_show_type_dampend_paths
8383 || type
== bgp_show_type_damp_neighbor
)
8384 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8385 safi
, use_json
, json_paths
);
8386 else if (type
== bgp_show_type_flap_statistics
8387 || type
== bgp_show_type_flap_neighbor
)
8388 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8389 safi
, use_json
, json_paths
);
8391 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8402 sprintf(buf2
, "%s/%d",
8403 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8406 vty_out(vty
, "\"%s\": ", buf2
);
8408 vty_out(vty
, ",\"%s\": ", buf2
);
8411 json_object_to_json_string(json_paths
));
8412 json_object_free(json_paths
);
8419 output_count
+= *output_cum
;
8420 *output_cum
= output_count
;
8423 total_count
+= *total_cum
;
8424 *total_cum
= total_count
;
8428 json_object_free(json_paths
);
8430 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8434 for (i
= 0; i
< *json_header_depth
; ++i
)
8435 vty_out(vty
, " } ");
8439 /* No route is displayed */
8440 if (output_count
== 0) {
8441 if (type
== bgp_show_type_normal
)
8443 "No BGP prefixes displayed, %ld exist\n",
8447 "\nDisplayed %ld routes and %ld total paths\n",
8448 output_count
, total_count
);
8455 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8456 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8457 enum bgp_show_type type
, void *output_arg
,
8460 struct bgp_node
*rn
, *next
;
8461 unsigned long output_cum
= 0;
8462 unsigned long total_cum
= 0;
8463 unsigned long json_header_depth
= 0;
8466 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8468 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8469 next
= bgp_route_next(rn
);
8470 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8472 if (rn
->info
!= NULL
) {
8473 struct prefix_rd prd
;
8474 char rd
[RD_ADDRSTRLEN
];
8476 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8477 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8478 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8479 output_arg
, use_json
, rd
, next
== NULL
,
8480 &output_cum
, &total_cum
,
8481 &json_header_depth
);
8487 if (output_cum
== 0)
8488 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8492 "\nDisplayed %ld routes and %ld total paths\n",
8493 output_cum
, total_cum
);
8497 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8498 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8500 struct bgp_table
*table
;
8501 unsigned long json_header_depth
= 0;
8504 bgp
= bgp_get_default();
8509 vty_out(vty
, "No BGP process is configured\n");
8511 vty_out(vty
, "{}\n");
8515 table
= bgp
->rib
[afi
][safi
];
8516 /* use MPLS and ENCAP specific shows until they are merged */
8517 if (safi
== SAFI_MPLS_VPN
) {
8518 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8519 output_arg
, use_json
);
8522 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8523 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8524 output_arg
, use_json
,
8527 /* labeled-unicast routes live in the unicast table */
8528 else if (safi
== SAFI_LABELED_UNICAST
)
8529 safi
= SAFI_UNICAST
;
8531 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8532 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8535 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8536 safi_t safi
, uint8_t use_json
)
8538 struct listnode
*node
, *nnode
;
8543 vty_out(vty
, "{\n");
8545 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8548 vty_out(vty
, ",\n");
8552 vty_out(vty
, "\"%s\":",
8553 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8557 vty_out(vty
, "\nInstance %s:\n",
8558 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8562 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8567 vty_out(vty
, "}\n");
8570 /* Header of detailed BGP route information */
8571 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8572 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8573 afi_t afi
, safi_t safi
, json_object
*json
)
8575 struct bgp_info
*ri
;
8578 struct listnode
*node
, *nnode
;
8579 char buf1
[RD_ADDRSTRLEN
];
8580 char buf2
[INET6_ADDRSTRLEN
];
8581 char buf3
[EVPN_ROUTE_STRLEN
];
8582 char prefix_str
[BUFSIZ
];
8587 int no_advertise
= 0;
8590 int has_valid_label
= 0;
8591 mpls_label_t label
= 0;
8592 json_object
*json_adv_to
= NULL
;
8595 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8597 if (has_valid_label
)
8598 label
= label_pton(&rn
->local_label
);
8601 if (has_valid_label
)
8602 json_object_int_add(json
, "localLabel", label
);
8604 json_object_string_add(
8606 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8608 if (safi
== SAFI_EVPN
)
8609 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8610 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8613 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8614 buf3
, sizeof(buf3
)));
8616 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8617 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8618 ? prefix_rd2str(prd
, buf1
,
8621 safi
== SAFI_MPLS_VPN
? ":" : "",
8622 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8626 if (has_valid_label
)
8627 vty_out(vty
, "Local label: %d\n", label
);
8628 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8629 vty_out(vty
, "not allocated\n");
8632 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8634 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8636 if (ri
->extra
&& ri
->extra
->suppress
)
8638 if (ri
->attr
->community
!= NULL
) {
8639 if (community_include(ri
->attr
->community
,
8640 COMMUNITY_NO_ADVERTISE
))
8642 if (community_include(ri
->attr
->community
,
8643 COMMUNITY_NO_EXPORT
))
8645 if (community_include(ri
->attr
->community
,
8646 COMMUNITY_LOCAL_AS
))
8653 vty_out(vty
, "Paths: (%d available", count
);
8655 vty_out(vty
, ", best #%d", best
);
8656 if (safi
== SAFI_UNICAST
)
8657 vty_out(vty
, ", table %s",
8659 == BGP_INSTANCE_TYPE_DEFAULT
)
8660 ? "Default-IP-Routing-Table"
8663 vty_out(vty
, ", no best path");
8666 vty_out(vty
, ", not advertised to any peer");
8668 vty_out(vty
, ", not advertised to EBGP peer");
8670 vty_out(vty
, ", not advertised outside local AS");
8674 ", Advertisements suppressed by an aggregate.");
8675 vty_out(vty
, ")\n");
8678 /* If we are not using addpath then we can display Advertised to and
8680 * show what peers we advertised the bestpath to. If we are using
8682 * though then we must display Advertised to on a path-by-path basis. */
8683 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8684 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8685 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8686 if (json
&& !json_adv_to
)
8687 json_adv_to
= json_object_new_object();
8689 route_vty_out_advertised_to(
8691 " Advertised to non peer-group peers:\n ",
8698 json_object_object_add(json
, "advertisedTo",
8703 vty_out(vty
, " Not advertised to any peer");
8709 /* Display specified route of BGP table. */
8710 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8711 struct bgp_table
*rib
, const char *ip_str
,
8712 afi_t afi
, safi_t safi
,
8713 struct prefix_rd
*prd
, int prefix_check
,
8714 enum bgp_path_type pathtype
,
8720 struct prefix match
;
8721 struct bgp_node
*rn
;
8722 struct bgp_node
*rm
;
8723 struct bgp_info
*ri
;
8724 struct bgp_table
*table
;
8725 json_object
*json
= NULL
;
8726 json_object
*json_paths
= NULL
;
8728 /* Check IP address argument. */
8729 ret
= str2prefix(ip_str
, &match
);
8731 vty_out(vty
, "address is malformed\n");
8735 match
.family
= afi2family(afi
);
8738 json
= json_object_new_object();
8739 json_paths
= json_object_new_array();
8742 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8743 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8744 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8747 if ((table
= rn
->info
) == NULL
)
8752 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8756 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8757 bgp_unlock_node(rm
);
8761 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8763 route_vty_out_detail_header(
8765 (struct prefix_rd
*)&rn
->p
,
8766 AFI_IP
, safi
, json
);
8771 if (pathtype
== BGP_PATH_ALL
8772 || (pathtype
== BGP_PATH_BESTPATH
8773 && CHECK_FLAG(ri
->flags
,
8775 || (pathtype
== BGP_PATH_MULTIPATH
8776 && (CHECK_FLAG(ri
->flags
,
8778 || CHECK_FLAG(ri
->flags
,
8779 BGP_INFO_SELECTED
))))
8780 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8785 bgp_unlock_node(rm
);
8787 } else if (safi
== SAFI_FLOWSPEC
) {
8788 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
8789 &match
, prefix_check
,
8796 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8798 || rn
->p
.prefixlen
== match
.prefixlen
) {
8799 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8801 route_vty_out_detail_header(
8802 vty
, bgp
, rn
, NULL
, afi
,
8808 if (pathtype
== BGP_PATH_ALL
8809 || (pathtype
== BGP_PATH_BESTPATH
8813 || (pathtype
== BGP_PATH_MULTIPATH
8819 BGP_INFO_SELECTED
))))
8820 route_vty_out_detail(
8821 vty
, bgp
, &rn
->p
, ri
,
8822 afi
, safi
, json_paths
);
8826 bgp_unlock_node(rn
);
8832 json_object_object_add(json
, "paths", json_paths
);
8834 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8835 json
, JSON_C_TO_STRING_PRETTY
));
8836 json_object_free(json
);
8839 vty_out(vty
, "%% Network not in table\n");
8847 /* Display specified route of Main RIB */
8848 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8849 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8850 int prefix_check
, enum bgp_path_type pathtype
,
8854 bgp
= bgp_get_default();
8857 vty_out(vty
, "No BGP process is configured\n");
8859 vty_out(vty
, "{}\n");
8864 /* labeled-unicast routes live in the unicast table */
8865 if (safi
== SAFI_LABELED_UNICAST
)
8866 safi
= SAFI_UNICAST
;
8868 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8869 afi
, safi
, prd
, prefix_check
, pathtype
,
8873 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8874 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8877 struct lcommunity
*lcom
;
8883 b
= buffer_new(1024);
8884 for (i
= 0; i
< argc
; i
++) {
8886 buffer_putc(b
, ' ');
8888 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8890 buffer_putstr(b
, argv
[i
]->arg
);
8894 buffer_putc(b
, '\0');
8896 str
= buffer_getstr(b
);
8899 lcom
= lcommunity_str2com(str
);
8900 XFREE(MTYPE_TMP
, str
);
8902 vty_out(vty
, "%% Large-community malformed\n");
8906 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8910 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8911 const char *lcom
, afi_t afi
, safi_t safi
,
8914 struct community_list
*list
;
8916 list
= community_list_lookup(bgp_clist
, lcom
,
8917 LARGE_COMMUNITY_LIST_MASTER
);
8919 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8924 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8928 DEFUN (show_ip_bgp_large_community_list
,
8929 show_ip_bgp_large_community_list_cmd
,
8930 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8934 BGP_INSTANCE_HELP_STR
8936 BGP_SAFI_WITH_LABEL_HELP_STR
8937 "Display routes matching the large-community-list\n"
8938 "large-community-list number\n"
8939 "large-community-list name\n"
8943 afi_t afi
= AFI_IP6
;
8944 safi_t safi
= SAFI_UNICAST
;
8947 if (argv_find(argv
, argc
, "ip", &idx
))
8949 if (argv_find(argv
, argc
, "view", &idx
)
8950 || argv_find(argv
, argc
, "vrf", &idx
))
8951 vrf
= argv
[++idx
]->arg
;
8952 if (argv_find(argv
, argc
, "ipv4", &idx
)
8953 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8954 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8955 if (argv_find(argv
, argc
, "unicast", &idx
)
8956 || argv_find(argv
, argc
, "multicast", &idx
))
8957 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8960 int uj
= use_json(argc
, argv
);
8962 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8964 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8968 argv_find(argv
, argc
, "large-community-list", &idx
);
8969 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8972 DEFUN (show_ip_bgp_large_community
,
8973 show_ip_bgp_large_community_cmd
,
8974 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8978 BGP_INSTANCE_HELP_STR
8980 BGP_SAFI_WITH_LABEL_HELP_STR
8981 "Display routes matching the large-communities\n"
8982 "List of large-community numbers\n"
8986 afi_t afi
= AFI_IP6
;
8987 safi_t safi
= SAFI_UNICAST
;
8990 if (argv_find(argv
, argc
, "ip", &idx
))
8992 if (argv_find(argv
, argc
, "view", &idx
)
8993 || argv_find(argv
, argc
, "vrf", &idx
))
8994 vrf
= argv
[++idx
]->arg
;
8995 if (argv_find(argv
, argc
, "ipv4", &idx
)
8996 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8997 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8998 if (argv_find(argv
, argc
, "unicast", &idx
)
8999 || argv_find(argv
, argc
, "multicast", &idx
))
9000 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9003 int uj
= use_json(argc
, argv
);
9005 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9007 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9011 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9012 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9014 return bgp_show(vty
, bgp
, afi
, safi
,
9015 bgp_show_type_lcommunity_all
, NULL
, uj
);
9018 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9022 /* BGP route print out function without JSON */
9025 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9026 <dampening <parameters>\
9031 |community-list <(1-500)|WORD> [exact-match]\
9032 |A.B.C.D/M longer-prefixes\
9033 |X:X::X:X/M longer-prefixes\
9038 BGP_INSTANCE_HELP_STR
9040 BGP_SAFI_WITH_LABEL_HELP_STR
9041 "Display detailed information about dampening\n"
9042 "Display detail of configured dampening parameters\n"
9043 "Display routes matching the route-map\n"
9044 "A route-map to match on\n"
9045 "Display routes conforming to the prefix-list\n"
9046 "Prefix-list name\n"
9047 "Display routes conforming to the filter-list\n"
9048 "Regular expression access list name\n"
9049 "BGP RIB advertisement statistics\n"
9050 "Display routes matching the community-list\n"
9051 "community-list number\n"
9052 "community-list name\n"
9053 "Exact match of the communities\n"
9055 "Display route and more specific routes\n"
9057 "Display route and more specific routes\n")
9059 afi_t afi
= AFI_IP6
;
9060 safi_t safi
= SAFI_UNICAST
;
9061 int exact_match
= 0;
9062 struct bgp
*bgp
= NULL
;
9065 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9070 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9071 if (argv_find(argv
, argc
, "parameters", &idx
))
9072 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9075 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9076 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9077 safi
, bgp_show_type_prefix_list
);
9079 if (argv_find(argv
, argc
, "filter-list", &idx
))
9080 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9081 safi
, bgp_show_type_filter_list
);
9083 if (argv_find(argv
, argc
, "statistics", &idx
))
9084 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9086 if (argv_find(argv
, argc
, "route-map", &idx
))
9087 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9088 safi
, bgp_show_type_route_map
);
9090 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9091 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9092 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9094 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9095 exact_match
, afi
, safi
);
9098 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9099 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9100 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9102 bgp_show_type_prefix_longer
);
9107 /* BGP route print out function with JSON */
9108 DEFUN (show_ip_bgp_json
,
9109 show_ip_bgp_json_cmd
,
9110 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9113 |dampening <flap-statistics|dampened-paths>\
9114 |community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown>] [exact-match]\
9119 BGP_INSTANCE_HELP_STR
9121 BGP_SAFI_WITH_LABEL_HELP_STR
9122 "Display only routes with non-natural netmasks\n"
9123 "Display detailed information about dampening\n"
9124 "Display flap statistics of routes\n"
9125 "Display paths suppressed due to dampening\n"
9126 "Display routes matching the communities\n"
9128 "Do not send outside local AS (well-known community)\n"
9129 "Do not advertise to any peer (well-known community)\n"
9130 "Do not export to next AS (well-known community)\n"
9131 "Graceful shutdown (well-known community)\n"
9132 "Exact match of the communities\n"
9135 afi_t afi
= AFI_IP6
;
9136 safi_t safi
= SAFI_UNICAST
;
9137 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9138 struct bgp
*bgp
= NULL
;
9140 int idx_community_type
= 0;
9141 int exact_match
= 0;
9143 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9148 int uj
= use_json(argc
, argv
);
9152 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9153 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9156 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9157 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9158 return bgp_show(vty
, bgp
, afi
, safi
,
9159 bgp_show_type_dampend_paths
, NULL
, uj
);
9160 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9161 return bgp_show(vty
, bgp
, afi
, safi
,
9162 bgp_show_type_flap_statistics
, NULL
,
9166 if (argv_find(argv
, argc
, "community", &idx
)) {
9168 /* show a specific community */
9169 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
) ||
9170 argv_find(argv
, argc
, "no-advertise",
9171 &idx_community_type
) ||
9172 argv_find(argv
, argc
, "no-export",
9173 &idx_community_type
) ||
9174 argv_find(argv
, argc
, "graceful-shutdown",
9175 &idx_community_type
) ||
9176 argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9177 if (argv_find(argv
, argc
, "exact-match", &idx
))
9180 return (bgp_show_community(vty
, bgp
,
9181 argv
[idx_community_type
]->arg
,
9182 exact_match
, afi
, safi
, uj
));
9185 /* show all communities */
9186 return (bgp_show(vty
, bgp
, afi
, safi
,
9187 bgp_show_type_community_all
, NULL
,
9192 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9195 DEFUN (show_ip_bgp_route
,
9196 show_ip_bgp_route_cmd
,
9197 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9198 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9202 BGP_INSTANCE_HELP_STR
9204 BGP_SAFI_WITH_LABEL_HELP_STR
9205 "Network in the BGP routing table to display\n"
9207 "Network in the BGP routing table to display\n"
9209 "Display only the bestpath\n"
9210 "Display only multipaths\n"
9213 int prefix_check
= 0;
9215 afi_t afi
= AFI_IP6
;
9216 safi_t safi
= SAFI_UNICAST
;
9217 char *prefix
= NULL
;
9218 struct bgp
*bgp
= NULL
;
9219 enum bgp_path_type path_type
;
9220 uint8_t uj
= use_json(argc
, argv
);
9224 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9231 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9235 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9236 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9237 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9239 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9240 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9243 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9244 && afi
!= AFI_IP6
) {
9246 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9249 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9252 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9256 prefix
= argv
[idx
]->arg
;
9258 /* [<bestpath|multipath>] */
9259 if (argv_find(argv
, argc
, "bestpath", &idx
))
9260 path_type
= BGP_PATH_BESTPATH
;
9261 else if (argv_find(argv
, argc
, "multipath", &idx
))
9262 path_type
= BGP_PATH_MULTIPATH
;
9264 path_type
= BGP_PATH_ALL
;
9266 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9270 DEFUN (show_ip_bgp_regexp
,
9271 show_ip_bgp_regexp_cmd
,
9272 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9276 BGP_INSTANCE_HELP_STR
9278 BGP_SAFI_WITH_LABEL_HELP_STR
9279 "Display routes matching the AS path regular expression\n"
9280 "A regular-expression to match the BGP AS paths\n")
9282 afi_t afi
= AFI_IP6
;
9283 safi_t safi
= SAFI_UNICAST
;
9284 struct bgp
*bgp
= NULL
;
9287 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9292 // get index of regex
9293 argv_find(argv
, argc
, "regexp", &idx
);
9296 char *regstr
= argv_concat(argv
, argc
, idx
);
9297 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9298 bgp_show_type_regexp
);
9299 XFREE(MTYPE_TMP
, regstr
);
9303 DEFUN (show_ip_bgp_instance_all
,
9304 show_ip_bgp_instance_all_cmd
,
9305 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9309 BGP_INSTANCE_ALL_HELP_STR
9311 BGP_SAFI_WITH_LABEL_HELP_STR
9315 safi_t safi
= SAFI_UNICAST
;
9316 struct bgp
*bgp
= NULL
;
9319 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9324 int uj
= use_json(argc
, argv
);
9328 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9332 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9333 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9338 regex
= bgp_regcomp(regstr
);
9340 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9344 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9345 bgp_regex_free(regex
);
9349 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9350 const char *prefix_list_str
, afi_t afi
,
9351 safi_t safi
, enum bgp_show_type type
)
9353 struct prefix_list
*plist
;
9355 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9356 if (plist
== NULL
) {
9357 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9362 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9365 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9366 const char *filter
, afi_t afi
, safi_t safi
,
9367 enum bgp_show_type type
)
9369 struct as_list
*as_list
;
9371 as_list
= as_list_lookup(filter
);
9372 if (as_list
== NULL
) {
9373 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9378 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9381 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9382 const char *rmap_str
, afi_t afi
, safi_t safi
,
9383 enum bgp_show_type type
)
9385 struct route_map
*rmap
;
9387 rmap
= route_map_lookup_by_name(rmap_str
);
9389 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9393 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9396 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9397 const char *comstr
, int exact
, afi_t afi
,
9398 safi_t safi
, uint8_t use_json
)
9400 struct community
*com
;
9403 com
= community_str2com(comstr
);
9405 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9409 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9410 (exact
? bgp_show_type_community_exact
9411 : bgp_show_type_community
),
9413 community_free(com
);
9418 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9419 const char *com
, int exact
, afi_t afi
,
9422 struct community_list
*list
;
9424 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9426 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9430 return bgp_show(vty
, bgp
, afi
, safi
,
9431 (exact
? bgp_show_type_community_list_exact
9432 : bgp_show_type_community_list
),
9436 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9437 const char *prefix
, afi_t afi
, safi_t safi
,
9438 enum bgp_show_type type
)
9445 ret
= str2prefix(prefix
, p
);
9447 vty_out(vty
, "%% Malformed Prefix\n");
9451 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9456 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9457 const char *ip_str
, uint8_t use_json
)
9463 /* Get peer sockunion. */
9464 ret
= str2sockunion(ip_str
, &su
);
9466 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9468 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9472 json_object
*json_no
= NULL
;
9473 json_no
= json_object_new_object();
9474 json_object_string_add(
9476 "malformedAddressOrName",
9478 vty_out(vty
, "%s\n",
9479 json_object_to_json_string_ext(
9481 JSON_C_TO_STRING_PRETTY
));
9482 json_object_free(json_no
);
9485 "%% Malformed address or name: %s\n",
9493 /* Peer structure lookup. */
9494 peer
= peer_lookup(bgp
, &su
);
9497 json_object
*json_no
= NULL
;
9498 json_no
= json_object_new_object();
9499 json_object_string_add(json_no
, "warning",
9500 "No such neighbor in this view/vrf");
9501 vty_out(vty
, "%s\n",
9502 json_object_to_json_string_ext(
9503 json_no
, JSON_C_TO_STRING_PRETTY
));
9504 json_object_free(json_no
);
9506 vty_out(vty
, "No such neighbor in this view/vrf\n");
9514 BGP_STATS_MAXBITLEN
= 0,
9518 BGP_STATS_UNAGGREGATEABLE
,
9519 BGP_STATS_MAX_AGGREGATEABLE
,
9520 BGP_STATS_AGGREGATES
,
9522 BGP_STATS_ASPATH_COUNT
,
9523 BGP_STATS_ASPATH_MAXHOPS
,
9524 BGP_STATS_ASPATH_TOTHOPS
,
9525 BGP_STATS_ASPATH_MAXSIZE
,
9526 BGP_STATS_ASPATH_TOTSIZE
,
9527 BGP_STATS_ASN_HIGHEST
,
9531 static const char *table_stats_strs
[] = {
9532 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9533 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9534 [BGP_STATS_RIB
] = "Total Advertisements",
9535 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9536 [BGP_STATS_MAX_AGGREGATEABLE
] =
9537 "Maximum aggregateable prefixes",
9538 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9539 [BGP_STATS_SPACE
] = "Address space advertised",
9540 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9541 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9542 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9543 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9544 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9545 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9546 [BGP_STATS_MAX
] = NULL
,
9549 struct bgp_table_stats
{
9550 struct bgp_table
*table
;
9551 unsigned long long counts
[BGP_STATS_MAX
];
9556 #define TALLY_SIGFIG 100000
9557 static unsigned long
9558 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9560 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9561 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9562 unsigned long ret
= newtot
/ count
;
9564 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9571 static int bgp_table_stats_walker(struct thread
*t
)
9573 struct bgp_node
*rn
;
9574 struct bgp_node
*top
;
9575 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9576 unsigned int space
= 0;
9578 if (!(top
= bgp_table_top(ts
->table
)))
9581 switch (top
->p
.family
) {
9583 space
= IPV4_MAX_BITLEN
;
9586 space
= IPV6_MAX_BITLEN
;
9590 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9592 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9593 struct bgp_info
*ri
;
9594 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9595 unsigned int rinum
= 0;
9603 ts
->counts
[BGP_STATS_PREFIXES
]++;
9604 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9607 ts
->counts
[BGP_STATS_AVGPLEN
]
9608 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9609 ts
->counts
[BGP_STATS_AVGPLEN
],
9613 /* check if the prefix is included by any other announcements */
9614 while (prn
&& !prn
->info
)
9615 prn
= bgp_node_parent_nolock(prn
);
9617 if (prn
== NULL
|| prn
== top
) {
9618 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9619 /* announced address space */
9622 pow(2.0, space
- rn
->p
.prefixlen
);
9623 } else if (prn
->info
)
9624 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9626 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9628 ts
->counts
[BGP_STATS_RIB
]++;
9631 && (CHECK_FLAG(ri
->attr
->flag
,
9633 BGP_ATTR_ATOMIC_AGGREGATE
))))
9634 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9637 if (ri
->attr
&& ri
->attr
->aspath
) {
9639 aspath_count_hops(ri
->attr
->aspath
);
9641 aspath_size(ri
->attr
->aspath
);
9642 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9644 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9646 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9647 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9650 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9651 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9654 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9655 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9657 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9658 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9659 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9661 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9662 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9663 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9666 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9667 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9675 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9678 struct bgp_table_stats ts
;
9681 if (!bgp
->rib
[afi
][safi
]) {
9682 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9687 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9689 /* labeled-unicast routes live in the unicast table */
9690 if (safi
== SAFI_LABELED_UNICAST
)
9691 safi
= SAFI_UNICAST
;
9693 memset(&ts
, 0, sizeof(ts
));
9694 ts
.table
= bgp
->rib
[afi
][safi
];
9695 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9697 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9698 if (!table_stats_strs
[i
])
9703 case BGP_STATS_ASPATH_AVGHOPS
:
9704 case BGP_STATS_ASPATH_AVGSIZE
:
9705 case BGP_STATS_AVGPLEN
:
9706 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9707 vty_out (vty
, "%12.2f",
9708 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9711 case BGP_STATS_ASPATH_TOTHOPS
:
9712 case BGP_STATS_ASPATH_TOTSIZE
:
9713 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9714 vty_out(vty
, "%12.2f",
9716 ? (float)ts
.counts
[i
]
9718 [BGP_STATS_ASPATH_COUNT
]
9721 case BGP_STATS_TOTPLEN
:
9722 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9723 vty_out(vty
, "%12.2f",
9725 ? (float)ts
.counts
[i
]
9727 [BGP_STATS_PREFIXES
]
9730 case BGP_STATS_SPACE
:
9731 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9732 vty_out(vty
, "%12g\n", ts
.total_space
);
9734 if (afi
== AFI_IP6
) {
9735 vty_out(vty
, "%30s: ", "/32 equivalent ");
9736 vty_out(vty
, "%12g\n",
9737 ts
.total_space
* pow(2.0, -128 + 32));
9738 vty_out(vty
, "%30s: ", "/48 equivalent ");
9739 vty_out(vty
, "%12g\n",
9740 ts
.total_space
* pow(2.0, -128 + 48));
9742 vty_out(vty
, "%30s: ", "% announced ");
9743 vty_out(vty
, "%12.2f\n",
9744 ts
.total_space
* 100. * pow(2.0, -32));
9745 vty_out(vty
, "%30s: ", "/8 equivalent ");
9746 vty_out(vty
, "%12.2f\n",
9747 ts
.total_space
* pow(2.0, -32 + 8));
9748 vty_out(vty
, "%30s: ", "/24 equivalent ");
9749 vty_out(vty
, "%12.2f\n",
9750 ts
.total_space
* pow(2.0, -32 + 24));
9754 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9755 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9772 PCOUNT_PFCNT
, /* the figure we display to users */
9776 static const char *pcount_strs
[] = {
9777 [PCOUNT_ADJ_IN
] = "Adj-in",
9778 [PCOUNT_DAMPED
] = "Damped",
9779 [PCOUNT_REMOVED
] = "Removed",
9780 [PCOUNT_HISTORY
] = "History",
9781 [PCOUNT_STALE
] = "Stale",
9782 [PCOUNT_VALID
] = "Valid",
9783 [PCOUNT_ALL
] = "All RIB",
9784 [PCOUNT_COUNTED
] = "PfxCt counted",
9785 [PCOUNT_PFCNT
] = "Useable",
9786 [PCOUNT_MAX
] = NULL
,
9789 struct peer_pcounts
{
9790 unsigned int count
[PCOUNT_MAX
];
9791 const struct peer
*peer
;
9792 const struct bgp_table
*table
;
9795 static int bgp_peer_count_walker(struct thread
*t
)
9797 struct bgp_node
*rn
;
9798 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9799 const struct peer
*peer
= pc
->peer
;
9801 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9802 struct bgp_adj_in
*ain
;
9803 struct bgp_info
*ri
;
9805 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9806 if (ain
->peer
== peer
)
9807 pc
->count
[PCOUNT_ADJ_IN
]++;
9809 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9810 char buf
[SU_ADDRSTRLEN
];
9812 if (ri
->peer
!= peer
)
9815 pc
->count
[PCOUNT_ALL
]++;
9817 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9818 pc
->count
[PCOUNT_DAMPED
]++;
9819 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9820 pc
->count
[PCOUNT_HISTORY
]++;
9821 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9822 pc
->count
[PCOUNT_REMOVED
]++;
9823 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9824 pc
->count
[PCOUNT_STALE
]++;
9825 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9826 pc
->count
[PCOUNT_VALID
]++;
9827 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9828 pc
->count
[PCOUNT_PFCNT
]++;
9830 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9831 pc
->count
[PCOUNT_COUNTED
]++;
9832 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9834 "%s [pcount] %s/%d is counted but flags 0x%x",
9836 inet_ntop(rn
->p
.family
,
9837 &rn
->p
.u
.prefix
, buf
,
9839 rn
->p
.prefixlen
, ri
->flags
);
9841 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9843 "%s [pcount] %s/%d not counted but flags 0x%x",
9845 inet_ntop(rn
->p
.family
,
9846 &rn
->p
.u
.prefix
, buf
,
9848 rn
->p
.prefixlen
, ri
->flags
);
9855 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9856 safi_t safi
, uint8_t use_json
)
9858 struct peer_pcounts pcounts
= {.peer
= peer
};
9860 json_object
*json
= NULL
;
9861 json_object
*json_loop
= NULL
;
9864 json
= json_object_new_object();
9865 json_loop
= json_object_new_object();
9868 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9869 || !peer
->bgp
->rib
[afi
][safi
]) {
9871 json_object_string_add(
9873 "No such neighbor or address family");
9874 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9875 json_object_free(json
);
9877 vty_out(vty
, "%% No such neighbor or address family\n");
9882 memset(&pcounts
, 0, sizeof(pcounts
));
9883 pcounts
.peer
= peer
;
9884 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9886 /* in-place call via thread subsystem so as to record execution time
9887 * stats for the thread-walk (i.e. ensure this can't be blamed on
9888 * on just vty_read()).
9890 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9893 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9894 json_object_string_add(json
, "multiProtocol",
9895 afi_safi_print(afi
, safi
));
9896 json_object_int_add(json
, "pfxCounter",
9897 peer
->pcount
[afi
][safi
]);
9899 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9900 json_object_int_add(json_loop
, pcount_strs
[i
],
9903 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9905 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9906 json_object_string_add(json
, "pfxctDriftFor",
9908 json_object_string_add(
9909 json
, "recommended",
9910 "Please report this bug, with the above command output");
9912 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9913 json
, JSON_C_TO_STRING_PRETTY
));
9914 json_object_free(json
);
9918 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9919 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9920 peer
->hostname
, peer
->host
,
9921 afi_safi_print(afi
, safi
));
9923 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9924 afi_safi_print(afi
, safi
));
9927 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9928 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9930 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9931 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9934 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9935 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9937 "Please report this bug, with the above command output\n");
9944 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9945 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9946 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9947 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9951 BGP_INSTANCE_HELP_STR
9954 "Detailed information on TCP and BGP neighbor connections\n"
9955 "Neighbor to display information about\n"
9956 "Neighbor to display information about\n"
9957 "Neighbor on BGP configured interface\n"
9958 "Display detailed prefix count information\n"
9961 afi_t afi
= AFI_IP6
;
9962 safi_t safi
= SAFI_UNICAST
;
9965 struct bgp
*bgp
= NULL
;
9967 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9972 int uj
= use_json(argc
, argv
);
9976 argv_find(argv
, argc
, "neighbors", &idx
);
9977 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9981 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9984 #ifdef KEEP_OLD_VPN_COMMANDS
9985 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9986 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9987 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9992 "Display information about all VPNv4 NLRIs\n"
9993 "Detailed information on TCP and BGP neighbor connections\n"
9994 "Neighbor to display information about\n"
9995 "Neighbor to display information about\n"
9996 "Neighbor on BGP configured interface\n"
9997 "Display detailed prefix count information\n"
10002 uint8_t uj
= use_json(argc
, argv
);
10004 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10006 return CMD_WARNING
;
10008 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10011 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10012 show_ip_bgp_vpn_all_route_prefix_cmd
,
10013 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10018 "Display information about all VPNv4 NLRIs\n"
10019 "Network in the BGP routing table to display\n"
10020 "Network in the BGP routing table to display\n"
10024 char *network
= NULL
;
10025 struct bgp
*bgp
= bgp_get_default();
10027 vty_out(vty
, "Can't find default instance\n");
10028 return CMD_WARNING
;
10031 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10032 network
= argv
[idx
]->arg
;
10033 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10034 network
= argv
[idx
]->arg
;
10036 vty_out(vty
, "Unable to figure out Network\n");
10037 return CMD_WARNING
;
10040 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10041 BGP_PATH_ALL
, use_json(argc
, argv
));
10043 #endif /* KEEP_OLD_VPN_COMMANDS */
10045 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10046 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10047 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10053 "Display information about all EVPN NLRIs\n"
10054 "Network in the BGP routing table to display\n"
10055 "Network in the BGP routing table to display\n"
10059 char *network
= NULL
;
10061 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10062 network
= argv
[idx
]->arg
;
10063 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10064 network
= argv
[idx
]->arg
;
10066 vty_out(vty
, "Unable to figure out Network\n");
10067 return CMD_WARNING
;
10069 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10070 BGP_PATH_ALL
, use_json(argc
, argv
));
10073 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10074 safi_t safi
, enum bgp_show_adj_route_type type
,
10075 const char *rmap_name
, uint8_t use_json
,
10078 struct bgp_table
*table
;
10079 struct bgp_adj_in
*ain
;
10080 struct bgp_adj_out
*adj
;
10081 unsigned long output_count
;
10082 unsigned long filtered_count
;
10083 struct bgp_node
*rn
;
10089 struct update_subgroup
*subgrp
;
10090 json_object
*json_scode
= NULL
;
10091 json_object
*json_ocode
= NULL
;
10092 json_object
*json_ar
= NULL
;
10093 struct peer_af
*paf
;
10094 bool route_filtered
;
10097 json_scode
= json_object_new_object();
10098 json_ocode
= json_object_new_object();
10099 json_ar
= json_object_new_object();
10101 json_object_string_add(json_scode
, "suppressed", "s");
10102 json_object_string_add(json_scode
, "damped", "d");
10103 json_object_string_add(json_scode
, "history", "h");
10104 json_object_string_add(json_scode
, "valid", "*");
10105 json_object_string_add(json_scode
, "best", ">");
10106 json_object_string_add(json_scode
, "multipath", "=");
10107 json_object_string_add(json_scode
, "internal", "i");
10108 json_object_string_add(json_scode
, "ribFailure", "r");
10109 json_object_string_add(json_scode
, "stale", "S");
10110 json_object_string_add(json_scode
, "removed", "R");
10112 json_object_string_add(json_ocode
, "igp", "i");
10113 json_object_string_add(json_ocode
, "egp", "e");
10114 json_object_string_add(json_ocode
, "incomplete", "?");
10121 json_object_string_add(json
, "alert", "no BGP");
10122 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10123 json_object_free(json
);
10125 vty_out(vty
, "%% No bgp\n");
10129 table
= bgp
->rib
[afi
][safi
];
10131 output_count
= filtered_count
= 0;
10132 subgrp
= peer_subgroup(peer
, afi
, safi
);
10134 if (type
== bgp_show_adj_route_advertised
&& subgrp
10135 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10137 json_object_int_add(json
, "bgpTableVersion",
10139 json_object_string_add(json
, "bgpLocalRouterId",
10140 inet_ntoa(bgp
->router_id
));
10141 json_object_object_add(json
, "bgpStatusCodes",
10143 json_object_object_add(json
, "bgpOriginCodes",
10145 json_object_string_add(
10146 json
, "bgpOriginatingDefaultNetwork",
10147 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10149 vty_out(vty
, "BGP table version is %" PRIu64
10150 ", local router ID is %s, vrf id ",
10151 table
->version
, inet_ntoa(bgp
->router_id
));
10152 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10153 vty_out(vty
, "%s", VRFID_NONE_STR
);
10155 vty_out(vty
, "%u", bgp
->vrf_id
);
10156 vty_out(vty
, "\n");
10157 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10158 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10159 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10161 vty_out(vty
, "Originating default network %s\n\n",
10162 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10167 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10168 if (type
== bgp_show_adj_route_received
10169 || type
== bgp_show_adj_route_filtered
) {
10170 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10171 if (ain
->peer
!= peer
|| !ain
->attr
)
10176 json_object_int_add(
10177 json
, "bgpTableVersion",
10179 json_object_string_add(
10181 "bgpLocalRouterId",
10184 json_object_object_add(
10185 json
, "bgpStatusCodes",
10187 json_object_object_add(
10188 json
, "bgpOriginCodes",
10192 "BGP table version is 0, local router ID is %s, vrf id ",
10195 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10201 vty_out(vty
, "\n");
10203 BGP_SHOW_SCODE_HEADER
);
10205 BGP_SHOW_NCODE_HEADER
);
10207 BGP_SHOW_OCODE_HEADER
);
10213 vty_out(vty
, BGP_SHOW_HEADER
);
10217 bgp_attr_dup(&attr
, ain
->attr
);
10218 route_filtered
= false;
10220 /* Filter prefix using distribute list,
10221 * filter list or prefix list
10223 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10224 safi
)) == FILTER_DENY
)
10225 route_filtered
= true;
10227 /* Filter prefix using route-map */
10228 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10229 afi
, safi
, rmap_name
);
10231 if (type
== bgp_show_adj_route_filtered
&&
10232 !route_filtered
&& ret
!= RMAP_DENY
) {
10233 bgp_attr_undup(&attr
, ain
->attr
);
10237 if (type
== bgp_show_adj_route_received
&&
10238 (route_filtered
|| ret
== RMAP_DENY
))
10241 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10242 use_json
, json_ar
);
10243 bgp_attr_undup(&attr
, ain
->attr
);
10246 } else if (type
== bgp_show_adj_route_advertised
) {
10247 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10248 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10249 if (paf
->peer
!= peer
|| !adj
->attr
)
10254 json_object_int_add(
10258 json_object_string_add(
10260 "bgpLocalRouterId",
10263 json_object_object_add(
10267 json_object_object_add(
10273 "BGP table version is %" PRIu64
10274 ", local router ID is %s, vrf id ",
10287 vty_out(vty
, "\n");
10289 BGP_SHOW_SCODE_HEADER
);
10291 BGP_SHOW_NCODE_HEADER
);
10293 BGP_SHOW_OCODE_HEADER
);
10304 bgp_attr_dup(&attr
, adj
->attr
);
10305 ret
= bgp_output_modifier(
10306 peer
, &rn
->p
, &attr
, afi
, safi
,
10309 if (ret
!= RMAP_DENY
) {
10310 route_vty_out_tmp(vty
, &rn
->p
,
10319 bgp_attr_undup(&attr
, adj
->attr
);
10325 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10326 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10327 json_object_int_add(json
, "filteredPrefixCounter",
10330 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10331 json
, JSON_C_TO_STRING_PRETTY
));
10332 json_object_free(json
);
10333 } else if (output_count
> 0) {
10334 if (filtered_count
> 0)
10336 "\nTotal number of prefixes %ld (%ld filtered)\n",
10337 output_count
, filtered_count
);
10339 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10344 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10345 safi_t safi
, enum bgp_show_adj_route_type type
,
10346 const char *rmap_name
, uint8_t use_json
)
10348 json_object
*json
= NULL
;
10351 json
= json_object_new_object();
10353 /* labeled-unicast routes live in the unicast table */
10354 if (safi
== SAFI_LABELED_UNICAST
)
10355 safi
= SAFI_UNICAST
;
10357 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10359 json_object_string_add(
10361 "No such neighbor or address family");
10362 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10363 json_object_free(json
);
10365 vty_out(vty
, "%% No such neighbor or address family\n");
10367 return CMD_WARNING
;
10370 if ((type
== bgp_show_adj_route_received
10371 || type
== bgp_show_adj_route_filtered
)
10372 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10373 PEER_FLAG_SOFT_RECONFIG
)) {
10375 json_object_string_add(
10377 "Inbound soft reconfiguration not enabled");
10378 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10379 json_object_free(json
);
10382 "%% Inbound soft reconfiguration not enabled\n");
10384 return CMD_WARNING
;
10387 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10389 return CMD_SUCCESS
;
10392 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10393 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10394 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10395 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10399 BGP_INSTANCE_HELP_STR
10401 BGP_SAFI_WITH_LABEL_HELP_STR
10402 "Detailed information on TCP and BGP neighbor connections\n"
10403 "Neighbor to display information about\n"
10404 "Neighbor to display information about\n"
10405 "Neighbor on BGP configured interface\n"
10406 "Display the routes advertised to a BGP neighbor\n"
10407 "Display the received routes from neighbor\n"
10408 "Display the filtered routes received from neighbor\n"
10409 "Route-map to modify the attributes\n"
10410 "Name of the route map\n"
10413 afi_t afi
= AFI_IP6
;
10414 safi_t safi
= SAFI_UNICAST
;
10415 char *rmap_name
= NULL
;
10416 char *peerstr
= NULL
;
10417 struct bgp
*bgp
= NULL
;
10419 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10422 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10425 return CMD_WARNING
;
10427 int uj
= use_json(argc
, argv
);
10432 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10433 argv_find(argv
, argc
, "neighbors", &idx
);
10434 peerstr
= argv
[++idx
]->arg
;
10436 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10438 return CMD_WARNING
;
10440 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10441 type
= bgp_show_adj_route_advertised
;
10442 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10443 type
= bgp_show_adj_route_received
;
10444 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10445 type
= bgp_show_adj_route_filtered
;
10447 if (argv_find(argv
, argc
, "route-map", &idx
))
10448 rmap_name
= argv
[++idx
]->arg
;
10450 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10453 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10454 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10455 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10461 "Address Family modifier\n"
10462 "Detailed information on TCP and BGP neighbor connections\n"
10463 "Neighbor to display information about\n"
10464 "Neighbor to display information about\n"
10465 "Neighbor on BGP configured interface\n"
10466 "Display information received from a BGP neighbor\n"
10467 "Display the prefixlist filter\n"
10470 afi_t afi
= AFI_IP6
;
10471 safi_t safi
= SAFI_UNICAST
;
10472 char *peerstr
= NULL
;
10475 union sockunion su
;
10481 /* show [ip] bgp */
10482 if (argv_find(argv
, argc
, "ip", &idx
))
10484 /* [<ipv4|ipv6> [unicast]] */
10485 if (argv_find(argv
, argc
, "ipv4", &idx
))
10487 if (argv_find(argv
, argc
, "ipv6", &idx
))
10489 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10490 argv_find(argv
, argc
, "neighbors", &idx
);
10491 peerstr
= argv
[++idx
]->arg
;
10493 uint8_t uj
= use_json(argc
, argv
);
10495 ret
= str2sockunion(peerstr
, &su
);
10497 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10500 vty_out(vty
, "{}\n");
10503 "%% Malformed address or name: %s\n",
10505 return CMD_WARNING
;
10508 peer
= peer_lookup(NULL
, &su
);
10511 vty_out(vty
, "{}\n");
10513 vty_out(vty
, "No peer\n");
10514 return CMD_WARNING
;
10518 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10519 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10522 vty_out(vty
, "Address Family: %s\n",
10523 afi_safi_print(afi
, safi
));
10524 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10527 vty_out(vty
, "{}\n");
10529 vty_out(vty
, "No functional output\n");
10532 return CMD_SUCCESS
;
10535 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10536 afi_t afi
, safi_t safi
,
10537 enum bgp_show_type type
, uint8_t use_json
)
10539 /* labeled-unicast routes live in the unicast table */
10540 if (safi
== SAFI_LABELED_UNICAST
)
10541 safi
= SAFI_UNICAST
;
10543 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10545 json_object
*json_no
= NULL
;
10546 json_no
= json_object_new_object();
10547 json_object_string_add(
10548 json_no
, "warning",
10549 "No such neighbor or address family");
10550 vty_out(vty
, "%s\n",
10551 json_object_to_json_string(json_no
));
10552 json_object_free(json_no
);
10554 vty_out(vty
, "%% No such neighbor or address family\n");
10555 return CMD_WARNING
;
10558 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10561 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10562 show_ip_bgp_flowspec_routes_detailed_cmd
,
10563 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10567 BGP_INSTANCE_HELP_STR
10570 "Detailed information on flowspec entries\n"
10573 afi_t afi
= AFI_IP
;
10574 safi_t safi
= SAFI_UNICAST
;
10575 struct bgp
*bgp
= NULL
;
10578 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10581 return CMD_WARNING
;
10583 return bgp_show(vty
, bgp
, afi
, safi
,
10584 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10587 DEFUN (show_ip_bgp_neighbor_routes
,
10588 show_ip_bgp_neighbor_routes_cmd
,
10589 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10590 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10594 BGP_INSTANCE_HELP_STR
10596 BGP_SAFI_WITH_LABEL_HELP_STR
10597 "Detailed information on TCP and BGP neighbor connections\n"
10598 "Neighbor to display information about\n"
10599 "Neighbor to display information about\n"
10600 "Neighbor on BGP configured interface\n"
10601 "Display flap statistics of the routes learned from neighbor\n"
10602 "Display the dampened routes received from neighbor\n"
10603 "Display routes learned from neighbor\n"
10606 char *peerstr
= NULL
;
10607 struct bgp
*bgp
= NULL
;
10608 afi_t afi
= AFI_IP6
;
10609 safi_t safi
= SAFI_UNICAST
;
10611 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10615 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10618 return CMD_WARNING
;
10620 int uj
= use_json(argc
, argv
);
10624 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10625 argv_find(argv
, argc
, "neighbors", &idx
);
10626 peerstr
= argv
[++idx
]->arg
;
10628 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10630 return CMD_WARNING
;
10632 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10633 sh_type
= bgp_show_type_flap_neighbor
;
10634 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10635 sh_type
= bgp_show_type_damp_neighbor
;
10636 else if (argv_find(argv
, argc
, "routes", &idx
))
10637 sh_type
= bgp_show_type_neighbor
;
10639 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10642 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10644 struct bgp_distance
{
10645 /* Distance value for the IP source prefix. */
10648 /* Name of the access-list to be matched. */
10652 DEFUN (show_bgp_afi_vpn_rd_route
,
10653 show_bgp_afi_vpn_rd_route_cmd
,
10654 "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]",
10658 "Address Family modifier\n"
10659 "Display information for a route distinguisher\n"
10660 "Route Distinguisher\n"
10661 "Network in the BGP routing table to display\n"
10662 "Network in the BGP routing table to display\n"
10666 struct prefix_rd prd
;
10667 afi_t afi
= AFI_MAX
;
10670 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10671 vty_out(vty
, "%% Malformed Address Family\n");
10672 return CMD_WARNING
;
10675 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10677 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10678 return CMD_WARNING
;
10681 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10682 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10685 static struct bgp_distance
*bgp_distance_new(void)
10687 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10690 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10692 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10695 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10696 const char *ip_str
, const char *access_list_str
)
10703 struct bgp_node
*rn
;
10704 struct bgp_distance
*bdistance
;
10706 afi
= bgp_node_afi(vty
);
10707 safi
= bgp_node_safi(vty
);
10709 ret
= str2prefix(ip_str
, &p
);
10711 vty_out(vty
, "Malformed prefix\n");
10712 return CMD_WARNING_CONFIG_FAILED
;
10715 distance
= atoi(distance_str
);
10717 /* Get BGP distance node. */
10718 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10720 bdistance
= rn
->info
;
10721 bgp_unlock_node(rn
);
10723 bdistance
= bgp_distance_new();
10724 rn
->info
= bdistance
;
10727 /* Set distance value. */
10728 bdistance
->distance
= distance
;
10730 /* Reset access-list configuration. */
10731 if (bdistance
->access_list
) {
10732 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10733 bdistance
->access_list
= NULL
;
10735 if (access_list_str
)
10736 bdistance
->access_list
=
10737 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10739 return CMD_SUCCESS
;
10742 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10743 const char *ip_str
, const char *access_list_str
)
10750 struct bgp_node
*rn
;
10751 struct bgp_distance
*bdistance
;
10753 afi
= bgp_node_afi(vty
);
10754 safi
= bgp_node_safi(vty
);
10756 ret
= str2prefix(ip_str
, &p
);
10758 vty_out(vty
, "Malformed prefix\n");
10759 return CMD_WARNING_CONFIG_FAILED
;
10762 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10763 (struct prefix
*)&p
);
10765 vty_out(vty
, "Can't find specified prefix\n");
10766 return CMD_WARNING_CONFIG_FAILED
;
10769 bdistance
= rn
->info
;
10770 distance
= atoi(distance_str
);
10772 if (bdistance
->distance
!= distance
) {
10773 vty_out(vty
, "Distance does not match configured\n");
10774 return CMD_WARNING_CONFIG_FAILED
;
10777 if (bdistance
->access_list
)
10778 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10779 bgp_distance_free(bdistance
);
10782 bgp_unlock_node(rn
);
10783 bgp_unlock_node(rn
);
10785 return CMD_SUCCESS
;
10788 /* Apply BGP information to distance method. */
10789 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10790 safi_t safi
, struct bgp
*bgp
)
10792 struct bgp_node
*rn
;
10795 struct bgp_distance
*bdistance
;
10796 struct access_list
*alist
;
10797 struct bgp_static
*bgp_static
;
10802 peer
= rinfo
->peer
;
10804 /* Check source address. */
10805 sockunion2hostprefix(&peer
->su
, &q
);
10806 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10808 bdistance
= rn
->info
;
10809 bgp_unlock_node(rn
);
10811 if (bdistance
->access_list
) {
10812 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10814 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10815 return bdistance
->distance
;
10817 return bdistance
->distance
;
10820 /* Backdoor check. */
10821 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10823 bgp_static
= rn
->info
;
10824 bgp_unlock_node(rn
);
10826 if (bgp_static
->backdoor
) {
10827 if (bgp
->distance_local
[afi
][safi
])
10828 return bgp
->distance_local
[afi
][safi
];
10830 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10834 if (peer
->sort
== BGP_PEER_EBGP
) {
10835 if (bgp
->distance_ebgp
[afi
][safi
])
10836 return bgp
->distance_ebgp
[afi
][safi
];
10837 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10839 if (bgp
->distance_ibgp
[afi
][safi
])
10840 return bgp
->distance_ibgp
[afi
][safi
];
10841 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10845 DEFUN (bgp_distance
,
10847 "distance bgp (1-255) (1-255) (1-255)",
10848 "Define an administrative distance\n"
10850 "Distance for routes external to the AS\n"
10851 "Distance for routes internal to the AS\n"
10852 "Distance for local routes\n")
10854 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10855 int idx_number
= 2;
10856 int idx_number_2
= 3;
10857 int idx_number_3
= 4;
10861 afi
= bgp_node_afi(vty
);
10862 safi
= bgp_node_safi(vty
);
10864 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10865 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10866 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10867 return CMD_SUCCESS
;
10870 DEFUN (no_bgp_distance
,
10871 no_bgp_distance_cmd
,
10872 "no distance bgp [(1-255) (1-255) (1-255)]",
10874 "Define an administrative distance\n"
10876 "Distance for routes external to the AS\n"
10877 "Distance for routes internal to the AS\n"
10878 "Distance for local routes\n")
10880 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10884 afi
= bgp_node_afi(vty
);
10885 safi
= bgp_node_safi(vty
);
10887 bgp
->distance_ebgp
[afi
][safi
] = 0;
10888 bgp
->distance_ibgp
[afi
][safi
] = 0;
10889 bgp
->distance_local
[afi
][safi
] = 0;
10890 return CMD_SUCCESS
;
10894 DEFUN (bgp_distance_source
,
10895 bgp_distance_source_cmd
,
10896 "distance (1-255) A.B.C.D/M",
10897 "Define an administrative distance\n"
10898 "Administrative distance\n"
10899 "IP source prefix\n")
10901 int idx_number
= 1;
10902 int idx_ipv4_prefixlen
= 2;
10903 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10904 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10905 return CMD_SUCCESS
;
10908 DEFUN (no_bgp_distance_source
,
10909 no_bgp_distance_source_cmd
,
10910 "no distance (1-255) A.B.C.D/M",
10912 "Define an administrative distance\n"
10913 "Administrative distance\n"
10914 "IP source prefix\n")
10916 int idx_number
= 2;
10917 int idx_ipv4_prefixlen
= 3;
10918 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10919 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10920 return CMD_SUCCESS
;
10923 DEFUN (bgp_distance_source_access_list
,
10924 bgp_distance_source_access_list_cmd
,
10925 "distance (1-255) A.B.C.D/M WORD",
10926 "Define an administrative distance\n"
10927 "Administrative distance\n"
10928 "IP source prefix\n"
10929 "Access list name\n")
10931 int idx_number
= 1;
10932 int idx_ipv4_prefixlen
= 2;
10934 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10935 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10936 return CMD_SUCCESS
;
10939 DEFUN (no_bgp_distance_source_access_list
,
10940 no_bgp_distance_source_access_list_cmd
,
10941 "no distance (1-255) A.B.C.D/M WORD",
10943 "Define an administrative distance\n"
10944 "Administrative distance\n"
10945 "IP source prefix\n"
10946 "Access list name\n")
10948 int idx_number
= 2;
10949 int idx_ipv4_prefixlen
= 3;
10951 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10952 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10953 return CMD_SUCCESS
;
10956 DEFUN (ipv6_bgp_distance_source
,
10957 ipv6_bgp_distance_source_cmd
,
10958 "distance (1-255) X:X::X:X/M",
10959 "Define an administrative distance\n"
10960 "Administrative distance\n"
10961 "IP source prefix\n")
10963 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10964 return CMD_SUCCESS
;
10967 DEFUN (no_ipv6_bgp_distance_source
,
10968 no_ipv6_bgp_distance_source_cmd
,
10969 "no distance (1-255) X:X::X:X/M",
10971 "Define an administrative distance\n"
10972 "Administrative distance\n"
10973 "IP source prefix\n")
10975 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10976 return CMD_SUCCESS
;
10979 DEFUN (ipv6_bgp_distance_source_access_list
,
10980 ipv6_bgp_distance_source_access_list_cmd
,
10981 "distance (1-255) X:X::X:X/M WORD",
10982 "Define an administrative distance\n"
10983 "Administrative distance\n"
10984 "IP source prefix\n"
10985 "Access list name\n")
10987 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10988 return CMD_SUCCESS
;
10991 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10992 no_ipv6_bgp_distance_source_access_list_cmd
,
10993 "no distance (1-255) X:X::X:X/M WORD",
10995 "Define an administrative distance\n"
10996 "Administrative distance\n"
10997 "IP source prefix\n"
10998 "Access list name\n")
11000 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11001 return CMD_SUCCESS
;
11004 DEFUN (bgp_damp_set
,
11006 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11007 "BGP Specific commands\n"
11008 "Enable route-flap dampening\n"
11009 "Half-life time for the penalty\n"
11010 "Value to start reusing a route\n"
11011 "Value to start suppressing a route\n"
11012 "Maximum duration to suppress a stable route\n")
11014 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11015 int idx_half_life
= 2;
11017 int idx_suppress
= 4;
11018 int idx_max_suppress
= 5;
11019 int half
= DEFAULT_HALF_LIFE
* 60;
11020 int reuse
= DEFAULT_REUSE
;
11021 int suppress
= DEFAULT_SUPPRESS
;
11022 int max
= 4 * half
;
11025 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11026 reuse
= atoi(argv
[idx_reuse
]->arg
);
11027 suppress
= atoi(argv
[idx_suppress
]->arg
);
11028 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11029 } else if (argc
== 3) {
11030 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11034 if (suppress
< reuse
) {
11036 "Suppress value cannot be less than reuse value \n");
11040 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11041 reuse
, suppress
, max
);
11044 DEFUN (bgp_damp_unset
,
11045 bgp_damp_unset_cmd
,
11046 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11048 "BGP Specific commands\n"
11049 "Enable route-flap dampening\n"
11050 "Half-life time for the penalty\n"
11051 "Value to start reusing a route\n"
11052 "Value to start suppressing a route\n"
11053 "Maximum duration to suppress a stable route\n")
11055 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11056 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11059 /* Display specified route of BGP table. */
11060 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11061 const char *ip_str
, afi_t afi
, safi_t safi
,
11062 struct prefix_rd
*prd
, int prefix_check
)
11065 struct prefix match
;
11066 struct bgp_node
*rn
;
11067 struct bgp_node
*rm
;
11068 struct bgp_info
*ri
;
11069 struct bgp_info
*ri_temp
;
11071 struct bgp_table
*table
;
11073 /* BGP structure lookup. */
11075 bgp
= bgp_lookup_by_name(view_name
);
11077 vty_out(vty
, "%% Can't find BGP instance %s\n",
11079 return CMD_WARNING
;
11082 bgp
= bgp_get_default();
11084 vty_out(vty
, "%% No BGP process is configured\n");
11085 return CMD_WARNING
;
11089 /* Check IP address argument. */
11090 ret
= str2prefix(ip_str
, &match
);
11092 vty_out(vty
, "%% address is malformed\n");
11093 return CMD_WARNING
;
11096 match
.family
= afi2family(afi
);
11098 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11099 || (safi
== SAFI_EVPN
)) {
11100 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11101 rn
= bgp_route_next(rn
)) {
11102 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11104 if ((table
= rn
->info
) == NULL
)
11106 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11110 || rm
->p
.prefixlen
== match
.prefixlen
) {
11113 if (ri
->extra
&& ri
->extra
->damp_info
) {
11114 ri_temp
= ri
->next
;
11115 bgp_damp_info_free(
11116 ri
->extra
->damp_info
,
11124 bgp_unlock_node(rm
);
11127 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11130 || rn
->p
.prefixlen
== match
.prefixlen
) {
11133 if (ri
->extra
&& ri
->extra
->damp_info
) {
11134 ri_temp
= ri
->next
;
11135 bgp_damp_info_free(
11136 ri
->extra
->damp_info
,
11144 bgp_unlock_node(rn
);
11148 return CMD_SUCCESS
;
11151 DEFUN (clear_ip_bgp_dampening
,
11152 clear_ip_bgp_dampening_cmd
,
11153 "clear ip bgp dampening",
11157 "Clear route flap dampening information\n")
11159 bgp_damp_info_clean();
11160 return CMD_SUCCESS
;
11163 DEFUN (clear_ip_bgp_dampening_prefix
,
11164 clear_ip_bgp_dampening_prefix_cmd
,
11165 "clear ip bgp dampening A.B.C.D/M",
11169 "Clear route flap dampening information\n"
11172 int idx_ipv4_prefixlen
= 4;
11173 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11174 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11177 DEFUN (clear_ip_bgp_dampening_address
,
11178 clear_ip_bgp_dampening_address_cmd
,
11179 "clear ip bgp dampening A.B.C.D",
11183 "Clear route flap dampening information\n"
11184 "Network to clear damping information\n")
11187 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11188 SAFI_UNICAST
, NULL
, 0);
11191 DEFUN (clear_ip_bgp_dampening_address_mask
,
11192 clear_ip_bgp_dampening_address_mask_cmd
,
11193 "clear ip bgp dampening A.B.C.D A.B.C.D",
11197 "Clear route flap dampening information\n"
11198 "Network to clear damping information\n"
11202 int idx_ipv4_2
= 5;
11204 char prefix_str
[BUFSIZ
];
11206 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11209 vty_out(vty
, "%% Inconsistent address and mask\n");
11210 return CMD_WARNING
;
11213 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11217 /* also used for encap safi */
11218 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11219 afi_t afi
, safi_t safi
)
11221 struct bgp_node
*prn
;
11222 struct bgp_node
*rn
;
11223 struct bgp_table
*table
;
11225 struct prefix_rd
*prd
;
11226 struct bgp_static
*bgp_static
;
11227 mpls_label_t label
;
11228 char buf
[SU_ADDRSTRLEN
];
11229 char rdbuf
[RD_ADDRSTRLEN
];
11231 /* Network configuration. */
11232 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11233 prn
= bgp_route_next(prn
)) {
11234 if ((table
= prn
->info
) == NULL
)
11237 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11238 if ((bgp_static
= rn
->info
) == NULL
)
11242 prd
= (struct prefix_rd
*)&prn
->p
;
11244 /* "network" configuration display. */
11245 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11246 label
= decode_label(&bgp_static
->label
);
11248 vty_out(vty
, " network %s/%d rd %s",
11249 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11251 p
->prefixlen
, rdbuf
);
11252 if (safi
== SAFI_MPLS_VPN
)
11253 vty_out(vty
, " label %u", label
);
11255 if (bgp_static
->rmap
.name
)
11256 vty_out(vty
, " route-map %s",
11257 bgp_static
->rmap
.name
);
11259 if (bgp_static
->backdoor
)
11260 vty_out(vty
, " backdoor");
11262 vty_out(vty
, "\n");
11267 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11268 afi_t afi
, safi_t safi
)
11270 struct bgp_node
*prn
;
11271 struct bgp_node
*rn
;
11272 struct bgp_table
*table
;
11274 struct prefix_rd
*prd
;
11275 struct bgp_static
*bgp_static
;
11276 char buf
[PREFIX_STRLEN
* 2];
11277 char buf2
[SU_ADDRSTRLEN
];
11278 char rdbuf
[RD_ADDRSTRLEN
];
11280 /* Network configuration. */
11281 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11282 prn
= bgp_route_next(prn
)) {
11283 if ((table
= prn
->info
) == NULL
)
11286 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11287 if ((bgp_static
= rn
->info
) == NULL
)
11290 char *macrouter
= NULL
;
11293 if (bgp_static
->router_mac
)
11294 macrouter
= prefix_mac2str(
11295 bgp_static
->router_mac
, NULL
, 0);
11296 if (bgp_static
->eth_s_id
)
11297 esi
= esi2str(bgp_static
->eth_s_id
);
11299 prd
= (struct prefix_rd
*)&prn
->p
;
11301 /* "network" configuration display. */
11302 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11303 if (p
->u
.prefix_evpn
.route_type
== 5) {
11304 char local_buf
[PREFIX_STRLEN
];
11305 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11306 struct prefix_evpn
*)p
)
11310 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11311 local_buf
, PREFIX_STRLEN
);
11312 sprintf(buf
, "%s/%u", local_buf
,
11313 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11315 prefix2str(p
, buf
, sizeof(buf
));
11318 if (bgp_static
->gatewayIp
.family
== AF_INET
11319 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11320 inet_ntop(bgp_static
->gatewayIp
.family
,
11321 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11324 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11326 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11327 decode_label(&bgp_static
->label
), esi
, buf2
,
11331 XFREE(MTYPE_TMP
, macrouter
);
11333 XFREE(MTYPE_TMP
, esi
);
11338 /* Configuration of static route announcement and aggregate
11340 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11343 struct bgp_node
*rn
;
11345 struct bgp_static
*bgp_static
;
11346 struct bgp_aggregate
*bgp_aggregate
;
11347 char buf
[SU_ADDRSTRLEN
];
11349 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11350 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11354 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11355 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11359 /* Network configuration. */
11360 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11361 rn
= bgp_route_next(rn
)) {
11362 if ((bgp_static
= rn
->info
) == NULL
)
11367 /* "network" configuration display. */
11368 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11369 uint32_t destination
;
11370 struct in_addr netmask
;
11372 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11373 masklen2ip(p
->prefixlen
, &netmask
);
11374 vty_out(vty
, " network %s",
11375 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11378 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11379 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11380 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11381 || p
->u
.prefix4
.s_addr
== 0) {
11382 /* Natural mask is not display. */
11384 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11386 vty_out(vty
, " network %s/%d",
11387 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11392 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11393 vty_out(vty
, " label-index %u",
11394 bgp_static
->label_index
);
11396 if (bgp_static
->rmap
.name
)
11397 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11399 if (bgp_static
->backdoor
)
11400 vty_out(vty
, " backdoor");
11402 vty_out(vty
, "\n");
11405 /* Aggregate-address configuration. */
11406 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11407 rn
= bgp_route_next(rn
)) {
11408 if ((bgp_aggregate
= rn
->info
) == NULL
)
11413 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11414 struct in_addr netmask
;
11416 masklen2ip(p
->prefixlen
, &netmask
);
11417 vty_out(vty
, " aggregate-address %s %s",
11418 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11420 inet_ntoa(netmask
));
11422 vty_out(vty
, " aggregate-address %s/%d",
11423 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11428 if (bgp_aggregate
->as_set
)
11429 vty_out(vty
, " as-set");
11431 if (bgp_aggregate
->summary_only
)
11432 vty_out(vty
, " summary-only");
11434 vty_out(vty
, "\n");
11438 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11441 struct bgp_node
*rn
;
11442 struct bgp_distance
*bdistance
;
11444 /* Distance configuration. */
11445 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11446 && bgp
->distance_local
[afi
][safi
]
11447 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11448 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11449 || bgp
->distance_local
[afi
][safi
]
11450 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11451 vty_out(vty
, " distance bgp %d %d %d\n",
11452 bgp
->distance_ebgp
[afi
][safi
],
11453 bgp
->distance_ibgp
[afi
][safi
],
11454 bgp
->distance_local
[afi
][safi
]);
11457 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11458 rn
= bgp_route_next(rn
))
11459 if ((bdistance
= rn
->info
) != NULL
) {
11460 char buf
[PREFIX_STRLEN
];
11462 vty_out(vty
, " distance %d %s %s\n",
11463 bdistance
->distance
,
11464 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11465 bdistance
->access_list
? bdistance
->access_list
11470 /* Allocate routing table structure and install commands. */
11471 void bgp_route_init(void)
11476 /* Init BGP distance table. */
11477 FOREACH_AFI_SAFI (afi
, safi
)
11478 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11480 /* IPv4 BGP commands. */
11481 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11482 install_element(BGP_NODE
, &bgp_network_cmd
);
11483 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11485 install_element(BGP_NODE
, &aggregate_address_cmd
);
11486 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11487 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11488 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11490 /* IPv4 unicast configuration. */
11491 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11492 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11493 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11495 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11496 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11497 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11498 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11500 /* IPv4 multicast configuration. */
11501 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11502 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11503 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11504 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11505 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11506 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11507 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11509 /* IPv4 labeled-unicast configuration. */
11510 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11511 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11512 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11513 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11514 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11516 install_element(VIEW_NODE
,
11517 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11518 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11519 install_element(VIEW_NODE
,
11520 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11521 #ifdef KEEP_OLD_VPN_COMMANDS
11522 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11523 #endif /* KEEP_OLD_VPN_COMMANDS */
11524 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11525 install_element(VIEW_NODE
,
11526 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11528 /* BGP dampening clear commands */
11529 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11530 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11532 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11533 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11536 install_element(ENABLE_NODE
,
11537 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11538 #ifdef KEEP_OLD_VPN_COMMANDS
11539 install_element(ENABLE_NODE
,
11540 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11541 #endif /* KEEP_OLD_VPN_COMMANDS */
11543 /* New config IPv6 BGP commands. */
11544 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11545 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11546 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11548 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11549 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11551 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11553 install_element(BGP_NODE
, &bgp_distance_cmd
);
11554 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11555 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11556 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11557 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11558 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11559 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11560 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11561 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11562 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11563 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11564 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11565 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11566 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11567 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11568 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11569 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11570 install_element(BGP_IPV4M_NODE
,
11571 &no_bgp_distance_source_access_list_cmd
);
11572 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11573 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11574 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11575 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11576 install_element(BGP_IPV6_NODE
,
11577 &ipv6_bgp_distance_source_access_list_cmd
);
11578 install_element(BGP_IPV6_NODE
,
11579 &no_ipv6_bgp_distance_source_access_list_cmd
);
11580 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11581 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11582 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11583 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11584 install_element(BGP_IPV6M_NODE
,
11585 &ipv6_bgp_distance_source_access_list_cmd
);
11586 install_element(BGP_IPV6M_NODE
,
11587 &no_ipv6_bgp_distance_source_access_list_cmd
);
11589 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11590 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11591 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11592 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11594 /* IPv4 Multicast Mode */
11595 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11596 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11598 /* Large Communities */
11599 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11600 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11602 /* show bgp ipv4 flowspec detailed */
11603 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11607 void bgp_route_finish(void)
11612 FOREACH_AFI_SAFI (afi
, safi
) {
11613 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11614 bgp_distance_table
[afi
][safi
] = NULL
;