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 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2467 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2468 bm
->process_main_queue
->spec
.max_retries
= 0;
2469 bm
->process_main_queue
->spec
.hold
= 50;
2470 /* Use a higher yield value of 50ms for main queue processing */
2471 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2474 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2476 struct bgp_process_queue
*pqnode
;
2478 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2479 sizeof(struct bgp_process_queue
));
2481 /* unlocked in bgp_processq_del */
2482 pqnode
->bgp
= bgp_lock(bgp
);
2483 STAILQ_INIT(&pqnode
->pqueue
);
2488 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2490 #define ARBITRARY_PROCESS_QLEN 10000
2491 struct work_queue
*wq
= bm
->process_main_queue
;
2492 struct bgp_process_queue
*pqnode
;
2493 int pqnode_reuse
= 0;
2495 /* already scheduled for processing? */
2496 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2502 /* Add route nodes to an existing work queue item until reaching the
2503 limit only if is from the same BGP view and it's not an EOIU marker
2505 if (work_queue_item_count(wq
)) {
2506 struct work_queue_item
*item
= work_queue_last_item(wq
);
2507 pqnode
= item
->data
;
2509 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2510 || pqnode
->bgp
!= bgp
2511 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2512 pqnode
= bgp_processq_alloc(bgp
);
2516 pqnode
= bgp_processq_alloc(bgp
);
2517 /* all unlocked in bgp_process_wq */
2518 bgp_table_lock(bgp_node_table(rn
));
2520 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2523 /* can't be enqueued twice */
2524 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2525 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2529 work_queue_add(wq
, pqnode
);
2534 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2536 struct bgp_process_queue
*pqnode
;
2538 if (bm
->process_main_queue
== NULL
)
2541 pqnode
= bgp_processq_alloc(bgp
);
2543 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2544 work_queue_add(bm
->process_main_queue
, pqnode
);
2547 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2551 peer
= THREAD_ARG(thread
);
2552 peer
->t_pmax_restart
= NULL
;
2554 if (bgp_debug_neighbor_events(peer
))
2556 "%s Maximum-prefix restart timer expired, restore peering",
2559 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2560 zlog_debug("%s: %s peer_clear failed",
2561 __PRETTY_FUNCTION__
, peer
->host
);
2566 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2570 iana_safi_t pkt_safi
;
2572 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2575 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2576 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2577 PEER_STATUS_PREFIX_LIMIT
)
2582 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2584 afi_safi_print(afi
, safi
), peer
->host
,
2585 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2586 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2588 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2589 PEER_FLAG_MAX_PREFIX_WARNING
))
2592 /* Convert AFI, SAFI to values for packet. */
2593 pkt_afi
= afi_int2iana(afi
);
2594 pkt_safi
= safi_int2iana(safi
);
2598 ndata
[0] = (pkt_afi
>> 8);
2600 ndata
[2] = pkt_safi
;
2601 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2602 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2603 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2604 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2606 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2607 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2608 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2612 /* Dynamic peers will just close their connection. */
2613 if (peer_dynamic_neighbor(peer
))
2616 /* restart timer start */
2617 if (peer
->pmax_restart
[afi
][safi
]) {
2618 peer
->v_pmax_restart
=
2619 peer
->pmax_restart
[afi
][safi
] * 60;
2621 if (bgp_debug_neighbor_events(peer
))
2623 "%s Maximum-prefix restart timer started for %d secs",
2624 peer
->host
, peer
->v_pmax_restart
);
2626 BGP_TIMER_ON(peer
->t_pmax_restart
,
2627 bgp_maximum_prefix_restart_timer
,
2628 peer
->v_pmax_restart
);
2633 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2634 PEER_STATUS_PREFIX_LIMIT
);
2636 if (peer
->pcount
[afi
][safi
]
2637 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2638 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2639 PEER_STATUS_PREFIX_THRESHOLD
)
2644 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2645 afi_safi_print(afi
, safi
), peer
->host
,
2646 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2647 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2648 PEER_STATUS_PREFIX_THRESHOLD
);
2650 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2651 PEER_STATUS_PREFIX_THRESHOLD
);
2655 /* Unconditionally remove the route from the RIB, without taking
2656 * damping into consideration (eg, because the session went down)
2658 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2659 afi_t afi
, safi_t safi
)
2661 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2663 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2664 bgp_info_delete(rn
, ri
); /* keep historical info */
2666 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2669 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2670 struct peer
*peer
, afi_t afi
, safi_t safi
,
2671 struct prefix_rd
*prd
)
2673 /* apply dampening, if result is suppressed, we'll be retaining
2674 * the bgp_info in the RIB for historical reference.
2676 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2677 && peer
->sort
== BGP_PEER_EBGP
)
2678 if ((bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2679 == BGP_DAMP_SUPPRESSED
) {
2680 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2686 if (safi
== SAFI_MPLS_VPN
) {
2687 struct bgp_node
*prn
= NULL
;
2688 struct bgp_table
*table
= NULL
;
2690 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2691 (struct prefix
*)prd
);
2693 table
= (struct bgp_table
*)(prn
->info
);
2695 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2696 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2698 bgp_unlock_node(prn
);
2700 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2701 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2703 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2704 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2710 /* If this is an EVPN route, process for un-import. */
2711 if (safi
== SAFI_EVPN
)
2712 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2714 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2717 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2718 struct peer
*peer
, struct attr
*attr
,
2719 struct bgp_node
*rn
)
2721 struct bgp_info
*new;
2723 /* Make new BGP info. */
2724 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2726 new->instance
= instance
;
2727 new->sub_type
= sub_type
;
2730 new->uptime
= bgp_clock();
2732 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2736 static void overlay_index_update(struct attr
*attr
,
2737 struct eth_segment_id
*eth_s_id
,
2738 union gw_addr
*gw_ip
)
2743 if (eth_s_id
== NULL
) {
2744 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2745 sizeof(struct eth_segment_id
));
2747 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2748 sizeof(struct eth_segment_id
));
2750 if (gw_ip
== NULL
) {
2751 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2753 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2754 sizeof(union gw_addr
));
2758 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2759 struct eth_segment_id
*eth_s_id
,
2760 union gw_addr
*gw_ip
)
2762 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2763 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2766 if (afi
!= AFI_L2VPN
)
2769 memset(&temp
, 0, 16);
2770 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2771 info_gw_ip
= (union gw_addr
*)&temp
;
2772 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2775 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2776 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2779 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2781 info_gw_ip_remote
= gw_ip
;
2782 if (eth_s_id
== NULL
)
2783 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2785 info_eth_s_id_remote
= eth_s_id
;
2786 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2788 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2789 sizeof(struct eth_segment_id
));
2792 /* Check if received nexthop is valid or not. */
2793 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2798 /* Only validated for unicast and multicast currently. */
2799 /* Also valid for EVPN where the nexthop is an IP address. */
2800 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2803 /* If NEXT_HOP is present, validate it. */
2804 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2805 if (attr
->nexthop
.s_addr
== 0
2806 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2807 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2811 /* If MP_NEXTHOP is present, validate it. */
2812 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2813 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2814 * it is not an IPv6 link-local address.
2816 if (attr
->mp_nexthop_len
) {
2817 switch (attr
->mp_nexthop_len
) {
2818 case BGP_ATTR_NHLEN_IPV4
:
2819 case BGP_ATTR_NHLEN_VPNV4
:
2820 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2821 || IPV4_CLASS_DE(ntohl(
2822 attr
->mp_nexthop_global_in
.s_addr
))
2823 || bgp_nexthop_self(bgp
,
2824 attr
->mp_nexthop_global_in
));
2827 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2828 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2829 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2830 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2831 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2832 || IN6_IS_ADDR_MULTICAST(
2833 &attr
->mp_nexthop_global
));
2845 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2846 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2847 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2848 uint32_t num_labels
, int soft_reconfig
,
2849 struct bgp_route_evpn
*evpn
)
2852 int aspath_loop_count
= 0;
2853 struct bgp_node
*rn
;
2855 struct attr new_attr
;
2856 struct attr
*attr_new
;
2857 struct bgp_info
*ri
;
2858 struct bgp_info
*new;
2859 struct bgp_info_extra
*extra
;
2861 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2863 int do_loop_check
= 1;
2864 int has_valid_label
= 0;
2866 int vnc_implicit_withdraw
= 0;
2870 memset(&new_attr
, 0, sizeof(struct attr
));
2871 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2872 new_attr
.label
= MPLS_INVALID_LABEL
;
2875 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2876 /* TODO: Check to see if we can get rid of "is_valid_label" */
2877 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2878 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2880 has_valid_label
= bgp_is_valid_label(label
);
2882 /* When peer's soft reconfiguration enabled. Record input packet in
2885 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2886 && peer
!= bgp
->peer_self
)
2887 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2889 /* Check previously received route. */
2890 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2891 if (ri
->peer
== peer
&& ri
->type
== type
2892 && ri
->sub_type
== sub_type
2893 && ri
->addpath_rx_id
== addpath_id
)
2896 /* AS path local-as loop check. */
2897 if (peer
->change_local_as
) {
2898 if (peer
->allowas_in
[afi
][safi
])
2899 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2900 else if (!CHECK_FLAG(peer
->flags
,
2901 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2902 aspath_loop_count
= 1;
2904 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2905 > aspath_loop_count
) {
2906 reason
= "as-path contains our own AS;";
2911 /* If the peer is configured for "allowas-in origin" and the last ASN in
2913 * as-path is our ASN then we do not need to call aspath_loop_check
2915 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2916 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2919 /* AS path loop check. */
2920 if (do_loop_check
) {
2921 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2922 > peer
->allowas_in
[afi
][safi
]
2923 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2924 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2925 > peer
->allowas_in
[afi
][safi
])) {
2926 reason
= "as-path contains our own AS;";
2931 /* Route reflector originator ID check. */
2932 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2933 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2934 reason
= "originator is us;";
2938 /* Route reflector cluster ID check. */
2939 if (bgp_cluster_filter(peer
, attr
)) {
2940 reason
= "reflected from the same cluster;";
2944 /* Apply incoming filter. */
2945 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2950 bgp_attr_dup(&new_attr
, attr
);
2952 /* Apply incoming route-map.
2953 * NB: new_attr may now contain newly allocated values from route-map
2955 * commands, so we need bgp_attr_flush in the error paths, until we
2957 * the attr (which takes over the memory references) */
2958 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2960 reason
= "route-map;";
2961 bgp_attr_flush(&new_attr
);
2965 if (peer
->sort
== BGP_PEER_EBGP
) {
2967 /* If we receive the graceful-shutdown community from an eBGP
2968 * peer we must lower local-preference */
2969 if (new_attr
.community
2970 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2971 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2972 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2974 /* If graceful-shutdown is configured then add the GSHUT
2975 * community to all paths received from eBGP peers */
2976 } else if (bgp_flag_check(peer
->bgp
,
2977 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2978 bgp_attr_add_gshut_community(&new_attr
);
2982 /* next hop check. */
2983 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2984 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2985 reason
= "martian or self next-hop;";
2986 bgp_attr_flush(&new_attr
);
2990 attr_new
= bgp_attr_intern(&new_attr
);
2992 /* If the update is implicit withdraw. */
2994 ri
->uptime
= bgp_clock();
2995 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2997 /* Same attribute comes in. */
2998 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2999 && attrhash_cmp(ri
->attr
, attr_new
)
3000 && (!has_valid_label
3001 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
3002 num_labels
* sizeof(mpls_label_t
))
3004 && (overlay_index_equal(
3005 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3006 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3007 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3008 BGP_CONFIG_DAMPENING
)
3009 && peer
->sort
== BGP_PEER_EBGP
3010 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3011 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3012 bgp_debug_rdpfxpath2str(
3013 afi
, safi
, prd
, p
, label
,
3014 num_labels
, addpath_id
? 1 : 0,
3015 addpath_id
, pfx_buf
,
3017 zlog_debug("%s rcvd %s", peer
->host
,
3021 if (bgp_damp_update(ri
, rn
, afi
, safi
)
3022 != BGP_DAMP_SUPPRESSED
) {
3023 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
3025 bgp_process(bgp
, rn
, afi
, safi
);
3027 } else /* Duplicate - odd */
3029 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3030 if (!peer
->rcvd_attr_printed
) {
3032 "%s rcvd UPDATE w/ attr: %s",
3034 peer
->rcvd_attr_str
);
3035 peer
->rcvd_attr_printed
= 1;
3038 bgp_debug_rdpfxpath2str(
3039 afi
, safi
, prd
, p
, label
,
3040 num_labels
, addpath_id
? 1 : 0,
3041 addpath_id
, pfx_buf
,
3044 "%s rcvd %s...duplicate ignored",
3045 peer
->host
, pfx_buf
);
3048 /* graceful restart STALE flag unset. */
3049 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3050 bgp_info_unset_flag(rn
, ri
,
3052 bgp_process(bgp
, rn
, afi
, safi
);
3056 bgp_unlock_node(rn
);
3057 bgp_attr_unintern(&attr_new
);
3062 /* Withdraw/Announce before we fully processed the withdraw */
3063 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3064 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3065 bgp_debug_rdpfxpath2str(
3066 afi
, safi
, prd
, p
, label
, num_labels
,
3067 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3070 "%s rcvd %s, flapped quicker than processing",
3071 peer
->host
, pfx_buf
);
3074 bgp_info_restore(rn
, ri
);
3077 /* Received Logging. */
3078 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3079 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3080 num_labels
, addpath_id
? 1 : 0,
3081 addpath_id
, pfx_buf
,
3083 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3086 /* graceful restart STALE flag unset. */
3087 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3088 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3090 /* The attribute is changed. */
3091 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3093 /* implicit withdraw, decrement aggregate and pcount here.
3094 * only if update is accepted, they'll increment below.
3096 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3098 /* Update bgp route dampening information. */
3099 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3100 && peer
->sort
== BGP_PEER_EBGP
) {
3101 /* This is implicit withdraw so we should update
3104 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3105 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3108 if (safi
== SAFI_MPLS_VPN
) {
3109 struct bgp_node
*prn
= NULL
;
3110 struct bgp_table
*table
= NULL
;
3112 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3113 (struct prefix
*)prd
);
3115 table
= (struct bgp_table
*)(prn
->info
);
3117 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3118 bgp
, prd
, table
, p
, ri
);
3120 bgp_unlock_node(prn
);
3122 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3123 && (safi
== SAFI_UNICAST
)) {
3124 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3126 * Implicit withdraw case.
3128 ++vnc_implicit_withdraw
;
3129 vnc_import_bgp_del_route(bgp
, p
, ri
);
3130 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3135 /* Special handling for EVPN update of an existing route. If the
3136 * extended community attribute has changed, we need to
3138 * the route using its existing extended community. It will be
3139 * subsequently processed for import with the new extended
3142 if (safi
== SAFI_EVPN
&& !same_attr
) {
3144 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3146 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3149 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3150 attr_new
->ecommunity
);
3152 if (bgp_debug_update(peer
, p
, NULL
, 1))
3154 "Change in EXT-COMM, existing %s new %s",
3156 ri
->attr
->ecommunity
),
3158 attr_new
->ecommunity
));
3159 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3165 /* Update to new attribute. */
3166 bgp_attr_unintern(&ri
->attr
);
3167 ri
->attr
= attr_new
;
3169 /* Update MPLS label */
3170 if (has_valid_label
) {
3171 extra
= bgp_info_extra_get(ri
);
3172 memcpy(&extra
->label
, label
,
3173 num_labels
* sizeof(mpls_label_t
));
3174 extra
->num_labels
= num_labels
;
3175 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3176 bgp_set_valid_label(&extra
->label
[0]);
3180 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3181 && (safi
== SAFI_UNICAST
)) {
3182 if (vnc_implicit_withdraw
) {
3184 * Add back the route with its new attributes
3186 * The route is still selected, until the route
3188 * queued by bgp_process actually runs. We have
3190 * update to the VNC side immediately to avoid
3192 * configuration changes (e.g., route-map
3194 * trigger re-importation of the entire RIB.
3196 vnc_import_bgp_add_route(bgp
, p
, ri
);
3197 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3201 /* Update Overlay Index */
3202 if (afi
== AFI_L2VPN
) {
3203 overlay_index_update(
3204 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3205 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3208 /* Update bgp route dampening information. */
3209 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3210 && peer
->sort
== BGP_PEER_EBGP
) {
3211 /* Now we do normal update dampening. */
3212 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3213 if (ret
== BGP_DAMP_SUPPRESSED
) {
3214 bgp_unlock_node(rn
);
3219 /* Nexthop reachability check - for unicast and
3220 * labeled-unicast.. */
3221 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3222 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3223 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3224 && !CHECK_FLAG(peer
->flags
,
3225 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3227 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3232 struct bgp
*bgp_nexthop
= bgp
;
3234 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3235 bgp_nexthop
= ri
->extra
->bgp_orig
;
3237 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3238 ri
, NULL
, connected
)
3239 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3240 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3242 if (BGP_DEBUG(nht
, NHT
)) {
3243 char buf1
[INET6_ADDRSTRLEN
];
3245 (const void *)&attr_new
3247 buf1
, INET6_ADDRSTRLEN
);
3248 zlog_debug("%s(%s): NH unresolved",
3249 __FUNCTION__
, buf1
);
3251 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3254 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3257 if (safi
== SAFI_MPLS_VPN
) {
3258 struct bgp_node
*prn
= NULL
;
3259 struct bgp_table
*table
= NULL
;
3261 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3262 (struct prefix
*)prd
);
3264 table
= (struct bgp_table
*)(prn
->info
);
3266 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3267 bgp
, prd
, table
, p
, ri
);
3269 bgp_unlock_node(prn
);
3273 /* If this is an EVPN route and some attribute has changed,
3275 * route for import. If the extended community has changed, we
3277 * have done the un-import earlier and the import would result
3279 * route getting injected into appropriate L2 VNIs. If it is
3281 * some other attribute change, the import will result in
3283 * the attributes for the route in the VNI(s).
3285 if (safi
== SAFI_EVPN
&& !same_attr
)
3286 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3288 /* Process change. */
3289 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3291 bgp_process(bgp
, rn
, afi
, safi
);
3292 bgp_unlock_node(rn
);
3294 if (SAFI_UNICAST
== safi
3295 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3296 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3298 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3300 if ((SAFI_MPLS_VPN
== safi
)
3301 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3303 vpn_leak_to_vrf_update(bgp
, ri
);
3307 if (SAFI_MPLS_VPN
== safi
) {
3308 mpls_label_t label_decoded
= decode_label(label
);
3310 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3311 type
, sub_type
, &label_decoded
);
3313 if (SAFI_ENCAP
== safi
) {
3314 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3315 type
, sub_type
, NULL
);
3320 } // End of implicit withdraw
3322 /* Received Logging. */
3323 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3324 if (!peer
->rcvd_attr_printed
) {
3325 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3326 peer
->rcvd_attr_str
);
3327 peer
->rcvd_attr_printed
= 1;
3330 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3331 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3333 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3336 /* Make new BGP info. */
3337 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3339 /* Update MPLS label */
3340 if (has_valid_label
) {
3341 extra
= bgp_info_extra_get(new);
3342 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3343 extra
->num_labels
= num_labels
;
3344 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3345 bgp_set_valid_label(&extra
->label
[0]);
3348 /* Update Overlay Index */
3349 if (afi
== AFI_L2VPN
) {
3350 overlay_index_update(new->attr
,
3351 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3352 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3354 /* Nexthop reachability check. */
3355 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3356 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3357 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3358 && !CHECK_FLAG(peer
->flags
,
3359 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3360 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3365 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3366 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3367 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3369 if (BGP_DEBUG(nht
, NHT
)) {
3370 char buf1
[INET6_ADDRSTRLEN
];
3372 (const void *)&attr_new
->nexthop
,
3373 buf1
, INET6_ADDRSTRLEN
);
3374 zlog_debug("%s(%s): NH unresolved",
3375 __FUNCTION__
, buf1
);
3377 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3380 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3383 new->addpath_rx_id
= addpath_id
;
3385 /* Increment prefix */
3386 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3388 /* Register new BGP information. */
3389 bgp_info_add(rn
, new);
3391 /* route_node_get lock */
3392 bgp_unlock_node(rn
);
3395 if (safi
== SAFI_MPLS_VPN
) {
3396 struct bgp_node
*prn
= NULL
;
3397 struct bgp_table
*table
= NULL
;
3399 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3401 table
= (struct bgp_table
*)(prn
->info
);
3403 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3404 bgp
, prd
, table
, p
, new);
3406 bgp_unlock_node(prn
);
3410 /* If maximum prefix count is configured and current prefix
3412 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3415 /* If this is an EVPN route, process for import. */
3416 if (safi
== SAFI_EVPN
)
3417 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3419 /* Process change. */
3420 bgp_process(bgp
, rn
, afi
, safi
);
3422 if (SAFI_UNICAST
== safi
3423 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3424 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3425 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3427 if ((SAFI_MPLS_VPN
== safi
)
3428 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3430 vpn_leak_to_vrf_update(bgp
, new);
3433 if (SAFI_MPLS_VPN
== safi
) {
3434 mpls_label_t label_decoded
= decode_label(label
);
3436 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3437 sub_type
, &label_decoded
);
3439 if (SAFI_ENCAP
== safi
) {
3440 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3447 /* This BGP update is filtered. Log the reason then update BGP
3450 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3451 if (!peer
->rcvd_attr_printed
) {
3452 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3453 peer
->rcvd_attr_str
);
3454 peer
->rcvd_attr_printed
= 1;
3457 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3458 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3460 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3461 peer
->host
, pfx_buf
, reason
);
3465 /* If this is an EVPN route, un-import it as it is now filtered.
3467 if (safi
== SAFI_EVPN
)
3468 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3470 if (SAFI_UNICAST
== safi
3471 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3472 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3474 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3476 if ((SAFI_MPLS_VPN
== safi
)
3477 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3479 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3482 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3485 bgp_unlock_node(rn
);
3489 * Filtered update is treated as an implicit withdrawal (see
3491 * a few lines above)
3493 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3494 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3502 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3503 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3504 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3505 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3508 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3509 struct bgp_node
*rn
;
3510 struct bgp_info
*ri
;
3513 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3514 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3522 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3524 /* If peer is soft reconfiguration enabled. Record input packet for
3525 * further calculation.
3527 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3528 * routes that are filtered. This tanks out Quagga RS pretty badly due
3530 * the iteration over all RS clients.
3531 * Since we need to remove the entry from adj_in anyway, do that first
3533 * if there was no entry, we don't need to do anything more.
3535 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3536 && peer
!= bgp
->peer_self
)
3537 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3538 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3539 bgp_debug_rdpfxpath2str(
3540 afi
, safi
, prd
, p
, label
, num_labels
,
3541 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3544 "%s withdrawing route %s not in adj-in",
3545 peer
->host
, pfx_buf
);
3547 bgp_unlock_node(rn
);
3551 /* Lookup withdrawn route. */
3552 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3553 if (ri
->peer
== peer
&& ri
->type
== type
3554 && ri
->sub_type
== sub_type
3555 && ri
->addpath_rx_id
== addpath_id
)
3559 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3560 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3561 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3563 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3567 /* Withdraw specified route from routing table. */
3568 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3569 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3570 if (SAFI_UNICAST
== safi
3571 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3572 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3573 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3575 if ((SAFI_MPLS_VPN
== safi
)
3576 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3578 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3580 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3581 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3582 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3584 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3587 /* Unlock bgp_node_get() lock. */
3588 bgp_unlock_node(rn
);
3593 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3596 struct update_subgroup
*subgrp
;
3597 subgrp
= peer_subgroup(peer
, afi
, safi
);
3598 subgroup_default_originate(subgrp
, withdraw
);
3603 * bgp_stop_announce_route_timer
3605 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3607 if (!paf
->t_announce_route
)
3610 THREAD_TIMER_OFF(paf
->t_announce_route
);
3614 * bgp_announce_route_timer_expired
3616 * Callback that is invoked when the route announcement timer for a
3619 static int bgp_announce_route_timer_expired(struct thread
*t
)
3621 struct peer_af
*paf
;
3624 paf
= THREAD_ARG(t
);
3627 if (peer
->status
!= Established
)
3630 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3633 peer_af_announce_route(paf
, 1);
3638 * bgp_announce_route
3640 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3642 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3644 struct peer_af
*paf
;
3645 struct update_subgroup
*subgrp
;
3647 paf
= peer_af_find(peer
, afi
, safi
);
3650 subgrp
= PAF_SUBGRP(paf
);
3653 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3654 * or a refresh has already been triggered.
3656 if (!subgrp
|| paf
->t_announce_route
)
3660 * Start a timer to stagger/delay the announce. This serves
3661 * two purposes - announcement can potentially be combined for
3662 * multiple peers and the announcement doesn't happen in the
3665 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3666 (subgrp
->peer_count
== 1)
3667 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3668 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3669 &paf
->t_announce_route
);
3673 * Announce routes from all AF tables to a peer.
3675 * This should ONLY be called when there is a need to refresh the
3676 * routes to the peer based on a policy change for this peer alone
3677 * or a route refresh request received from the peer.
3678 * The operation will result in splitting the peer from its existing
3679 * subgroups and putting it in new subgroups.
3681 void bgp_announce_route_all(struct peer
*peer
)
3686 FOREACH_AFI_SAFI (afi
, safi
)
3687 bgp_announce_route(peer
, afi
, safi
);
3690 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3691 struct bgp_table
*table
,
3692 struct prefix_rd
*prd
)
3695 struct bgp_node
*rn
;
3696 struct bgp_adj_in
*ain
;
3699 table
= peer
->bgp
->rib
[afi
][safi
];
3701 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3702 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3703 if (ain
->peer
!= peer
)
3706 struct bgp_info
*ri
= rn
->info
;
3707 uint32_t num_labels
= 0;
3708 mpls_label_t
*label_pnt
= NULL
;
3710 if (ri
&& ri
->extra
)
3711 num_labels
= ri
->extra
->num_labels
;
3713 label_pnt
= &ri
->extra
->label
[0];
3715 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3716 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3717 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3718 num_labels
, 1, NULL
);
3721 bgp_unlock_node(rn
);
3727 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3729 struct bgp_node
*rn
;
3730 struct bgp_table
*table
;
3732 if (peer
->status
!= Established
)
3735 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3736 && (safi
!= SAFI_EVPN
))
3737 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3739 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3740 rn
= bgp_route_next(rn
))
3741 if ((table
= rn
->info
) != NULL
) {
3742 struct prefix_rd prd
;
3743 prd
.family
= AF_UNSPEC
;
3745 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3747 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3753 struct bgp_clear_node_queue
{
3754 struct bgp_node
*rn
;
3757 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3759 struct bgp_clear_node_queue
*cnq
= data
;
3760 struct bgp_node
*rn
= cnq
->rn
;
3761 struct peer
*peer
= wq
->spec
.data
;
3762 struct bgp_info
*ri
;
3764 afi_t afi
= bgp_node_table(rn
)->afi
;
3765 safi_t safi
= bgp_node_table(rn
)->safi
;
3770 /* It is possible that we have multiple paths for a prefix from a peer
3771 * if that peer is using AddPath.
3773 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3774 if (ri
->peer
!= peer
)
3777 /* graceful restart STALE flag set. */
3778 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3779 && peer
->nsf
[afi
][safi
]
3780 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3781 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3782 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3784 /* If this is an EVPN route, process for
3786 if (safi
== SAFI_EVPN
)
3787 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3789 /* Handle withdraw for VRF route-leaking and L3VPN */
3790 if (SAFI_UNICAST
== safi
3791 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3792 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3793 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3796 if (SAFI_MPLS_VPN
== safi
&&
3797 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3798 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3801 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3807 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3809 struct bgp_clear_node_queue
*cnq
= data
;
3810 struct bgp_node
*rn
= cnq
->rn
;
3811 struct bgp_table
*table
= bgp_node_table(rn
);
3813 bgp_unlock_node(rn
);
3814 bgp_table_unlock(table
);
3815 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3818 static void bgp_clear_node_complete(struct work_queue
*wq
)
3820 struct peer
*peer
= wq
->spec
.data
;
3822 /* Tickle FSM to start moving again */
3823 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3825 peer_unlock(peer
); /* bgp_clear_route */
3828 static void bgp_clear_node_queue_init(struct peer
*peer
)
3830 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3832 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3833 #undef CLEAR_QUEUE_NAME_LEN
3835 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3836 peer
->clear_node_queue
->spec
.hold
= 10;
3837 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3838 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3839 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3840 peer
->clear_node_queue
->spec
.max_retries
= 0;
3842 /* we only 'lock' this peer reference when the queue is actually active
3844 peer
->clear_node_queue
->spec
.data
= peer
;
3847 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3848 struct bgp_table
*table
)
3850 struct bgp_node
*rn
;
3851 int force
= bm
->process_main_queue
? 0 : 1;
3854 table
= peer
->bgp
->rib
[afi
][safi
];
3856 /* If still no table => afi/safi isn't configured at all or smth. */
3860 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3861 struct bgp_info
*ri
, *next
;
3862 struct bgp_adj_in
*ain
;
3863 struct bgp_adj_in
*ain_next
;
3865 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3866 * queued for every clearing peer, regardless of whether it is
3867 * relevant to the peer at hand.
3869 * Overview: There are 3 different indices which need to be
3870 * scrubbed, potentially, when a peer is removed:
3872 * 1 peer's routes visible via the RIB (ie accepted routes)
3873 * 2 peer's routes visible by the (optional) peer's adj-in index
3874 * 3 other routes visible by the peer's adj-out index
3876 * 3 there is no hurry in scrubbing, once the struct peer is
3877 * removed from bgp->peer, we could just GC such deleted peer's
3878 * adj-outs at our leisure.
3880 * 1 and 2 must be 'scrubbed' in some way, at least made
3881 * invisible via RIB index before peer session is allowed to be
3882 * brought back up. So one needs to know when such a 'search' is
3887 * - there'd be a single global queue or a single RIB walker
3888 * - rather than tracking which route_nodes still need to be
3889 * examined on a peer basis, we'd track which peers still
3892 * Given that our per-peer prefix-counts now should be reliable,
3893 * this may actually be achievable. It doesn't seem to be a huge
3894 * problem at this time,
3896 * It is possible that we have multiple paths for a prefix from
3898 * if that peer is using AddPath.
3902 ain_next
= ain
->next
;
3904 if (ain
->peer
== peer
) {
3905 bgp_adj_in_remove(rn
, ain
);
3906 bgp_unlock_node(rn
);
3912 for (ri
= rn
->info
; ri
; ri
= next
) {
3914 if (ri
->peer
!= peer
)
3918 bgp_info_reap(rn
, ri
);
3920 struct bgp_clear_node_queue
*cnq
;
3922 /* both unlocked in bgp_clear_node_queue_del */
3923 bgp_table_lock(bgp_node_table(rn
));
3926 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3927 sizeof(struct bgp_clear_node_queue
));
3929 work_queue_add(peer
->clear_node_queue
, cnq
);
3937 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3939 struct bgp_node
*rn
;
3940 struct bgp_table
*table
;
3942 if (peer
->clear_node_queue
== NULL
)
3943 bgp_clear_node_queue_init(peer
);
3945 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3946 * Idle until it receives a Clearing_Completed event. This protects
3947 * against peers which flap faster than we can we clear, which could
3950 * a) race with routes from the new session being installed before
3951 * clear_route_node visits the node (to delete the route of that
3953 * b) resource exhaustion, clear_route_node likely leads to an entry
3954 * on the process_main queue. Fast-flapping could cause that queue
3958 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3959 * the unlock will happen upon work-queue completion; other wise, the
3960 * unlock happens at the end of this function.
3962 if (!peer
->clear_node_queue
->thread
)
3965 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3966 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3968 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3969 rn
= bgp_route_next(rn
))
3970 if ((table
= rn
->info
) != NULL
)
3971 bgp_clear_route_table(peer
, afi
, safi
, table
);
3973 /* unlock if no nodes got added to the clear-node-queue. */
3974 if (!peer
->clear_node_queue
->thread
)
3978 void bgp_clear_route_all(struct peer
*peer
)
3983 FOREACH_AFI_SAFI (afi
, safi
)
3984 bgp_clear_route(peer
, afi
, safi
);
3987 rfapiProcessPeerDown(peer
);
3991 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3993 struct bgp_table
*table
;
3994 struct bgp_node
*rn
;
3995 struct bgp_adj_in
*ain
;
3996 struct bgp_adj_in
*ain_next
;
3998 table
= peer
->bgp
->rib
[afi
][safi
];
4000 /* It is possible that we have multiple paths for a prefix from a peer
4001 * if that peer is using AddPath.
4003 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4007 ain_next
= ain
->next
;
4009 if (ain
->peer
== peer
) {
4010 bgp_adj_in_remove(rn
, ain
);
4011 bgp_unlock_node(rn
);
4019 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4021 struct bgp_node
*rn
;
4022 struct bgp_info
*ri
;
4023 struct bgp_table
*table
;
4025 if (safi
== SAFI_MPLS_VPN
) {
4026 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4027 rn
= bgp_route_next(rn
)) {
4028 struct bgp_node
*rm
;
4029 struct bgp_info
*ri
;
4031 /* look for neighbor in tables */
4032 if ((table
= rn
->info
) == NULL
)
4035 for (rm
= bgp_table_top(table
); rm
;
4036 rm
= bgp_route_next(rm
))
4037 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4038 if (ri
->peer
!= peer
)
4040 if (!CHECK_FLAG(ri
->flags
,
4044 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4049 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4050 rn
= bgp_route_next(rn
))
4051 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4052 if (ri
->peer
!= peer
)
4054 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4056 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4062 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4065 struct bgp_node
*rn
;
4066 struct bgp_info
*ri
;
4067 struct bgp_info
*next
;
4069 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4070 for (ri
= rn
->info
; ri
; ri
= next
) {
4072 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4073 && ri
->type
== ZEBRA_ROUTE_BGP
4074 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4075 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4076 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4078 if (bgp_fibupd_safi(safi
))
4079 bgp_zebra_withdraw(&rn
->p
, ri
,
4081 bgp_info_reap(rn
, ri
);
4086 /* Delete all kernel routes. */
4087 void bgp_cleanup_routes(struct bgp
*bgp
)
4090 struct bgp_node
*rn
;
4092 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4093 if (afi
== AFI_L2VPN
)
4095 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4098 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4100 if (afi
!= AFI_L2VPN
) {
4102 safi
= SAFI_MPLS_VPN
;
4103 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4104 rn
= bgp_route_next(rn
)) {
4106 bgp_cleanup_table(bgp
,
4107 (struct bgp_table
*)(rn
->info
),
4109 bgp_table_finish((struct bgp_table
**)&(
4112 bgp_unlock_node(rn
);
4116 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4117 rn
= bgp_route_next(rn
)) {
4119 bgp_cleanup_table(bgp
,
4120 (struct bgp_table
*)(rn
->info
),
4122 bgp_table_finish((struct bgp_table
**)&(
4125 bgp_unlock_node(rn
);
4130 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4131 rn
= bgp_route_next(rn
)) {
4133 bgp_cleanup_table(bgp
,
4134 (struct bgp_table
*)(rn
->info
),
4136 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4138 bgp_unlock_node(rn
);
4143 void bgp_reset(void)
4146 bgp_zclient_reset();
4147 access_list_reset();
4148 prefix_list_reset();
4151 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4153 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4154 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4155 PEER_CAP_ADDPATH_AF_TX_RCV
));
4158 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4160 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4161 struct bgp_nlri
*packet
)
4170 int addpath_encoded
;
4171 uint32_t addpath_id
;
4174 lim
= pnt
+ packet
->length
;
4176 safi
= packet
->safi
;
4178 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4180 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4181 syntactic validity. If the field is syntactically incorrect,
4182 then the Error Subcode is set to Invalid Network Field. */
4183 for (; pnt
< lim
; pnt
+= psize
) {
4184 /* Clear prefix structure. */
4185 memset(&p
, 0, sizeof(struct prefix
));
4187 if (addpath_encoded
) {
4189 /* When packet overflow occurs return immediately. */
4190 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4193 addpath_id
= ntohl(*((uint32_t *)pnt
));
4194 pnt
+= BGP_ADDPATH_ID_LEN
;
4197 /* Fetch prefix length. */
4198 p
.prefixlen
= *pnt
++;
4199 /* afi/safi validity already verified by caller,
4200 * bgp_update_receive */
4201 p
.family
= afi2family(afi
);
4203 /* Prefix length check. */
4204 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4206 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
4207 peer
->host
, p
.prefixlen
, packet
->afi
);
4211 /* Packet size overflow check. */
4212 psize
= PSIZE(p
.prefixlen
);
4214 /* When packet overflow occur return immediately. */
4215 if (pnt
+ psize
> lim
) {
4217 "%s [Error] Update packet error (prefix length %d overflows packet)",
4218 peer
->host
, p
.prefixlen
);
4222 /* Defensive coding, double-check the psize fits in a struct
4224 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4226 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4227 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4231 /* Fetch prefix from NLRI packet. */
4232 memcpy(p
.u
.val
, pnt
, psize
);
4234 /* Check address. */
4235 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4236 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4237 /* From RFC4271 Section 6.3:
4239 * If a prefix in the NLRI field is semantically
4241 * (e.g., an unexpected multicast IP address),
4243 * be logged locally, and the prefix SHOULD be
4247 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4248 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4253 /* Check address. */
4254 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4255 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4259 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4261 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4266 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4270 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4272 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4279 /* Normal process. */
4281 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4282 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4283 NULL
, NULL
, 0, 0, NULL
);
4285 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4286 safi
, ZEBRA_ROUTE_BGP
,
4287 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4290 /* Address family configuration mismatch or maximum-prefix count
4296 /* Packet length consistency check. */
4299 "%s [Error] Update packet error (prefix length mismatch with total length)",
4307 static struct bgp_static
*bgp_static_new(void)
4309 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4312 static void bgp_static_free(struct bgp_static
*bgp_static
)
4314 if (bgp_static
->rmap
.name
)
4315 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4316 if (bgp_static
->eth_s_id
)
4317 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4318 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4321 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4322 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4324 struct bgp_node
*rn
;
4325 struct bgp_info
*ri
;
4326 struct bgp_info
*new;
4327 struct bgp_info info
;
4329 struct attr
*attr_new
;
4332 int vnc_implicit_withdraw
= 0;
4339 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4341 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4343 attr
.nexthop
= bgp_static
->igpnexthop
;
4344 attr
.med
= bgp_static
->igpmetric
;
4345 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4347 if (bgp_static
->atomic
)
4348 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4350 /* Store label index, if required. */
4351 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4352 attr
.label_index
= bgp_static
->label_index
;
4353 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4356 /* Apply route-map. */
4357 if (bgp_static
->rmap
.name
) {
4358 struct attr attr_tmp
= attr
;
4360 memset(&info
, 0, sizeof(struct bgp_info
));
4361 info
.peer
= bgp
->peer_self
;
4362 info
.attr
= &attr_tmp
;
4364 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4366 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4368 bgp
->peer_self
->rmap_type
= 0;
4370 if (ret
== RMAP_DENYMATCH
) {
4371 /* Free uninterned attribute. */
4372 bgp_attr_flush(&attr_tmp
);
4374 /* Unintern original. */
4375 aspath_unintern(&attr
.aspath
);
4376 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4380 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4381 bgp_attr_add_gshut_community(&attr_tmp
);
4383 attr_new
= bgp_attr_intern(&attr_tmp
);
4386 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4387 bgp_attr_add_gshut_community(&attr
);
4389 attr_new
= bgp_attr_intern(&attr
);
4392 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4393 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4394 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4398 if (attrhash_cmp(ri
->attr
, attr_new
)
4399 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4400 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4401 bgp_unlock_node(rn
);
4402 bgp_attr_unintern(&attr_new
);
4403 aspath_unintern(&attr
.aspath
);
4406 /* The attribute is changed. */
4407 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4409 /* Rewrite BGP route information. */
4410 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4411 bgp_info_restore(rn
, ri
);
4413 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4415 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4416 && (safi
== SAFI_UNICAST
)) {
4417 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4419 * Implicit withdraw case.
4420 * We have to do this before ri is
4423 ++vnc_implicit_withdraw
;
4424 vnc_import_bgp_del_route(bgp
, p
, ri
);
4425 vnc_import_bgp_exterior_del_route(
4430 bgp_attr_unintern(&ri
->attr
);
4431 ri
->attr
= attr_new
;
4432 ri
->uptime
= bgp_clock();
4434 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4435 && (safi
== SAFI_UNICAST
)) {
4436 if (vnc_implicit_withdraw
) {
4437 vnc_import_bgp_add_route(bgp
, p
, ri
);
4438 vnc_import_bgp_exterior_add_route(
4444 /* Nexthop reachability check. */
4445 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4446 && (safi
== SAFI_UNICAST
4447 || safi
== SAFI_LABELED_UNICAST
)) {
4449 struct bgp
*bgp_nexthop
= bgp
;
4451 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4452 bgp_nexthop
= ri
->extra
->bgp_orig
;
4454 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4456 bgp_info_set_flag(rn
, ri
,
4459 if (BGP_DEBUG(nht
, NHT
)) {
4460 char buf1
[INET6_ADDRSTRLEN
];
4461 inet_ntop(p
->family
,
4465 "%s(%s): Route not in table, not advertising",
4466 __FUNCTION__
, buf1
);
4468 bgp_info_unset_flag(rn
, ri
,
4472 /* Delete the NHT structure if any, if we're
4474 * enabling/disabling import check. We
4475 * deregister the route
4476 * from NHT to avoid overloading NHT and the
4477 * process interaction
4479 bgp_unlink_nexthop(ri
);
4480 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4482 /* Process change. */
4483 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4484 bgp_process(bgp
, rn
, afi
, safi
);
4486 if (SAFI_UNICAST
== safi
4487 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4489 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4490 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4494 bgp_unlock_node(rn
);
4495 aspath_unintern(&attr
.aspath
);
4500 /* Make new BGP info. */
4501 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4503 /* Nexthop reachability check. */
4504 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4505 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4506 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4507 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4509 if (BGP_DEBUG(nht
, NHT
)) {
4510 char buf1
[INET6_ADDRSTRLEN
];
4511 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4514 "%s(%s): Route not in table, not advertising",
4515 __FUNCTION__
, buf1
);
4517 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4520 /* Delete the NHT structure if any, if we're toggling between
4521 * enabling/disabling import check. We deregister the route
4522 * from NHT to avoid overloading NHT and the process interaction
4524 bgp_unlink_nexthop(new);
4526 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4529 /* Aggregate address increment. */
4530 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4532 /* Register new BGP information. */
4533 bgp_info_add(rn
, new);
4535 /* route_node_get lock */
4536 bgp_unlock_node(rn
);
4538 /* Process change. */
4539 bgp_process(bgp
, rn
, afi
, safi
);
4541 if (SAFI_UNICAST
== safi
4542 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4543 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4544 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4547 /* Unintern original. */
4548 aspath_unintern(&attr
.aspath
);
4551 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4554 struct bgp_node
*rn
;
4555 struct bgp_info
*ri
;
4557 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4559 /* Check selected route and self inserted route. */
4560 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4561 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4562 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4565 /* Withdraw static BGP route from routing table. */
4567 if (SAFI_UNICAST
== safi
4568 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4569 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4570 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4572 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4573 bgp_unlink_nexthop(ri
);
4574 bgp_info_delete(rn
, ri
);
4575 bgp_process(bgp
, rn
, afi
, safi
);
4578 /* Unlock bgp_node_lookup. */
4579 bgp_unlock_node(rn
);
4583 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4585 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4586 afi_t afi
, safi_t safi
,
4587 struct prefix_rd
*prd
)
4589 struct bgp_node
*rn
;
4590 struct bgp_info
*ri
;
4592 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4594 /* Check selected route and self inserted route. */
4595 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4596 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4597 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4600 /* Withdraw static BGP route from routing table. */
4603 rfapiProcessWithdraw(
4604 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4605 1); /* Kill, since it is an administrative change */
4607 if (SAFI_MPLS_VPN
== safi
4608 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4609 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4611 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4612 bgp_info_delete(rn
, ri
);
4613 bgp_process(bgp
, rn
, afi
, safi
);
4616 /* Unlock bgp_node_lookup. */
4617 bgp_unlock_node(rn
);
4620 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4621 struct bgp_static
*bgp_static
, afi_t afi
,
4624 struct bgp_node
*rn
;
4625 struct bgp_info
*new;
4626 struct attr
*attr_new
;
4627 struct attr attr
= {0};
4628 struct bgp_info
*ri
;
4630 mpls_label_t label
= 0;
4632 uint32_t num_labels
= 0;
4637 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4639 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4642 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4644 attr
.nexthop
= bgp_static
->igpnexthop
;
4645 attr
.med
= bgp_static
->igpmetric
;
4646 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4648 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4649 || (safi
== SAFI_ENCAP
)) {
4650 if (afi
== AFI_IP
) {
4651 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4652 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4655 if (afi
== AFI_L2VPN
) {
4656 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4658 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4659 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4660 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4661 sizeof(struct in6_addr
));
4662 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4663 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4664 struct bgp_encap_type_vxlan bet
;
4665 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4666 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4667 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4669 if (bgp_static
->router_mac
) {
4670 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4673 /* Apply route-map. */
4674 if (bgp_static
->rmap
.name
) {
4675 struct attr attr_tmp
= attr
;
4676 struct bgp_info info
;
4679 info
.peer
= bgp
->peer_self
;
4680 info
.attr
= &attr_tmp
;
4682 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4684 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4686 bgp
->peer_self
->rmap_type
= 0;
4688 if (ret
== RMAP_DENYMATCH
) {
4689 /* Free uninterned attribute. */
4690 bgp_attr_flush(&attr_tmp
);
4692 /* Unintern original. */
4693 aspath_unintern(&attr
.aspath
);
4694 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4699 attr_new
= bgp_attr_intern(&attr_tmp
);
4701 attr_new
= bgp_attr_intern(&attr
);
4704 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4705 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4706 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4711 memset(&add
, 0, sizeof(union gw_addr
));
4712 if (attrhash_cmp(ri
->attr
, attr_new
)
4713 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4714 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4715 bgp_unlock_node(rn
);
4716 bgp_attr_unintern(&attr_new
);
4717 aspath_unintern(&attr
.aspath
);
4720 /* The attribute is changed. */
4721 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4723 /* Rewrite BGP route information. */
4724 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4725 bgp_info_restore(rn
, ri
);
4727 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4728 bgp_attr_unintern(&ri
->attr
);
4729 ri
->attr
= attr_new
;
4730 ri
->uptime
= bgp_clock();
4733 label
= decode_label(&ri
->extra
->label
[0]);
4736 /* Process change. */
4737 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4738 bgp_process(bgp
, rn
, afi
, safi
);
4740 if (SAFI_MPLS_VPN
== safi
4741 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4742 vpn_leak_to_vrf_update(bgp
, ri
);
4745 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4746 ri
->attr
, afi
, safi
, ri
->type
,
4747 ri
->sub_type
, &label
);
4749 bgp_unlock_node(rn
);
4750 aspath_unintern(&attr
.aspath
);
4756 /* Make new BGP info. */
4757 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4759 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4760 new->extra
= bgp_info_extra_new();
4762 new->extra
->label
[0] = bgp_static
->label
;
4763 new->extra
->num_labels
= num_labels
;
4766 label
= decode_label(&bgp_static
->label
);
4769 /* Aggregate address increment. */
4770 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4772 /* Register new BGP information. */
4773 bgp_info_add(rn
, new);
4774 /* route_node_get lock */
4775 bgp_unlock_node(rn
);
4777 /* Process change. */
4778 bgp_process(bgp
, rn
, afi
, safi
);
4780 if (SAFI_MPLS_VPN
== safi
4781 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4782 vpn_leak_to_vrf_update(bgp
, new);
4785 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4786 safi
, new->type
, new->sub_type
, &label
);
4789 /* Unintern original. */
4790 aspath_unintern(&attr
.aspath
);
4793 /* Configure static BGP network. When user don't run zebra, static
4794 route should be installed as valid. */
4795 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4796 const char *ip_str
, afi_t afi
, safi_t safi
,
4797 const char *rmap
, int backdoor
, uint32_t label_index
)
4799 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4802 struct bgp_static
*bgp_static
;
4803 struct bgp_node
*rn
;
4804 uint8_t need_update
= 0;
4806 /* Convert IP prefix string to struct prefix. */
4807 ret
= str2prefix(ip_str
, &p
);
4809 vty_out(vty
, "%% Malformed prefix\n");
4810 return CMD_WARNING_CONFIG_FAILED
;
4812 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4813 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4814 return CMD_WARNING_CONFIG_FAILED
;
4821 /* Set BGP static route configuration. */
4822 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4825 vty_out(vty
, "%% Can't find static route specified\n");
4826 return CMD_WARNING_CONFIG_FAILED
;
4829 bgp_static
= rn
->info
;
4831 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4832 && (label_index
!= bgp_static
->label_index
)) {
4834 "%% label-index doesn't match static route\n");
4835 return CMD_WARNING_CONFIG_FAILED
;
4838 if ((rmap
&& bgp_static
->rmap
.name
)
4839 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4841 "%% route-map name doesn't match static route\n");
4842 return CMD_WARNING_CONFIG_FAILED
;
4845 /* Update BGP RIB. */
4846 if (!bgp_static
->backdoor
)
4847 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4849 /* Clear configuration. */
4850 bgp_static_free(bgp_static
);
4852 bgp_unlock_node(rn
);
4853 bgp_unlock_node(rn
);
4856 /* Set BGP static route configuration. */
4857 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4860 /* Configuration change. */
4861 bgp_static
= rn
->info
;
4863 /* Label index cannot be changed. */
4864 if (bgp_static
->label_index
!= label_index
) {
4865 vty_out(vty
, "%% cannot change label-index\n");
4866 return CMD_WARNING_CONFIG_FAILED
;
4869 /* Check previous routes are installed into BGP. */
4870 if (bgp_static
->valid
4871 && bgp_static
->backdoor
!= backdoor
)
4874 bgp_static
->backdoor
= backdoor
;
4877 if (bgp_static
->rmap
.name
)
4878 XFREE(MTYPE_ROUTE_MAP_NAME
,
4879 bgp_static
->rmap
.name
);
4880 bgp_static
->rmap
.name
=
4881 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4882 bgp_static
->rmap
.map
=
4883 route_map_lookup_by_name(rmap
);
4885 if (bgp_static
->rmap
.name
)
4886 XFREE(MTYPE_ROUTE_MAP_NAME
,
4887 bgp_static
->rmap
.name
);
4888 bgp_static
->rmap
.name
= NULL
;
4889 bgp_static
->rmap
.map
= NULL
;
4890 bgp_static
->valid
= 0;
4892 bgp_unlock_node(rn
);
4894 /* New configuration. */
4895 bgp_static
= bgp_static_new();
4896 bgp_static
->backdoor
= backdoor
;
4897 bgp_static
->valid
= 0;
4898 bgp_static
->igpmetric
= 0;
4899 bgp_static
->igpnexthop
.s_addr
= 0;
4900 bgp_static
->label_index
= label_index
;
4903 if (bgp_static
->rmap
.name
)
4904 XFREE(MTYPE_ROUTE_MAP_NAME
,
4905 bgp_static
->rmap
.name
);
4906 bgp_static
->rmap
.name
=
4907 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4908 bgp_static
->rmap
.map
=
4909 route_map_lookup_by_name(rmap
);
4911 rn
->info
= bgp_static
;
4914 bgp_static
->valid
= 1;
4916 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4918 if (!bgp_static
->backdoor
)
4919 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4925 void bgp_static_add(struct bgp
*bgp
)
4929 struct bgp_node
*rn
;
4930 struct bgp_node
*rm
;
4931 struct bgp_table
*table
;
4932 struct bgp_static
*bgp_static
;
4934 FOREACH_AFI_SAFI (afi
, safi
)
4935 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4936 rn
= bgp_route_next(rn
)) {
4937 if (rn
->info
== NULL
)
4940 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4941 || (safi
== SAFI_EVPN
)) {
4944 for (rm
= bgp_table_top(table
); rm
;
4945 rm
= bgp_route_next(rm
)) {
4946 bgp_static
= rm
->info
;
4947 bgp_static_update_safi(bgp
, &rm
->p
,
4952 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4958 /* Called from bgp_delete(). Delete all static routes from the BGP
4960 void bgp_static_delete(struct bgp
*bgp
)
4964 struct bgp_node
*rn
;
4965 struct bgp_node
*rm
;
4966 struct bgp_table
*table
;
4967 struct bgp_static
*bgp_static
;
4969 FOREACH_AFI_SAFI (afi
, safi
)
4970 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4971 rn
= bgp_route_next(rn
)) {
4972 if (rn
->info
== NULL
)
4975 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4976 || (safi
== SAFI_EVPN
)) {
4979 for (rm
= bgp_table_top(table
); rm
;
4980 rm
= bgp_route_next(rm
)) {
4981 bgp_static
= rm
->info
;
4982 bgp_static_withdraw_safi(
4983 bgp
, &rm
->p
, AFI_IP
, safi
,
4984 (struct prefix_rd
*)&rn
->p
);
4985 bgp_static_free(bgp_static
);
4987 bgp_unlock_node(rn
);
4990 bgp_static
= rn
->info
;
4991 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
4992 bgp_static_free(bgp_static
);
4994 bgp_unlock_node(rn
);
4999 void bgp_static_redo_import_check(struct bgp
*bgp
)
5003 struct bgp_node
*rn
;
5004 struct bgp_node
*rm
;
5005 struct bgp_table
*table
;
5006 struct bgp_static
*bgp_static
;
5008 /* Use this flag to force reprocessing of the route */
5009 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5010 FOREACH_AFI_SAFI (afi
, safi
) {
5011 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5012 rn
= bgp_route_next(rn
)) {
5013 if (rn
->info
== NULL
)
5016 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5017 || (safi
== SAFI_EVPN
)) {
5020 for (rm
= bgp_table_top(table
); rm
;
5021 rm
= bgp_route_next(rm
)) {
5022 bgp_static
= rm
->info
;
5023 bgp_static_update_safi(bgp
, &rm
->p
,
5028 bgp_static
= rn
->info
;
5029 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5034 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5037 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5040 struct bgp_table
*table
;
5041 struct bgp_node
*rn
;
5042 struct bgp_info
*ri
;
5044 table
= bgp
->rib
[afi
][safi
];
5045 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5046 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5047 if (ri
->peer
== bgp
->peer_self
5048 && ((ri
->type
== ZEBRA_ROUTE_BGP
5049 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5050 || (ri
->type
!= ZEBRA_ROUTE_BGP
5052 == BGP_ROUTE_REDISTRIBUTE
))) {
5053 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5055 bgp_unlink_nexthop(ri
);
5056 bgp_info_delete(rn
, ri
);
5057 bgp_process(bgp
, rn
, afi
, safi
);
5064 * Purge all networks and redistributed routes from routing table.
5065 * Invoked upon the instance going down.
5067 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5072 FOREACH_AFI_SAFI (afi
, safi
)
5073 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5078 * Currently this is used to set static routes for VPN and ENCAP.
5079 * I think it can probably be factored with bgp_static_set.
5081 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5082 const char *ip_str
, const char *rd_str
,
5083 const char *label_str
, const char *rmap_str
,
5084 int evpn_type
, const char *esi
, const char *gwip
,
5085 const char *ethtag
, const char *routermac
)
5087 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5090 struct prefix_rd prd
;
5091 struct bgp_node
*prn
;
5092 struct bgp_node
*rn
;
5093 struct bgp_table
*table
;
5094 struct bgp_static
*bgp_static
;
5095 mpls_label_t label
= MPLS_INVALID_LABEL
;
5096 struct prefix gw_ip
;
5098 /* validate ip prefix */
5099 ret
= str2prefix(ip_str
, &p
);
5101 vty_out(vty
, "%% Malformed prefix\n");
5102 return CMD_WARNING_CONFIG_FAILED
;
5105 if ((afi
== AFI_L2VPN
)
5106 && (bgp_build_evpn_prefix(evpn_type
,
5107 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5108 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5109 return CMD_WARNING_CONFIG_FAILED
;
5112 ret
= str2prefix_rd(rd_str
, &prd
);
5114 vty_out(vty
, "%% Malformed rd\n");
5115 return CMD_WARNING_CONFIG_FAILED
;
5119 unsigned long label_val
;
5120 label_val
= strtoul(label_str
, NULL
, 10);
5121 encode_label(label_val
, &label
);
5124 if (safi
== SAFI_EVPN
) {
5125 if (esi
&& str2esi(esi
, NULL
) == 0) {
5126 vty_out(vty
, "%% Malformed ESI\n");
5127 return CMD_WARNING_CONFIG_FAILED
;
5129 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5130 vty_out(vty
, "%% Malformed Router MAC\n");
5131 return CMD_WARNING_CONFIG_FAILED
;
5134 memset(&gw_ip
, 0, sizeof(struct prefix
));
5135 ret
= str2prefix(gwip
, &gw_ip
);
5137 vty_out(vty
, "%% Malformed GatewayIp\n");
5138 return CMD_WARNING_CONFIG_FAILED
;
5140 if ((gw_ip
.family
== AF_INET
5141 && is_evpn_prefix_ipaddr_v6(
5142 (struct prefix_evpn
*)&p
))
5143 || (gw_ip
.family
== AF_INET6
5144 && is_evpn_prefix_ipaddr_v4(
5145 (struct prefix_evpn
*)&p
))) {
5147 "%% GatewayIp family differs with IP prefix\n");
5148 return CMD_WARNING_CONFIG_FAILED
;
5152 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5153 if (prn
->info
== NULL
)
5154 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5156 bgp_unlock_node(prn
);
5159 rn
= bgp_node_get(table
, &p
);
5162 vty_out(vty
, "%% Same network configuration exists\n");
5163 bgp_unlock_node(rn
);
5165 /* New configuration. */
5166 bgp_static
= bgp_static_new();
5167 bgp_static
->backdoor
= 0;
5168 bgp_static
->valid
= 0;
5169 bgp_static
->igpmetric
= 0;
5170 bgp_static
->igpnexthop
.s_addr
= 0;
5171 bgp_static
->label
= label
;
5172 bgp_static
->prd
= prd
;
5175 if (bgp_static
->rmap
.name
)
5176 XFREE(MTYPE_ROUTE_MAP_NAME
,
5177 bgp_static
->rmap
.name
);
5178 bgp_static
->rmap
.name
=
5179 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5180 bgp_static
->rmap
.map
=
5181 route_map_lookup_by_name(rmap_str
);
5184 if (safi
== SAFI_EVPN
) {
5186 bgp_static
->eth_s_id
=
5188 sizeof(struct eth_segment_id
));
5189 str2esi(esi
, bgp_static
->eth_s_id
);
5192 bgp_static
->router_mac
=
5193 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5194 (void)prefix_str2mac(routermac
,
5195 bgp_static
->router_mac
);
5198 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5200 rn
->info
= bgp_static
;
5202 bgp_static
->valid
= 1;
5203 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5209 /* Configure static BGP network. */
5210 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5211 const char *ip_str
, const char *rd_str
,
5212 const char *label_str
, int evpn_type
, const char *esi
,
5213 const char *gwip
, const char *ethtag
)
5215 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5218 struct prefix_rd prd
;
5219 struct bgp_node
*prn
;
5220 struct bgp_node
*rn
;
5221 struct bgp_table
*table
;
5222 struct bgp_static
*bgp_static
;
5223 mpls_label_t label
= MPLS_INVALID_LABEL
;
5225 /* Convert IP prefix string to struct prefix. */
5226 ret
= str2prefix(ip_str
, &p
);
5228 vty_out(vty
, "%% Malformed prefix\n");
5229 return CMD_WARNING_CONFIG_FAILED
;
5232 if ((afi
== AFI_L2VPN
)
5233 && (bgp_build_evpn_prefix(evpn_type
,
5234 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5235 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5236 return CMD_WARNING_CONFIG_FAILED
;
5238 ret
= str2prefix_rd(rd_str
, &prd
);
5240 vty_out(vty
, "%% Malformed rd\n");
5241 return CMD_WARNING_CONFIG_FAILED
;
5245 unsigned long label_val
;
5246 label_val
= strtoul(label_str
, NULL
, 10);
5247 encode_label(label_val
, &label
);
5250 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5251 if (prn
->info
== NULL
)
5252 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5254 bgp_unlock_node(prn
);
5257 rn
= bgp_node_lookup(table
, &p
);
5260 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5262 bgp_static
= rn
->info
;
5263 bgp_static_free(bgp_static
);
5265 bgp_unlock_node(rn
);
5266 bgp_unlock_node(rn
);
5268 vty_out(vty
, "%% Can't find the route\n");
5273 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5274 const char *rmap_name
)
5276 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5277 struct bgp_rmap
*rmap
;
5279 rmap
= &bgp
->table_map
[afi
][safi
];
5282 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5283 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5284 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5287 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5292 if (bgp_fibupd_safi(safi
))
5293 bgp_zebra_announce_table(bgp
, afi
, safi
);
5298 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5299 const char *rmap_name
)
5301 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5302 struct bgp_rmap
*rmap
;
5304 rmap
= &bgp
->table_map
[afi
][safi
];
5306 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5310 if (bgp_fibupd_safi(safi
))
5311 bgp_zebra_announce_table(bgp
, afi
, safi
);
5316 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5319 if (bgp
->table_map
[afi
][safi
].name
) {
5320 vty_out(vty
, " table-map %s\n",
5321 bgp
->table_map
[afi
][safi
].name
);
5325 DEFUN (bgp_table_map
,
5328 "BGP table to RIB route download filter\n"
5329 "Name of the route map\n")
5332 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5333 argv
[idx_word
]->arg
);
5335 DEFUN (no_bgp_table_map
,
5336 no_bgp_table_map_cmd
,
5337 "no table-map WORD",
5339 "BGP table to RIB route download filter\n"
5340 "Name of the route map\n")
5343 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5344 argv
[idx_word
]->arg
);
5350 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5351 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5352 backdoor$backdoor}]",
5354 "Specify a network to announce via BGP\n"
5359 "Route-map to modify the attributes\n"
5360 "Name of the route map\n"
5361 "Label index to associate with the prefix\n"
5362 "Label index value\n"
5363 "Specify a BGP backdoor route\n")
5365 char addr_prefix_str
[BUFSIZ
];
5370 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5373 vty_out(vty
, "%% Inconsistent address and mask\n");
5374 return CMD_WARNING_CONFIG_FAILED
;
5378 return bgp_static_set(
5379 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5380 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5381 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5384 DEFPY(ipv6_bgp_network
,
5385 ipv6_bgp_network_cmd
,
5386 "[no] network X:X::X:X/M$prefix \
5387 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5389 "Specify a network to announce via BGP\n"
5391 "Route-map to modify the attributes\n"
5392 "Name of the route map\n"
5393 "Label index to associate with the prefix\n"
5394 "Label index value\n")
5396 return bgp_static_set(
5397 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5398 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5401 /* Aggreagete address:
5403 advertise-map Set condition to advertise attribute
5404 as-set Generate AS set path information
5405 attribute-map Set attributes of aggregate
5406 route-map Set parameters of aggregate
5407 summary-only Filter more specific routes from updates
5408 suppress-map Conditionally filter more specific routes from updates
5411 struct bgp_aggregate
{
5412 /* Summary-only flag. */
5413 uint8_t summary_only
;
5415 /* AS set generation. */
5418 /* Route-map for aggregated route. */
5419 struct route_map
*map
;
5421 /* Suppress-count. */
5422 unsigned long count
;
5424 /* SAFI configuration. */
5428 static struct bgp_aggregate
*bgp_aggregate_new(void)
5430 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5433 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5435 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5438 static int bgp_aggregate_info_same(struct bgp_info
*ri
, struct aspath
*aspath
,
5439 struct community
*comm
)
5441 static struct aspath
*ae
= NULL
;
5444 ae
= aspath_empty();
5449 if (!aspath_cmp(ri
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5452 if (!community_cmp(ri
->attr
->community
, comm
))
5458 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5459 struct prefix
*p
, uint8_t origin
,
5460 struct aspath
*aspath
,
5461 struct community
*community
,
5462 uint8_t atomic_aggregate
,
5463 struct bgp_aggregate
*aggregate
)
5465 struct bgp_node
*rn
;
5466 struct bgp_table
*table
;
5467 struct bgp_info
*ri
, *new;
5469 table
= bgp
->rib
[afi
][safi
];
5471 rn
= bgp_node_get(table
, p
);
5473 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5474 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5475 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5478 if (aggregate
->count
> 0) {
5480 * If the aggregate information has not changed
5481 * no need to re-install it again.
5483 if (bgp_aggregate_info_same(rn
->info
, aspath
, community
)) {
5484 bgp_unlock_node(rn
);
5487 aspath_free(aspath
);
5489 community_free(community
);
5495 * Mark the old as unusable
5498 bgp_info_delete(rn
, ri
);
5501 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5502 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5503 community
, aggregate
->as_set
,
5506 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5508 bgp_info_add(rn
, new);
5509 bgp_process(bgp
, rn
, afi
, safi
);
5511 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5512 if (ri
->peer
== bgp
->peer_self
5513 && ri
->type
== ZEBRA_ROUTE_BGP
5514 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5517 /* Withdraw static BGP route from routing table. */
5519 bgp_info_delete(rn
, ri
);
5520 bgp_process(bgp
, rn
, afi
, safi
);
5524 bgp_unlock_node(rn
);
5527 /* Update an aggregate as routes are added/removed from the BGP table */
5528 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5529 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5530 struct bgp_info
*del
,
5531 struct bgp_aggregate
*aggregate
)
5533 struct bgp_table
*table
;
5534 struct bgp_node
*top
;
5535 struct bgp_node
*rn
;
5537 struct aspath
*aspath
= NULL
;
5538 struct aspath
*asmerge
= NULL
;
5539 struct community
*community
= NULL
;
5540 struct community
*commerge
= NULL
;
5541 struct bgp_info
*ri
;
5542 unsigned long match
= 0;
5543 uint8_t atomic_aggregate
= 0;
5545 /* ORIGIN attribute: If at least one route among routes that are
5546 aggregated has ORIGIN with the value INCOMPLETE, then the
5547 aggregated route must have the ORIGIN attribute with the value
5548 INCOMPLETE. Otherwise, if at least one route among routes that
5549 are aggregated has ORIGIN with the value EGP, then the aggregated
5550 route must have the origin attribute with the value EGP. In all
5551 other case the value of the ORIGIN attribute of the aggregated
5552 route is INTERNAL. */
5553 origin
= BGP_ORIGIN_IGP
;
5555 table
= bgp
->rib
[afi
][safi
];
5557 top
= bgp_node_get(table
, p
);
5558 for (rn
= bgp_node_get(table
, p
); rn
;
5559 rn
= bgp_route_next_until(rn
, top
)) {
5560 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5565 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5566 if (BGP_INFO_HOLDDOWN(ri
))
5569 if (del
&& ri
== del
)
5573 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5574 atomic_aggregate
= 1;
5576 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5580 * summary-only aggregate route suppress
5581 * aggregated route announcements.
5583 if (aggregate
->summary_only
) {
5584 (bgp_info_extra_get(ri
))->suppress
++;
5585 bgp_info_set_flag(rn
, ri
,
5586 BGP_INFO_ATTR_CHANGED
);
5593 * If at least one route among routes that are
5594 * aggregated has ORIGIN with the value INCOMPLETE,
5595 * then the aggregated route MUST have the ORIGIN
5596 * attribute with the value INCOMPLETE. Otherwise, if
5597 * at least one route among routes that are aggregated
5598 * has ORIGIN with the value EGP, then the aggregated
5599 * route MUST have the ORIGIN attribute with the value
5602 if (origin
< ri
->attr
->origin
)
5603 origin
= ri
->attr
->origin
;
5605 if (!aggregate
->as_set
)
5609 * as-set aggregate route generate origin, as path,
5610 * and community aggregation.
5613 asmerge
= aspath_aggregate(aspath
,
5615 aspath_free(aspath
);
5618 aspath
= aspath_dup(ri
->attr
->aspath
);
5620 if (!ri
->attr
->community
)
5624 commerge
= community_merge(community
,
5625 ri
->attr
->community
);
5626 community
= community_uniq_sort(commerge
);
5627 community_free(commerge
);
5629 community
= community_dup(ri
->attr
->community
);
5632 bgp_process(bgp
, rn
, afi
, safi
);
5634 bgp_unlock_node(top
);
5639 if (aggregate
->summary_only
)
5640 (bgp_info_extra_get(rinew
))->suppress
++;
5642 if (origin
< rinew
->attr
->origin
)
5643 origin
= rinew
->attr
->origin
;
5645 if (aggregate
->as_set
) {
5647 asmerge
= aspath_aggregate(aspath
,
5648 rinew
->attr
->aspath
);
5649 aspath_free(aspath
);
5652 aspath
= aspath_dup(rinew
->attr
->aspath
);
5654 if (rinew
->attr
->community
) {
5656 commerge
= community_merge(
5658 rinew
->attr
->community
);
5660 community_uniq_sort(commerge
);
5661 community_free(commerge
);
5663 community
= community_dup(
5664 rinew
->attr
->community
);
5669 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5670 atomic_aggregate
, aggregate
);
5672 if (aggregate
->count
== 0) {
5674 aspath_free(aspath
);
5676 community_free(community
);
5680 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5681 safi_t safi
, struct bgp_aggregate
*aggregate
)
5683 struct bgp_table
*table
;
5684 struct bgp_node
*top
;
5685 struct bgp_node
*rn
;
5686 struct bgp_info
*ri
;
5687 unsigned long match
;
5689 table
= bgp
->rib
[afi
][safi
];
5691 /* If routes exists below this node, generate aggregate routes. */
5692 top
= bgp_node_get(table
, p
);
5693 for (rn
= bgp_node_get(table
, p
); rn
;
5694 rn
= bgp_route_next_until(rn
, top
)) {
5695 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5699 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5700 if (BGP_INFO_HOLDDOWN(ri
))
5703 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5706 if (aggregate
->summary_only
&& ri
->extra
) {
5707 ri
->extra
->suppress
--;
5709 if (ri
->extra
->suppress
== 0) {
5711 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5718 /* If this node was suppressed, process the change. */
5720 bgp_process(bgp
, rn
, afi
, safi
);
5722 bgp_unlock_node(top
);
5725 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5726 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5728 struct bgp_node
*child
;
5729 struct bgp_node
*rn
;
5730 struct bgp_aggregate
*aggregate
;
5731 struct bgp_table
*table
;
5733 table
= bgp
->aggregate
[afi
][safi
];
5735 /* No aggregates configured. */
5736 if (bgp_table_top_nolock(table
) == NULL
)
5739 if (p
->prefixlen
== 0)
5742 if (BGP_INFO_HOLDDOWN(ri
))
5745 child
= bgp_node_get(table
, p
);
5747 /* Aggregate address configuration check. */
5748 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5749 if ((aggregate
= rn
->info
) != NULL
5750 && rn
->p
.prefixlen
< p
->prefixlen
) {
5751 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5752 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5755 bgp_unlock_node(child
);
5758 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5759 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5761 struct bgp_node
*child
;
5762 struct bgp_node
*rn
;
5763 struct bgp_aggregate
*aggregate
;
5764 struct bgp_table
*table
;
5766 table
= bgp
->aggregate
[afi
][safi
];
5768 /* No aggregates configured. */
5769 if (bgp_table_top_nolock(table
) == NULL
)
5772 if (p
->prefixlen
== 0)
5775 child
= bgp_node_get(table
, p
);
5777 /* Aggregate address configuration check. */
5778 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5779 if ((aggregate
= rn
->info
) != NULL
5780 && rn
->p
.prefixlen
< p
->prefixlen
) {
5781 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5782 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5785 bgp_unlock_node(child
);
5788 /* Aggregate route attribute. */
5789 #define AGGREGATE_SUMMARY_ONLY 1
5790 #define AGGREGATE_AS_SET 1
5792 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5793 afi_t afi
, safi_t safi
)
5795 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5798 struct bgp_node
*rn
;
5799 struct bgp_aggregate
*aggregate
;
5801 /* Convert string to prefix structure. */
5802 ret
= str2prefix(prefix_str
, &p
);
5804 vty_out(vty
, "Malformed prefix\n");
5805 return CMD_WARNING_CONFIG_FAILED
;
5809 /* Old configuration check. */
5810 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5813 "%% There is no aggregate-address configuration.\n");
5814 return CMD_WARNING_CONFIG_FAILED
;
5817 aggregate
= rn
->info
;
5818 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5819 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
, 0, aggregate
);
5821 /* Unlock aggregate address configuration. */
5823 bgp_aggregate_free(aggregate
);
5824 bgp_unlock_node(rn
);
5825 bgp_unlock_node(rn
);
5830 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5831 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5833 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5836 struct bgp_node
*rn
;
5837 struct bgp_aggregate
*aggregate
;
5839 /* Convert string to prefix structure. */
5840 ret
= str2prefix(prefix_str
, &p
);
5842 vty_out(vty
, "Malformed prefix\n");
5843 return CMD_WARNING_CONFIG_FAILED
;
5847 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5848 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5849 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5851 return CMD_WARNING_CONFIG_FAILED
;
5854 /* Old configuration check. */
5855 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5858 vty_out(vty
, "There is already same aggregate network.\n");
5859 /* try to remove the old entry */
5860 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5862 vty_out(vty
, "Error deleting aggregate.\n");
5863 bgp_unlock_node(rn
);
5864 return CMD_WARNING_CONFIG_FAILED
;
5868 /* Make aggregate address structure. */
5869 aggregate
= bgp_aggregate_new();
5870 aggregate
->summary_only
= summary_only
;
5871 aggregate
->as_set
= as_set
;
5872 aggregate
->safi
= safi
;
5873 rn
->info
= aggregate
;
5875 /* Aggregate address insert into BGP routing table. */
5876 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
5881 DEFUN (aggregate_address
,
5882 aggregate_address_cmd
,
5883 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5884 "Configure BGP aggregate entries\n"
5885 "Aggregate prefix\n"
5886 "Generate AS set path information\n"
5887 "Filter more specific routes from updates\n"
5888 "Filter more specific routes from updates\n"
5889 "Generate AS set path information\n")
5892 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5893 char *prefix
= argv
[idx
]->arg
;
5895 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5897 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5898 ? AGGREGATE_SUMMARY_ONLY
5901 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5902 summary_only
, as_set
);
5905 DEFUN (aggregate_address_mask
,
5906 aggregate_address_mask_cmd
,
5907 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5908 "Configure BGP aggregate entries\n"
5909 "Aggregate address\n"
5911 "Generate AS set path information\n"
5912 "Filter more specific routes from updates\n"
5913 "Filter more specific routes from updates\n"
5914 "Generate AS set path information\n")
5917 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5918 char *prefix
= argv
[idx
]->arg
;
5919 char *mask
= argv
[idx
+ 1]->arg
;
5921 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5923 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5924 ? AGGREGATE_SUMMARY_ONLY
5927 char prefix_str
[BUFSIZ
];
5928 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5931 vty_out(vty
, "%% Inconsistent address and mask\n");
5932 return CMD_WARNING_CONFIG_FAILED
;
5935 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5936 summary_only
, as_set
);
5939 DEFUN (no_aggregate_address
,
5940 no_aggregate_address_cmd
,
5941 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5943 "Configure BGP aggregate entries\n"
5944 "Aggregate prefix\n"
5945 "Generate AS set path information\n"
5946 "Filter more specific routes from updates\n"
5947 "Filter more specific routes from updates\n"
5948 "Generate AS set path information\n")
5951 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5952 char *prefix
= argv
[idx
]->arg
;
5953 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5956 DEFUN (no_aggregate_address_mask
,
5957 no_aggregate_address_mask_cmd
,
5958 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5960 "Configure BGP aggregate entries\n"
5961 "Aggregate address\n"
5963 "Generate AS set path information\n"
5964 "Filter more specific routes from updates\n"
5965 "Filter more specific routes from updates\n"
5966 "Generate AS set path information\n")
5969 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5970 char *prefix
= argv
[idx
]->arg
;
5971 char *mask
= argv
[idx
+ 1]->arg
;
5973 char prefix_str
[BUFSIZ
];
5974 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5977 vty_out(vty
, "%% Inconsistent address and mask\n");
5978 return CMD_WARNING_CONFIG_FAILED
;
5981 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5984 DEFUN (ipv6_aggregate_address
,
5985 ipv6_aggregate_address_cmd
,
5986 "aggregate-address X:X::X:X/M [summary-only]",
5987 "Configure BGP aggregate entries\n"
5988 "Aggregate prefix\n"
5989 "Filter more specific routes from updates\n")
5992 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
5993 char *prefix
= argv
[idx
]->arg
;
5994 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5995 ? AGGREGATE_SUMMARY_ONLY
5997 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6001 DEFUN (no_ipv6_aggregate_address
,
6002 no_ipv6_aggregate_address_cmd
,
6003 "no aggregate-address X:X::X:X/M [summary-only]",
6005 "Configure BGP aggregate entries\n"
6006 "Aggregate prefix\n"
6007 "Filter more specific routes from updates\n")
6010 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6011 char *prefix
= argv
[idx
]->arg
;
6012 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6015 /* Redistribute route treatment. */
6016 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6017 const union g_addr
*nexthop
, ifindex_t ifindex
,
6018 enum nexthop_types_t nhtype
, uint32_t metric
,
6019 uint8_t type
, unsigned short instance
,
6022 struct bgp_info
*new;
6023 struct bgp_info
*bi
;
6024 struct bgp_info info
;
6025 struct bgp_node
*bn
;
6027 struct attr
*new_attr
;
6030 struct bgp_redist
*red
;
6032 /* Make default attribute. */
6033 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6036 case NEXTHOP_TYPE_IFINDEX
:
6038 case NEXTHOP_TYPE_IPV4
:
6039 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6040 attr
.nexthop
= nexthop
->ipv4
;
6042 case NEXTHOP_TYPE_IPV6
:
6043 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6044 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6045 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6047 case NEXTHOP_TYPE_BLACKHOLE
:
6048 switch (p
->family
) {
6050 attr
.nexthop
.s_addr
= INADDR_ANY
;
6053 memset(&attr
.mp_nexthop_global
, 0,
6054 sizeof(attr
.mp_nexthop_global
));
6055 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6060 attr
.nh_ifindex
= ifindex
;
6063 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6066 afi
= family2afi(p
->family
);
6068 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6070 struct attr attr_new
;
6072 /* Copy attribute for modification. */
6073 bgp_attr_dup(&attr_new
, &attr
);
6075 if (red
->redist_metric_flag
)
6076 attr_new
.med
= red
->redist_metric
;
6078 /* Apply route-map. */
6079 if (red
->rmap
.name
) {
6080 memset(&info
, 0, sizeof(struct bgp_info
));
6081 info
.peer
= bgp
->peer_self
;
6082 info
.attr
= &attr_new
;
6084 SET_FLAG(bgp
->peer_self
->rmap_type
,
6085 PEER_RMAP_TYPE_REDISTRIBUTE
);
6087 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6090 bgp
->peer_self
->rmap_type
= 0;
6092 if (ret
== RMAP_DENYMATCH
) {
6093 /* Free uninterned attribute. */
6094 bgp_attr_flush(&attr_new
);
6096 /* Unintern original. */
6097 aspath_unintern(&attr
.aspath
);
6098 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6103 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6104 bgp_attr_add_gshut_community(&attr_new
);
6106 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6107 SAFI_UNICAST
, p
, NULL
);
6109 new_attr
= bgp_attr_intern(&attr_new
);
6111 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6112 if (bi
->peer
== bgp
->peer_self
6113 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6117 /* Ensure the (source route) type is updated. */
6119 if (attrhash_cmp(bi
->attr
, new_attr
)
6120 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6121 bgp_attr_unintern(&new_attr
);
6122 aspath_unintern(&attr
.aspath
);
6123 bgp_unlock_node(bn
);
6126 /* The attribute is changed. */
6127 bgp_info_set_flag(bn
, bi
,
6128 BGP_INFO_ATTR_CHANGED
);
6130 /* Rewrite BGP route information. */
6131 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6132 bgp_info_restore(bn
, bi
);
6134 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6136 bgp_attr_unintern(&bi
->attr
);
6137 bi
->attr
= new_attr
;
6138 bi
->uptime
= bgp_clock();
6140 /* Process change. */
6141 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6143 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6144 bgp_unlock_node(bn
);
6145 aspath_unintern(&attr
.aspath
);
6147 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6149 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6151 vpn_leak_from_vrf_update(
6152 bgp_get_default(), bgp
, bi
);
6158 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6159 bgp
->peer_self
, new_attr
, bn
);
6160 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6162 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6163 bgp_info_add(bn
, new);
6164 bgp_unlock_node(bn
);
6165 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6167 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6168 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6170 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6174 /* Unintern original. */
6175 aspath_unintern(&attr
.aspath
);
6178 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6179 unsigned short instance
)
6182 struct bgp_node
*rn
;
6183 struct bgp_info
*ri
;
6184 struct bgp_redist
*red
;
6186 afi
= family2afi(p
->family
);
6188 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6190 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6191 SAFI_UNICAST
, p
, NULL
);
6193 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6194 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6198 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6199 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6201 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6204 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6205 bgp_info_delete(rn
, ri
);
6206 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6208 bgp_unlock_node(rn
);
6212 /* Withdraw specified route type's route. */
6213 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6214 unsigned short instance
)
6216 struct bgp_node
*rn
;
6217 struct bgp_info
*ri
;
6218 struct bgp_table
*table
;
6220 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6222 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6223 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6224 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6225 && ri
->instance
== instance
)
6229 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6230 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6232 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6235 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6237 bgp_info_delete(rn
, ri
);
6238 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6243 /* Static function to display route. */
6244 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6248 uint32_t destination
;
6251 if (p
->family
== AF_INET
) {
6253 len
= vty_out(vty
, "%s",
6254 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6256 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6258 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6259 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6260 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6261 || p
->u
.prefix4
.s_addr
== 0) {
6262 /* When mask is natural,
6263 mask is not displayed. */
6265 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6267 json_object_string_add(json
, "prefix",
6268 inet_ntop(p
->family
,
6271 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6273 } else if (p
->family
== AF_ETHERNET
) {
6274 prefix2str(p
, buf
, PREFIX_STRLEN
);
6275 len
= vty_out(vty
, "%s", buf
);
6276 } else if (p
->family
== AF_EVPN
) {
6280 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6283 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6284 } else if (p
->family
== AF_FLOWSPEC
) {
6285 route_vty_out_flowspec(vty
, p
, NULL
,
6287 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6288 NLRI_STRING_FORMAT_MIN
, json
);
6293 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6300 vty_out(vty
, "\n%*s", 20, " ");
6302 vty_out(vty
, "%*s", len
, " ");
6306 enum bgp_display_type
{
6310 /* Print the short form route status for a bgp_info */
6311 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6312 json_object
*json_path
)
6316 /* Route status display. */
6317 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6318 json_object_boolean_true_add(json_path
, "removed");
6320 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6321 json_object_boolean_true_add(json_path
, "stale");
6323 if (binfo
->extra
&& binfo
->extra
->suppress
)
6324 json_object_boolean_true_add(json_path
, "suppressed");
6326 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6327 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6328 json_object_boolean_true_add(json_path
, "valid");
6331 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6332 json_object_boolean_true_add(json_path
, "history");
6334 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6335 json_object_boolean_true_add(json_path
, "damped");
6337 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6338 json_object_boolean_true_add(json_path
, "bestpath");
6340 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6341 json_object_boolean_true_add(json_path
, "multipath");
6343 /* Internal route. */
6344 if ((binfo
->peer
->as
)
6345 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6346 json_object_string_add(json_path
, "pathFrom",
6349 json_object_string_add(json_path
, "pathFrom",
6355 /* Route status display. */
6356 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6358 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6360 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6362 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6363 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6369 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6371 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6373 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6375 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6380 /* Internal route. */
6381 if (binfo
->peer
&& (binfo
->peer
->as
)
6382 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6388 /* called from terminal list command */
6389 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6390 int display
, safi_t safi
, json_object
*json_paths
)
6393 json_object
*json_path
= NULL
;
6394 json_object
*json_nexthops
= NULL
;
6395 json_object
*json_nexthop_global
= NULL
;
6396 json_object
*json_nexthop_ll
= NULL
;
6397 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6398 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6401 bool nexthop_othervrf
= false;
6402 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6403 const char *nexthop_vrfname
= "Default";
6406 json_path
= json_object_new_object();
6408 /* short status lead text */
6409 route_vty_short_status_out(vty
, binfo
, json_path
);
6412 /* print prefix and mask */
6414 route_vty_out_route(p
, vty
, json_path
);
6416 vty_out(vty
, "%*s", 17, " ");
6418 route_vty_out_route(p
, vty
, json_path
);
6421 /* Print attribute */
6425 json_object_array_add(json_paths
, json_path
);
6433 * If vrf id of nexthop is different from that of prefix,
6434 * set up printable string to append
6436 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6437 const char *self
= "";
6442 nexthop_othervrf
= true;
6443 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6445 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6446 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6447 "@%s%s", VRFID_NONE_STR
, self
);
6449 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6450 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6452 if (binfo
->extra
->bgp_orig
->inst_type
!=
6453 BGP_INSTANCE_TYPE_DEFAULT
)
6455 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6457 const char *self
= "";
6462 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6466 * For ENCAP and EVPN routes, nexthop address family is not
6467 * neccessarily the same as the prefix address family.
6468 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6469 * EVPN routes are also exchanged with a MP nexthop. Currently,
6471 * is only IPv4, the value will be present in either
6473 * attr->mp_nexthop_global_in
6475 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6478 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6482 sprintf(nexthop
, "%s",
6483 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6487 sprintf(nexthop
, "%s",
6488 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6492 sprintf(nexthop
, "?");
6497 json_nexthop_global
= json_object_new_object();
6499 json_object_string_add(json_nexthop_global
, "afi",
6500 (af
== AF_INET
) ? "ip" : "ipv6");
6501 json_object_string_add(json_nexthop_global
,
6502 (af
== AF_INET
) ? "ip" : "ipv6",
6504 json_object_boolean_true_add(json_nexthop_global
,
6507 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6508 } else if (safi
== SAFI_EVPN
) {
6510 json_nexthop_global
= json_object_new_object();
6512 json_object_string_add(json_nexthop_global
, "ip",
6513 inet_ntoa(attr
->nexthop
));
6514 json_object_string_add(json_nexthop_global
, "afi",
6516 json_object_boolean_true_add(json_nexthop_global
,
6519 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6521 } else if (safi
== SAFI_FLOWSPEC
) {
6522 if (attr
->nexthop
.s_addr
!= 0) {
6524 json_nexthop_global
= json_object_new_object();
6525 json_object_string_add(
6526 json_nexthop_global
, "ip",
6527 inet_ntoa(attr
->nexthop
));
6528 json_object_string_add(json_nexthop_global
,
6530 json_object_boolean_true_add(json_nexthop_global
,
6533 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6536 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6538 json_nexthop_global
= json_object_new_object();
6540 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6541 json_object_string_add(
6542 json_nexthop_global
, "ip",
6543 inet_ntoa(attr
->mp_nexthop_global_in
));
6545 json_object_string_add(
6546 json_nexthop_global
, "ip",
6547 inet_ntoa(attr
->nexthop
));
6549 json_object_string_add(json_nexthop_global
, "afi",
6551 json_object_boolean_true_add(json_nexthop_global
,
6556 snprintf(buf
, sizeof(buf
), "%s%s",
6557 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6558 vty_out(vty
, "%-16s", buf
);
6563 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6568 json_nexthop_global
= json_object_new_object();
6569 json_object_string_add(
6570 json_nexthop_global
, "ip",
6571 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6573 json_object_string_add(json_nexthop_global
, "afi",
6575 json_object_string_add(json_nexthop_global
, "scope",
6578 /* We display both LL & GL if both have been
6580 if ((attr
->mp_nexthop_len
== 32)
6581 || (binfo
->peer
->conf_if
)) {
6582 json_nexthop_ll
= json_object_new_object();
6583 json_object_string_add(
6584 json_nexthop_ll
, "ip",
6586 &attr
->mp_nexthop_local
, buf
,
6588 json_object_string_add(json_nexthop_ll
, "afi",
6590 json_object_string_add(json_nexthop_ll
, "scope",
6593 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6594 &attr
->mp_nexthop_local
)
6596 && !attr
->mp_nexthop_prefer_global
)
6597 json_object_boolean_true_add(
6598 json_nexthop_ll
, "used");
6600 json_object_boolean_true_add(
6601 json_nexthop_global
, "used");
6603 json_object_boolean_true_add(
6604 json_nexthop_global
, "used");
6606 /* Display LL if LL/Global both in table unless
6607 * prefer-global is set */
6608 if (((attr
->mp_nexthop_len
== 32)
6609 && !attr
->mp_nexthop_prefer_global
)
6610 || (binfo
->peer
->conf_if
)) {
6611 if (binfo
->peer
->conf_if
) {
6612 len
= vty_out(vty
, "%s",
6613 binfo
->peer
->conf_if
);
6614 len
= 16 - len
; /* len of IPv6
6620 vty_out(vty
, "\n%*s", 36, " ");
6622 vty_out(vty
, "%*s", len
, " ");
6628 &attr
->mp_nexthop_local
,
6634 vty_out(vty
, "\n%*s", 36, " ");
6636 vty_out(vty
, "%*s", len
, " ");
6642 &attr
->mp_nexthop_global
, buf
,
6648 vty_out(vty
, "\n%*s", 36, " ");
6650 vty_out(vty
, "%*s", len
, " ");
6656 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6658 json_object_int_add(json_path
, "med", attr
->med
);
6660 vty_out(vty
, "%10u", attr
->med
);
6661 else if (!json_paths
)
6665 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6667 json_object_int_add(json_path
, "localpref",
6670 vty_out(vty
, "%7u", attr
->local_pref
);
6671 else if (!json_paths
)
6675 json_object_int_add(json_path
, "weight", attr
->weight
);
6677 vty_out(vty
, "%7u ", attr
->weight
);
6681 json_object_string_add(
6682 json_path
, "peerId",
6683 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6689 json_object_string_add(json_path
, "aspath",
6692 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6697 json_object_string_add(json_path
, "origin",
6698 bgp_origin_long_str
[attr
->origin
]);
6700 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6704 json_object_boolean_true_add(json_path
,
6705 "announceNexthopSelf");
6706 if (nexthop_othervrf
) {
6707 json_object_string_add(json_path
, "nhVrfName",
6710 json_object_int_add(json_path
, "nhVrfId",
6711 ((nexthop_vrfid
== VRF_UNKNOWN
)
6713 : (int)nexthop_vrfid
));
6718 if (json_nexthop_global
|| json_nexthop_ll
) {
6719 json_nexthops
= json_object_new_array();
6721 if (json_nexthop_global
)
6722 json_object_array_add(json_nexthops
,
6723 json_nexthop_global
);
6725 if (json_nexthop_ll
)
6726 json_object_array_add(json_nexthops
,
6729 json_object_object_add(json_path
, "nexthops",
6733 json_object_array_add(json_paths
, json_path
);
6737 /* prints an additional line, indented, with VNC info, if
6739 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6740 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6745 /* called from terminal list command */
6746 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6747 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6749 json_object
*json_status
= NULL
;
6750 json_object
*json_net
= NULL
;
6752 /* Route status display. */
6754 json_status
= json_object_new_object();
6755 json_net
= json_object_new_object();
6762 /* print prefix and mask */
6764 json_object_string_add(
6765 json_net
, "addrPrefix",
6766 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6768 route_vty_out_route(p
, vty
, NULL
);
6770 /* Print attribute */
6773 if (p
->family
== AF_INET
6774 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6775 || safi
== SAFI_EVPN
6776 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6777 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6778 || safi
== SAFI_EVPN
)
6779 json_object_string_add(
6780 json_net
, "nextHop",
6782 attr
->mp_nexthop_global_in
));
6784 json_object_string_add(
6785 json_net
, "nextHop",
6786 inet_ntoa(attr
->nexthop
));
6787 } else if (p
->family
== AF_INET6
6788 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6791 json_object_string_add(
6792 json_net
, "netHopGloabal",
6794 &attr
->mp_nexthop_global
, buf
,
6799 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6800 json_object_int_add(json_net
, "metric",
6803 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6804 json_object_int_add(json_net
, "localPref",
6807 json_object_int_add(json_net
, "weight", attr
->weight
);
6811 json_object_string_add(json_net
, "asPath",
6815 json_object_string_add(json_net
, "bgpOriginCode",
6816 bgp_origin_str
[attr
->origin
]);
6818 if (p
->family
== AF_INET
6819 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6820 || safi
== SAFI_EVPN
6821 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6822 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6823 || safi
== SAFI_EVPN
)
6824 vty_out(vty
, "%-16s",
6826 attr
->mp_nexthop_global_in
));
6828 vty_out(vty
, "%-16s",
6829 inet_ntoa(attr
->nexthop
));
6830 } else if (p
->family
== AF_INET6
6831 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6838 &attr
->mp_nexthop_global
, buf
,
6842 vty_out(vty
, "\n%*s", 36, " ");
6844 vty_out(vty
, "%*s", len
, " ");
6847 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6848 vty_out(vty
, "%10u", attr
->med
);
6852 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6853 vty_out(vty
, "%7u", attr
->local_pref
);
6857 vty_out(vty
, "%7u ", attr
->weight
);
6861 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6864 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6868 json_object_boolean_true_add(json_status
, "*");
6869 json_object_boolean_true_add(json_status
, ">");
6870 json_object_object_add(json_net
, "appliedStatusSymbols",
6872 char buf_cut
[BUFSIZ
];
6873 json_object_object_add(
6875 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6881 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6882 struct bgp_info
*binfo
, int display
, safi_t safi
,
6885 json_object
*json_out
= NULL
;
6887 mpls_label_t label
= MPLS_INVALID_LABEL
;
6893 json_out
= json_object_new_object();
6895 /* short status lead text */
6896 route_vty_short_status_out(vty
, binfo
, json_out
);
6898 /* print prefix and mask */
6901 route_vty_out_route(p
, vty
, NULL
);
6903 vty_out(vty
, "%*s", 17, " ");
6906 /* Print attribute */
6909 if (((p
->family
== AF_INET
)
6910 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6911 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6912 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6913 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6914 || safi
== SAFI_EVPN
) {
6916 json_object_string_add(
6917 json_out
, "mpNexthopGlobalIn",
6919 attr
->mp_nexthop_global_in
));
6921 vty_out(vty
, "%-16s",
6923 attr
->mp_nexthop_global_in
));
6926 json_object_string_add(
6927 json_out
, "nexthop",
6928 inet_ntoa(attr
->nexthop
));
6930 vty_out(vty
, "%-16s",
6931 inet_ntoa(attr
->nexthop
));
6933 } else if (((p
->family
== AF_INET6
)
6934 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6935 || (safi
== SAFI_EVPN
6936 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6937 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6941 if (attr
->mp_nexthop_len
6942 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6944 json_object_string_add(
6945 json_out
, "mpNexthopGlobalIn",
6948 &attr
->mp_nexthop_global
,
6949 buf_a
, sizeof(buf_a
)));
6954 &attr
->mp_nexthop_global
,
6955 buf_a
, sizeof(buf_a
)));
6956 } else if (attr
->mp_nexthop_len
6957 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6960 &attr
->mp_nexthop_global
,
6961 buf_a
, sizeof(buf_a
));
6963 &attr
->mp_nexthop_local
,
6964 buf_b
, sizeof(buf_b
));
6965 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6966 json_object_string_add(
6968 "mpNexthopGlobalLocal", buf_c
);
6970 vty_out(vty
, "%s(%s)",
6973 &attr
->mp_nexthop_global
,
6974 buf_a
, sizeof(buf_a
)),
6977 &attr
->mp_nexthop_local
,
6978 buf_b
, sizeof(buf_b
)));
6983 label
= decode_label(&binfo
->extra
->label
[0]);
6985 if (bgp_is_valid_label(&label
)) {
6987 json_object_int_add(json_out
, "notag", label
);
6988 json_object_array_add(json
, json_out
);
6990 vty_out(vty
, "notag/%d", label
);
6996 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
6997 struct bgp_info
*binfo
, int display
,
6998 json_object
*json_paths
)
7002 json_object
*json_path
= NULL
;
7005 json_path
= json_object_new_object();
7010 /* short status lead text */
7011 route_vty_short_status_out(vty
, binfo
, json_path
);
7013 /* print prefix and mask */
7015 route_vty_out_route(p
, vty
, NULL
);
7017 vty_out(vty
, "%*s", 17, " ");
7019 /* Print attribute */
7023 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7027 vty_out(vty
, "%-16s",
7028 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7032 vty_out(vty
, "%s(%s)",
7033 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7035 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7042 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7044 vty_out(vty
, "%s", str
);
7045 XFREE(MTYPE_TMP
, str
);
7047 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7049 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7050 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7053 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7056 if (attr
->ecommunity
) {
7058 struct ecommunity_val
*routermac
= ecommunity_lookup(
7059 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7060 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7062 mac
= ecom_mac2str((char *)routermac
->val
);
7064 vty_out(vty
, "/%s", (char *)mac
);
7065 XFREE(MTYPE_TMP
, mac
);
7073 /* dampening route */
7074 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7075 struct bgp_info
*binfo
, int display
, safi_t safi
,
7076 uint8_t use_json
, json_object
*json
)
7080 char timebuf
[BGP_UPTIME_LEN
];
7082 /* short status lead text */
7083 route_vty_short_status_out(vty
, binfo
, json
);
7085 /* print prefix and mask */
7088 route_vty_out_route(p
, vty
, NULL
);
7090 vty_out(vty
, "%*s", 17, " ");
7093 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7097 vty_out(vty
, "\n%*s", 34, " ");
7100 json_object_int_add(json
, "peerHost", len
);
7102 vty_out(vty
, "%*s", len
, " ");
7106 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7109 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7113 /* Print attribute */
7119 json_object_string_add(json
, "asPath",
7122 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7127 json_object_string_add(json
, "origin",
7128 bgp_origin_str
[attr
->origin
]);
7130 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7137 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7138 struct bgp_info
*binfo
, int display
, safi_t safi
,
7139 uint8_t use_json
, json_object
*json
)
7142 struct bgp_damp_info
*bdi
;
7143 char timebuf
[BGP_UPTIME_LEN
];
7149 bdi
= binfo
->extra
->damp_info
;
7151 /* short status lead text */
7152 route_vty_short_status_out(vty
, binfo
, json
);
7154 /* print prefix and mask */
7157 route_vty_out_route(p
, vty
, NULL
);
7159 vty_out(vty
, "%*s", 17, " ");
7162 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7166 vty_out(vty
, "\n%*s", 33, " ");
7169 json_object_int_add(json
, "peerHost", len
);
7171 vty_out(vty
, "%*s", len
, " ");
7174 len
= vty_out(vty
, "%d", bdi
->flap
);
7181 json_object_int_add(json
, "bdiFlap", len
);
7183 vty_out(vty
, "%*s", len
, " ");
7187 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7190 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7191 BGP_UPTIME_LEN
, 0, NULL
));
7193 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7194 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7196 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7197 BGP_UPTIME_LEN
, use_json
, json
);
7200 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7205 vty_out(vty
, "%*s ", 8, " ");
7208 /* Print attribute */
7214 json_object_string_add(json
, "asPath",
7217 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7222 json_object_string_add(json
, "origin",
7223 bgp_origin_str
[attr
->origin
]);
7225 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7231 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7232 int *first
, const char *header
,
7233 json_object
*json_adv_to
)
7235 char buf1
[INET6_ADDRSTRLEN
];
7236 json_object
*json_peer
= NULL
;
7239 /* 'advertised-to' is a dictionary of peers we have advertised
7241 * prefix too. The key is the peer's IP or swpX, the value is
7243 * hostname if we know it and "" if not.
7245 json_peer
= json_object_new_object();
7248 json_object_string_add(json_peer
, "hostname",
7252 json_object_object_add(json_adv_to
, peer
->conf_if
,
7255 json_object_object_add(
7257 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7261 vty_out(vty
, "%s", header
);
7266 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7268 vty_out(vty
, " %s(%s)", peer
->hostname
,
7271 vty_out(vty
, " %s(%s)", peer
->hostname
,
7272 sockunion2str(&peer
->su
, buf1
,
7276 vty_out(vty
, " %s", peer
->conf_if
);
7279 sockunion2str(&peer
->su
, buf1
,
7285 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7286 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7287 json_object
*json_paths
)
7289 char buf
[INET6_ADDRSTRLEN
];
7291 char buf2
[EVPN_ROUTE_STRLEN
];
7293 int sockunion_vty_out(struct vty
*, union sockunion
*);
7295 json_object
*json_bestpath
= NULL
;
7296 json_object
*json_cluster_list
= NULL
;
7297 json_object
*json_cluster_list_list
= NULL
;
7298 json_object
*json_ext_community
= NULL
;
7299 json_object
*json_last_update
= NULL
;
7300 json_object
*json_pmsi
= NULL
;
7301 json_object
*json_nexthop_global
= NULL
;
7302 json_object
*json_nexthop_ll
= NULL
;
7303 json_object
*json_nexthops
= NULL
;
7304 json_object
*json_path
= NULL
;
7305 json_object
*json_peer
= NULL
;
7306 json_object
*json_string
= NULL
;
7307 json_object
*json_adv_to
= NULL
;
7309 struct listnode
*node
, *nnode
;
7311 int addpath_capable
;
7313 unsigned int first_as
;
7314 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7319 json_path
= json_object_new_object();
7320 json_peer
= json_object_new_object();
7321 json_nexthop_global
= json_object_new_object();
7324 if (!json_paths
&& safi
== SAFI_EVPN
) {
7327 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7328 vty_out(vty
, " Route %s", buf2
);
7330 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7331 bgp_evpn_label2str(binfo
->extra
->label
,
7332 binfo
->extra
->num_labels
, tag_buf
,
7334 vty_out(vty
, " VNI %s", tag_buf
);
7337 if (binfo
->extra
&& binfo
->extra
->parent
) {
7338 struct bgp_info
*parent_ri
;
7339 struct bgp_node
*rn
, *prn
;
7341 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7342 rn
= parent_ri
->net
;
7343 if (rn
&& rn
->prn
) {
7345 vty_out(vty
, " Imported from %s:%s\n",
7347 (struct prefix_rd
*)&prn
->p
,
7348 buf1
, sizeof(buf1
)),
7357 /* Line1 display AS-path, Aggregator */
7360 if (!attr
->aspath
->json
)
7361 aspath_str_update(attr
->aspath
, true);
7362 json_object_lock(attr
->aspath
->json
);
7363 json_object_object_add(json_path
, "aspath",
7364 attr
->aspath
->json
);
7366 if (attr
->aspath
->segments
)
7367 aspath_print_vty(vty
, " %s",
7370 vty_out(vty
, " Local");
7374 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7376 json_object_boolean_true_add(json_path
,
7379 vty_out(vty
, ", (removed)");
7382 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7384 json_object_boolean_true_add(json_path
,
7387 vty_out(vty
, ", (stale)");
7390 if (CHECK_FLAG(attr
->flag
,
7391 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7393 json_object_int_add(json_path
, "aggregatorAs",
7394 attr
->aggregator_as
);
7395 json_object_string_add(
7396 json_path
, "aggregatorId",
7397 inet_ntoa(attr
->aggregator_addr
));
7399 vty_out(vty
, ", (aggregated by %u %s)",
7400 attr
->aggregator_as
,
7401 inet_ntoa(attr
->aggregator_addr
));
7405 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7406 PEER_FLAG_REFLECTOR_CLIENT
)) {
7408 json_object_boolean_true_add(
7409 json_path
, "rxedFromRrClient");
7411 vty_out(vty
, ", (Received from a RR-client)");
7414 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7415 PEER_FLAG_RSERVER_CLIENT
)) {
7417 json_object_boolean_true_add(
7418 json_path
, "rxedFromRsClient");
7420 vty_out(vty
, ", (Received from a RS-client)");
7423 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7425 json_object_boolean_true_add(
7426 json_path
, "dampeningHistoryEntry");
7428 vty_out(vty
, ", (history entry)");
7429 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7431 json_object_boolean_true_add(
7432 json_path
, "dampeningSuppressed");
7434 vty_out(vty
, ", (suppressed due to dampening)");
7440 /* Line2 display Next-hop, Neighbor, Router-id */
7441 /* Display the nexthop */
7442 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7443 || p
->family
== AF_EVPN
)
7444 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7445 || safi
== SAFI_EVPN
7446 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7447 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7448 || safi
== SAFI_EVPN
) {
7450 json_object_string_add(
7451 json_nexthop_global
, "ip",
7453 attr
->mp_nexthop_global_in
));
7457 attr
->mp_nexthop_global_in
));
7460 json_object_string_add(
7461 json_nexthop_global
, "ip",
7462 inet_ntoa(attr
->nexthop
));
7465 inet_ntoa(attr
->nexthop
));
7469 json_object_string_add(json_nexthop_global
,
7473 json_object_string_add(
7474 json_nexthop_global
, "ip",
7476 &attr
->mp_nexthop_global
, buf
,
7478 json_object_string_add(json_nexthop_global
,
7480 json_object_string_add(json_nexthop_global
,
7485 &attr
->mp_nexthop_global
, buf
,
7490 /* Display the IGP cost or 'inaccessible' */
7491 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7493 json_object_boolean_false_add(
7494 json_nexthop_global
, "accessible");
7496 vty_out(vty
, " (inaccessible)");
7498 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7500 json_object_int_add(
7501 json_nexthop_global
, "metric",
7502 binfo
->extra
->igpmetric
);
7504 vty_out(vty
, " (metric %u)",
7505 binfo
->extra
->igpmetric
);
7508 /* IGP cost is 0, display this only for json */
7511 json_object_int_add(json_nexthop_global
,
7516 json_object_boolean_true_add(
7517 json_nexthop_global
, "accessible");
7520 /* Display peer "from" output */
7521 /* This path was originated locally */
7522 if (binfo
->peer
== bgp
->peer_self
) {
7524 if (safi
== SAFI_EVPN
7525 || (p
->family
== AF_INET
7526 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7528 json_object_string_add(
7529 json_peer
, "peerId", "0.0.0.0");
7531 vty_out(vty
, " from 0.0.0.0 ");
7534 json_object_string_add(json_peer
,
7537 vty_out(vty
, " from :: ");
7541 json_object_string_add(
7542 json_peer
, "routerId",
7543 inet_ntoa(bgp
->router_id
));
7545 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7548 /* We RXed this path from one of our peers */
7552 json_object_string_add(
7553 json_peer
, "peerId",
7554 sockunion2str(&binfo
->peer
->su
, buf
,
7556 json_object_string_add(
7557 json_peer
, "routerId",
7559 &binfo
->peer
->remote_id
, buf1
,
7562 if (binfo
->peer
->hostname
)
7563 json_object_string_add(
7564 json_peer
, "hostname",
7565 binfo
->peer
->hostname
);
7567 if (binfo
->peer
->domainname
)
7568 json_object_string_add(
7569 json_peer
, "domainname",
7570 binfo
->peer
->domainname
);
7572 if (binfo
->peer
->conf_if
)
7573 json_object_string_add(
7574 json_peer
, "interface",
7575 binfo
->peer
->conf_if
);
7577 if (binfo
->peer
->conf_if
) {
7578 if (binfo
->peer
->hostname
7581 BGP_FLAG_SHOW_HOSTNAME
))
7582 vty_out(vty
, " from %s(%s)",
7583 binfo
->peer
->hostname
,
7584 binfo
->peer
->conf_if
);
7586 vty_out(vty
, " from %s",
7587 binfo
->peer
->conf_if
);
7589 if (binfo
->peer
->hostname
7592 BGP_FLAG_SHOW_HOSTNAME
))
7593 vty_out(vty
, " from %s(%s)",
7594 binfo
->peer
->hostname
,
7597 vty_out(vty
, " from %s",
7606 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7607 vty_out(vty
, " (%s)",
7608 inet_ntoa(attr
->originator_id
));
7610 vty_out(vty
, " (%s)",
7613 &binfo
->peer
->remote_id
,
7614 buf1
, sizeof(buf1
)));
7619 * Note when vrfid of nexthop is different from that of prefix
7621 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7622 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7627 if (binfo
->extra
->bgp_orig
->inst_type
==
7628 BGP_INSTANCE_TYPE_DEFAULT
)
7632 vn
= binfo
->extra
->bgp_orig
->name
;
7634 json_object_string_add(json_path
, "nhVrfName",
7637 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7638 json_object_int_add(json_path
,
7641 json_object_int_add(json_path
,
7642 "nhVrfId", (int)nexthop_vrfid
);
7645 if (nexthop_vrfid
== VRF_UNKNOWN
)
7646 vty_out(vty
, " vrf ?");
7648 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7654 json_object_boolean_true_add(json_path
,
7655 "announceNexthopSelf");
7657 vty_out(vty
, " announce-nh-self");
7664 /* display the link-local nexthop */
7665 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7667 json_nexthop_ll
= json_object_new_object();
7668 json_object_string_add(
7669 json_nexthop_ll
, "ip",
7671 &attr
->mp_nexthop_local
, buf
,
7673 json_object_string_add(json_nexthop_ll
, "afi",
7675 json_object_string_add(json_nexthop_ll
, "scope",
7678 json_object_boolean_true_add(json_nexthop_ll
,
7681 if (!attr
->mp_nexthop_prefer_global
)
7682 json_object_boolean_true_add(
7683 json_nexthop_ll
, "used");
7685 json_object_boolean_true_add(
7686 json_nexthop_global
, "used");
7688 vty_out(vty
, " (%s) %s\n",
7690 &attr
->mp_nexthop_local
, buf
,
7692 attr
->mp_nexthop_prefer_global
7697 /* If we do not have a link-local nexthop then we must flag the
7701 json_object_boolean_true_add(
7702 json_nexthop_global
, "used");
7705 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7706 * Int/Ext/Local, Atomic, best */
7708 json_object_string_add(
7709 json_path
, "origin",
7710 bgp_origin_long_str
[attr
->origin
]);
7712 vty_out(vty
, " Origin %s",
7713 bgp_origin_long_str
[attr
->origin
]);
7715 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7717 json_object_int_add(json_path
, "med",
7720 vty_out(vty
, ", metric %u", attr
->med
);
7723 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7725 json_object_int_add(json_path
, "localpref",
7728 vty_out(vty
, ", localpref %u",
7732 if (attr
->weight
!= 0) {
7734 json_object_int_add(json_path
, "weight",
7737 vty_out(vty
, ", weight %u", attr
->weight
);
7740 if (attr
->tag
!= 0) {
7742 json_object_int_add(json_path
, "tag",
7745 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7749 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7751 json_object_boolean_false_add(json_path
,
7754 vty_out(vty
, ", invalid");
7755 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7757 json_object_boolean_true_add(json_path
,
7760 vty_out(vty
, ", valid");
7763 if (binfo
->peer
!= bgp
->peer_self
) {
7764 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7765 if (CHECK_FLAG(bgp
->config
,
7766 BGP_CONFIG_CONFEDERATION
)) {
7768 json_object_string_add(
7773 ", confed-internal");
7776 json_object_string_add(
7780 vty_out(vty
, ", internal");
7783 if (bgp_confederation_peers_check(
7784 bgp
, binfo
->peer
->as
)) {
7786 json_object_string_add(
7791 ", confed-external");
7794 json_object_string_add(
7798 vty_out(vty
, ", external");
7801 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7803 json_object_boolean_true_add(json_path
,
7805 json_object_boolean_true_add(json_path
,
7808 vty_out(vty
, ", aggregated, local");
7810 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7812 json_object_boolean_true_add(json_path
,
7815 vty_out(vty
, ", sourced");
7818 json_object_boolean_true_add(json_path
,
7820 json_object_boolean_true_add(json_path
,
7823 vty_out(vty
, ", sourced, local");
7827 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7829 json_object_boolean_true_add(json_path
,
7832 vty_out(vty
, ", atomic-aggregate");
7835 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7836 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7837 && bgp_info_mpath_count(binfo
))) {
7839 json_object_boolean_true_add(json_path
,
7842 vty_out(vty
, ", multipath");
7845 // Mark the bestpath(s)
7846 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7847 first_as
= aspath_get_first_as(attr
->aspath
);
7852 json_object_new_object();
7853 json_object_int_add(json_bestpath
,
7854 "bestpathFromAs", first_as
);
7857 vty_out(vty
, ", bestpath-from-AS %u",
7861 ", bestpath-from-AS Local");
7865 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7869 json_object_new_object();
7870 json_object_boolean_true_add(json_bestpath
,
7873 vty_out(vty
, ", best");
7877 json_object_object_add(json_path
, "bestpath",
7883 /* Line 4 display Community */
7884 if (attr
->community
) {
7886 if (!attr
->community
->json
)
7887 community_str(attr
->community
, true);
7888 json_object_lock(attr
->community
->json
);
7889 json_object_object_add(json_path
, "community",
7890 attr
->community
->json
);
7892 vty_out(vty
, " Community: %s\n",
7893 attr
->community
->str
);
7897 /* Line 5 display Extended-community */
7898 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7900 json_ext_community
= json_object_new_object();
7901 json_object_string_add(json_ext_community
,
7903 attr
->ecommunity
->str
);
7904 json_object_object_add(json_path
,
7905 "extendedCommunity",
7906 json_ext_community
);
7908 vty_out(vty
, " Extended Community: %s\n",
7909 attr
->ecommunity
->str
);
7913 /* Line 6 display Large community */
7914 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7916 if (!attr
->lcommunity
->json
)
7917 lcommunity_str(attr
->lcommunity
, true);
7918 json_object_lock(attr
->lcommunity
->json
);
7919 json_object_object_add(json_path
,
7921 attr
->lcommunity
->json
);
7923 vty_out(vty
, " Large Community: %s\n",
7924 attr
->lcommunity
->str
);
7928 /* Line 7 display Originator, Cluster-id */
7929 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7930 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7932 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7934 json_object_string_add(
7935 json_path
, "originatorId",
7936 inet_ntoa(attr
->originator_id
));
7938 vty_out(vty
, " Originator: %s",
7939 inet_ntoa(attr
->originator_id
));
7942 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7947 json_object_new_object();
7948 json_cluster_list_list
=
7949 json_object_new_array();
7952 i
< attr
->cluster
->length
/ 4;
7954 json_string
= json_object_new_string(
7958 json_object_array_add(
7959 json_cluster_list_list
,
7963 /* struct cluster_list does not have
7965 * aspath and community do. Add this
7968 json_object_string_add(json_cluster_list,
7969 "string", attr->cluster->str);
7971 json_object_object_add(
7972 json_cluster_list
, "list",
7973 json_cluster_list_list
);
7974 json_object_object_add(
7975 json_path
, "clusterList",
7978 vty_out(vty
, ", Cluster list: ");
7981 i
< attr
->cluster
->length
/ 4;
7995 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7996 bgp_damp_info_vty(vty
, binfo
, json_path
);
7999 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8000 && safi
!= SAFI_EVPN
) {
8001 mpls_label_t label
=
8002 label_pton(&binfo
->extra
->label
[0]);
8004 json_object_int_add(json_path
, "remoteLabel",
8007 vty_out(vty
, " Remote label: %d\n", label
);
8011 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8013 json_object_int_add(json_path
, "labelIndex",
8016 vty_out(vty
, " Label Index: %d\n",
8020 /* Line 8 display Addpath IDs */
8021 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8023 json_object_int_add(json_path
, "addpathRxId",
8024 binfo
->addpath_rx_id
);
8025 json_object_int_add(json_path
, "addpathTxId",
8026 binfo
->addpath_tx_id
);
8028 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8029 binfo
->addpath_rx_id
,
8030 binfo
->addpath_tx_id
);
8034 /* If we used addpath to TX a non-bestpath we need to display
8035 * "Advertised to" on a path-by-path basis */
8036 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8039 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8041 bgp_addpath_encode_tx(peer
, afi
, safi
);
8042 has_adj
= bgp_adj_out_lookup(
8043 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8045 if ((addpath_capable
&& has_adj
)
8046 || (!addpath_capable
&& has_adj
8047 && CHECK_FLAG(binfo
->flags
,
8048 BGP_INFO_SELECTED
))) {
8049 if (json_path
&& !json_adv_to
)
8051 json_object_new_object();
8053 route_vty_out_advertised_to(
8062 json_object_object_add(json_path
,
8073 /* Line 9 display Uptime */
8074 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8076 json_last_update
= json_object_new_object();
8077 json_object_int_add(json_last_update
, "epoch", tbuf
);
8078 json_object_string_add(json_last_update
, "string",
8080 json_object_object_add(json_path
, "lastUpdate",
8083 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8085 /* Line 10 display PMSI tunnel attribute, if present */
8086 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8087 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8088 attr
->pmsi_tnl_type
,
8089 PMSI_TNLTYPE_STR_DEFAULT
);
8092 json_pmsi
= json_object_new_object();
8093 json_object_string_add(json_pmsi
,
8095 json_object_object_add(json_path
, "pmsi",
8098 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8104 /* We've constructed the json object for this path, add it to the json
8108 if (json_nexthop_global
|| json_nexthop_ll
) {
8109 json_nexthops
= json_object_new_array();
8111 if (json_nexthop_global
)
8112 json_object_array_add(json_nexthops
,
8113 json_nexthop_global
);
8115 if (json_nexthop_ll
)
8116 json_object_array_add(json_nexthops
,
8119 json_object_object_add(json_path
, "nexthops",
8123 json_object_object_add(json_path
, "peer", json_peer
);
8124 json_object_array_add(json_paths
, json_path
);
8129 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8130 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8131 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8133 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8134 const char *prefix_list_str
, afi_t afi
,
8135 safi_t safi
, enum bgp_show_type type
);
8136 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8137 const char *filter
, afi_t afi
, safi_t safi
,
8138 enum bgp_show_type type
);
8139 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8140 const char *rmap_str
, afi_t afi
, safi_t safi
,
8141 enum bgp_show_type type
);
8142 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8143 const char *com
, int exact
, afi_t afi
,
8145 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8146 const char *prefix
, afi_t afi
, safi_t safi
,
8147 enum bgp_show_type type
);
8148 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8149 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8150 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8151 const char *comstr
, int exact
, afi_t afi
,
8152 safi_t safi
, uint8_t use_json
);
8155 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8156 struct bgp_table
*table
, enum bgp_show_type type
,
8157 void *output_arg
, uint8_t use_json
, char *rd
,
8158 int is_last
, unsigned long *output_cum
,
8159 unsigned long *total_cum
,
8160 unsigned long *json_header_depth
)
8162 struct bgp_info
*ri
;
8163 struct bgp_node
*rn
;
8166 unsigned long output_count
= 0;
8167 unsigned long total_count
= 0;
8171 json_object
*json_paths
= NULL
;
8174 if (output_cum
&& *output_cum
!= 0)
8177 if (use_json
&& !*json_header_depth
) {
8179 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8180 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8181 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8182 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8184 table
->version
, inet_ntoa(bgp
->router_id
));
8185 *json_header_depth
= 2;
8187 vty_out(vty
, " \"routeDistinguishers\" : {");
8188 ++*json_header_depth
;
8190 json_paths
= json_object_new_object();
8193 if (use_json
&& rd
) {
8194 vty_out(vty
, " \"%s\" : { ", rd
);
8197 /* Start processing of routes. */
8198 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8199 if (rn
->info
== NULL
)
8204 json_paths
= json_object_new_array();
8208 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8210 if (type
== bgp_show_type_flap_statistics
8211 || type
== bgp_show_type_flap_neighbor
8212 || type
== bgp_show_type_dampend_paths
8213 || type
== bgp_show_type_damp_neighbor
) {
8214 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8217 if (type
== bgp_show_type_regexp
) {
8218 regex_t
*regex
= output_arg
;
8220 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8224 if (type
== bgp_show_type_prefix_list
) {
8225 struct prefix_list
*plist
= output_arg
;
8227 if (prefix_list_apply(plist
, &rn
->p
)
8231 if (type
== bgp_show_type_filter_list
) {
8232 struct as_list
*as_list
= output_arg
;
8234 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8235 != AS_FILTER_PERMIT
)
8238 if (type
== bgp_show_type_route_map
) {
8239 struct route_map
*rmap
= output_arg
;
8240 struct bgp_info binfo
;
8241 struct attr dummy_attr
;
8244 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8246 binfo
.peer
= ri
->peer
;
8247 binfo
.attr
= &dummy_attr
;
8249 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8251 if (ret
== RMAP_DENYMATCH
)
8254 if (type
== bgp_show_type_neighbor
8255 || type
== bgp_show_type_flap_neighbor
8256 || type
== bgp_show_type_damp_neighbor
) {
8257 union sockunion
*su
= output_arg
;
8259 if (ri
->peer
== NULL
8260 || ri
->peer
->su_remote
== NULL
8261 || !sockunion_same(ri
->peer
->su_remote
, su
))
8264 if (type
== bgp_show_type_cidr_only
) {
8265 uint32_t destination
;
8267 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8268 if (IN_CLASSC(destination
)
8269 && rn
->p
.prefixlen
== 24)
8271 if (IN_CLASSB(destination
)
8272 && rn
->p
.prefixlen
== 16)
8274 if (IN_CLASSA(destination
)
8275 && rn
->p
.prefixlen
== 8)
8278 if (type
== bgp_show_type_prefix_longer
) {
8279 struct prefix
*p
= output_arg
;
8281 if (!prefix_match(p
, &rn
->p
))
8284 if (type
== bgp_show_type_community_all
) {
8285 if (!ri
->attr
->community
)
8288 if (type
== bgp_show_type_community
) {
8289 struct community
*com
= output_arg
;
8291 if (!ri
->attr
->community
8292 || !community_match(ri
->attr
->community
,
8296 if (type
== bgp_show_type_community_exact
) {
8297 struct community
*com
= output_arg
;
8299 if (!ri
->attr
->community
8300 || !community_cmp(ri
->attr
->community
, com
))
8303 if (type
== bgp_show_type_community_list
) {
8304 struct community_list
*list
= output_arg
;
8306 if (!community_list_match(ri
->attr
->community
,
8310 if (type
== bgp_show_type_community_list_exact
) {
8311 struct community_list
*list
= output_arg
;
8313 if (!community_list_exact_match(
8314 ri
->attr
->community
, list
))
8317 if (type
== bgp_show_type_lcommunity
) {
8318 struct lcommunity
*lcom
= output_arg
;
8320 if (!ri
->attr
->lcommunity
8321 || !lcommunity_match(ri
->attr
->lcommunity
,
8325 if (type
== bgp_show_type_lcommunity_list
) {
8326 struct community_list
*list
= output_arg
;
8328 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8332 if (type
== bgp_show_type_lcommunity_all
) {
8333 if (!ri
->attr
->lcommunity
)
8336 if (type
== bgp_show_type_dampend_paths
8337 || type
== bgp_show_type_damp_neighbor
) {
8338 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8339 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8343 if (!use_json
&& header
) {
8344 vty_out(vty
, "BGP table version is %" PRIu64
8345 ", local router ID is %s, vrf id ",
8347 inet_ntoa(bgp
->router_id
));
8348 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8349 vty_out(vty
, "%s", VRFID_NONE_STR
);
8351 vty_out(vty
, "%u", bgp
->vrf_id
);
8353 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8354 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8355 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8356 if (type
== bgp_show_type_dampend_paths
8357 || type
== bgp_show_type_damp_neighbor
)
8358 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8359 else if (type
== bgp_show_type_flap_statistics
8360 || type
== bgp_show_type_flap_neighbor
)
8361 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8363 vty_out(vty
, BGP_SHOW_HEADER
);
8366 if (rd
!= NULL
&& !display
&& !output_count
) {
8369 "Route Distinguisher: %s\n",
8372 if (type
== bgp_show_type_dampend_paths
8373 || type
== bgp_show_type_damp_neighbor
)
8374 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8375 safi
, use_json
, json_paths
);
8376 else if (type
== bgp_show_type_flap_statistics
8377 || type
== bgp_show_type_flap_neighbor
)
8378 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8379 safi
, use_json
, json_paths
);
8381 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8392 sprintf(buf2
, "%s/%d",
8393 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8396 vty_out(vty
, "\"%s\": ", buf2
);
8398 vty_out(vty
, ",\"%s\": ", buf2
);
8401 json_object_to_json_string(json_paths
));
8402 json_object_free(json_paths
);
8409 output_count
+= *output_cum
;
8410 *output_cum
= output_count
;
8413 total_count
+= *total_cum
;
8414 *total_cum
= total_count
;
8418 json_object_free(json_paths
);
8420 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8424 for (i
= 0; i
< *json_header_depth
; ++i
)
8425 vty_out(vty
, " } ");
8429 /* No route is displayed */
8430 if (output_count
== 0) {
8431 if (type
== bgp_show_type_normal
)
8433 "No BGP prefixes displayed, %ld exist\n",
8437 "\nDisplayed %ld routes and %ld total paths\n",
8438 output_count
, total_count
);
8445 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8446 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8447 enum bgp_show_type type
, void *output_arg
,
8450 struct bgp_node
*rn
, *next
;
8451 unsigned long output_cum
= 0;
8452 unsigned long total_cum
= 0;
8453 unsigned long json_header_depth
= 0;
8456 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8458 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8459 next
= bgp_route_next(rn
);
8460 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8462 if (rn
->info
!= NULL
) {
8463 struct prefix_rd prd
;
8464 char rd
[RD_ADDRSTRLEN
];
8466 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8467 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8468 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8469 output_arg
, use_json
, rd
, next
== NULL
,
8470 &output_cum
, &total_cum
,
8471 &json_header_depth
);
8477 if (output_cum
== 0)
8478 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8482 "\nDisplayed %ld routes and %ld total paths\n",
8483 output_cum
, total_cum
);
8487 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8488 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8490 struct bgp_table
*table
;
8491 unsigned long json_header_depth
= 0;
8494 bgp
= bgp_get_default();
8499 vty_out(vty
, "No BGP process is configured\n");
8501 vty_out(vty
, "{}\n");
8505 table
= bgp
->rib
[afi
][safi
];
8506 /* use MPLS and ENCAP specific shows until they are merged */
8507 if (safi
== SAFI_MPLS_VPN
) {
8508 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8509 output_arg
, use_json
);
8512 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8513 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8514 output_arg
, use_json
,
8517 /* labeled-unicast routes live in the unicast table */
8518 else if (safi
== SAFI_LABELED_UNICAST
)
8519 safi
= SAFI_UNICAST
;
8521 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8522 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8525 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8526 safi_t safi
, uint8_t use_json
)
8528 struct listnode
*node
, *nnode
;
8533 vty_out(vty
, "{\n");
8535 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8538 vty_out(vty
, ",\n");
8542 vty_out(vty
, "\"%s\":",
8543 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8547 vty_out(vty
, "\nInstance %s:\n",
8548 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8552 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8557 vty_out(vty
, "}\n");
8560 /* Header of detailed BGP route information */
8561 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8562 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8563 afi_t afi
, safi_t safi
, json_object
*json
)
8565 struct bgp_info
*ri
;
8568 struct listnode
*node
, *nnode
;
8569 char buf1
[RD_ADDRSTRLEN
];
8570 char buf2
[INET6_ADDRSTRLEN
];
8571 char buf3
[EVPN_ROUTE_STRLEN
];
8572 char prefix_str
[BUFSIZ
];
8577 int no_advertise
= 0;
8580 int has_valid_label
= 0;
8581 mpls_label_t label
= 0;
8582 json_object
*json_adv_to
= NULL
;
8585 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8587 if (has_valid_label
)
8588 label
= label_pton(&rn
->local_label
);
8591 if (has_valid_label
)
8592 json_object_int_add(json
, "localLabel", label
);
8594 json_object_string_add(
8596 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8598 if (safi
== SAFI_EVPN
)
8599 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8600 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8603 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8604 buf3
, sizeof(buf3
)));
8606 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8607 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8608 ? prefix_rd2str(prd
, buf1
,
8611 safi
== SAFI_MPLS_VPN
? ":" : "",
8612 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8616 if (has_valid_label
)
8617 vty_out(vty
, "Local label: %d\n", label
);
8618 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8619 vty_out(vty
, "not allocated\n");
8622 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8624 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8626 if (ri
->extra
&& ri
->extra
->suppress
)
8628 if (ri
->attr
->community
!= NULL
) {
8629 if (community_include(ri
->attr
->community
,
8630 COMMUNITY_NO_ADVERTISE
))
8632 if (community_include(ri
->attr
->community
,
8633 COMMUNITY_NO_EXPORT
))
8635 if (community_include(ri
->attr
->community
,
8636 COMMUNITY_LOCAL_AS
))
8643 vty_out(vty
, "Paths: (%d available", count
);
8645 vty_out(vty
, ", best #%d", best
);
8646 if (safi
== SAFI_UNICAST
)
8647 vty_out(vty
, ", table %s",
8649 == BGP_INSTANCE_TYPE_DEFAULT
)
8650 ? "Default-IP-Routing-Table"
8653 vty_out(vty
, ", no best path");
8656 vty_out(vty
, ", not advertised to any peer");
8658 vty_out(vty
, ", not advertised to EBGP peer");
8660 vty_out(vty
, ", not advertised outside local AS");
8664 ", Advertisements suppressed by an aggregate.");
8665 vty_out(vty
, ")\n");
8668 /* If we are not using addpath then we can display Advertised to and
8670 * show what peers we advertised the bestpath to. If we are using
8672 * though then we must display Advertised to on a path-by-path basis. */
8673 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8674 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8675 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8676 if (json
&& !json_adv_to
)
8677 json_adv_to
= json_object_new_object();
8679 route_vty_out_advertised_to(
8681 " Advertised to non peer-group peers:\n ",
8688 json_object_object_add(json
, "advertisedTo",
8693 vty_out(vty
, " Not advertised to any peer");
8699 /* Display specified route of BGP table. */
8700 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8701 struct bgp_table
*rib
, const char *ip_str
,
8702 afi_t afi
, safi_t safi
,
8703 struct prefix_rd
*prd
, int prefix_check
,
8704 enum bgp_path_type pathtype
,
8710 struct prefix match
;
8711 struct bgp_node
*rn
;
8712 struct bgp_node
*rm
;
8713 struct bgp_info
*ri
;
8714 struct bgp_table
*table
;
8715 json_object
*json
= NULL
;
8716 json_object
*json_paths
= NULL
;
8718 /* Check IP address argument. */
8719 ret
= str2prefix(ip_str
, &match
);
8721 vty_out(vty
, "address is malformed\n");
8725 match
.family
= afi2family(afi
);
8728 json
= json_object_new_object();
8729 json_paths
= json_object_new_array();
8732 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8733 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8734 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8737 if ((table
= rn
->info
) == NULL
)
8742 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8746 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8747 bgp_unlock_node(rm
);
8751 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8753 route_vty_out_detail_header(
8755 (struct prefix_rd
*)&rn
->p
,
8756 AFI_IP
, safi
, json
);
8761 if (pathtype
== BGP_PATH_ALL
8762 || (pathtype
== BGP_PATH_BESTPATH
8763 && CHECK_FLAG(ri
->flags
,
8765 || (pathtype
== BGP_PATH_MULTIPATH
8766 && (CHECK_FLAG(ri
->flags
,
8768 || CHECK_FLAG(ri
->flags
,
8769 BGP_INFO_SELECTED
))))
8770 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8775 bgp_unlock_node(rm
);
8777 } else if (safi
== SAFI_FLOWSPEC
) {
8778 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
8779 &match
, prefix_check
,
8786 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8788 || rn
->p
.prefixlen
== match
.prefixlen
) {
8789 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8791 route_vty_out_detail_header(
8792 vty
, bgp
, rn
, NULL
, afi
,
8798 if (pathtype
== BGP_PATH_ALL
8799 || (pathtype
== BGP_PATH_BESTPATH
8803 || (pathtype
== BGP_PATH_MULTIPATH
8809 BGP_INFO_SELECTED
))))
8810 route_vty_out_detail(
8811 vty
, bgp
, &rn
->p
, ri
,
8812 afi
, safi
, json_paths
);
8816 bgp_unlock_node(rn
);
8822 json_object_object_add(json
, "paths", json_paths
);
8824 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8825 json
, JSON_C_TO_STRING_PRETTY
));
8826 json_object_free(json
);
8829 vty_out(vty
, "%% Network not in table\n");
8837 /* Display specified route of Main RIB */
8838 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8839 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8840 int prefix_check
, enum bgp_path_type pathtype
,
8844 bgp
= bgp_get_default();
8847 vty_out(vty
, "No BGP process is configured\n");
8849 vty_out(vty
, "{}\n");
8854 /* labeled-unicast routes live in the unicast table */
8855 if (safi
== SAFI_LABELED_UNICAST
)
8856 safi
= SAFI_UNICAST
;
8858 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8859 afi
, safi
, prd
, prefix_check
, pathtype
,
8863 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8864 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8867 struct lcommunity
*lcom
;
8873 b
= buffer_new(1024);
8874 for (i
= 0; i
< argc
; i
++) {
8876 buffer_putc(b
, ' ');
8878 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8880 buffer_putstr(b
, argv
[i
]->arg
);
8884 buffer_putc(b
, '\0');
8886 str
= buffer_getstr(b
);
8889 lcom
= lcommunity_str2com(str
);
8890 XFREE(MTYPE_TMP
, str
);
8892 vty_out(vty
, "%% Large-community malformed\n");
8896 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8900 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8901 const char *lcom
, afi_t afi
, safi_t safi
,
8904 struct community_list
*list
;
8906 list
= community_list_lookup(bgp_clist
, lcom
,
8907 LARGE_COMMUNITY_LIST_MASTER
);
8909 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8914 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8918 DEFUN (show_ip_bgp_large_community_list
,
8919 show_ip_bgp_large_community_list_cmd
,
8920 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8924 BGP_INSTANCE_HELP_STR
8926 BGP_SAFI_WITH_LABEL_HELP_STR
8927 "Display routes matching the large-community-list\n"
8928 "large-community-list number\n"
8929 "large-community-list name\n"
8933 afi_t afi
= AFI_IP6
;
8934 safi_t safi
= SAFI_UNICAST
;
8937 if (argv_find(argv
, argc
, "ip", &idx
))
8939 if (argv_find(argv
, argc
, "view", &idx
)
8940 || argv_find(argv
, argc
, "vrf", &idx
))
8941 vrf
= argv
[++idx
]->arg
;
8942 if (argv_find(argv
, argc
, "ipv4", &idx
)
8943 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8944 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8945 if (argv_find(argv
, argc
, "unicast", &idx
)
8946 || argv_find(argv
, argc
, "multicast", &idx
))
8947 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8950 int uj
= use_json(argc
, argv
);
8952 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8954 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8958 argv_find(argv
, argc
, "large-community-list", &idx
);
8959 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8962 DEFUN (show_ip_bgp_large_community
,
8963 show_ip_bgp_large_community_cmd
,
8964 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8968 BGP_INSTANCE_HELP_STR
8970 BGP_SAFI_WITH_LABEL_HELP_STR
8971 "Display routes matching the large-communities\n"
8972 "List of large-community numbers\n"
8976 afi_t afi
= AFI_IP6
;
8977 safi_t safi
= SAFI_UNICAST
;
8980 if (argv_find(argv
, argc
, "ip", &idx
))
8982 if (argv_find(argv
, argc
, "view", &idx
)
8983 || argv_find(argv
, argc
, "vrf", &idx
))
8984 vrf
= argv
[++idx
]->arg
;
8985 if (argv_find(argv
, argc
, "ipv4", &idx
)
8986 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8987 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8988 if (argv_find(argv
, argc
, "unicast", &idx
)
8989 || argv_find(argv
, argc
, "multicast", &idx
))
8990 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8993 int uj
= use_json(argc
, argv
);
8995 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8997 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9001 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9002 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9004 return bgp_show(vty
, bgp
, afi
, safi
,
9005 bgp_show_type_lcommunity_all
, NULL
, uj
);
9008 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9012 /* BGP route print out function without JSON */
9015 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9016 <dampening <parameters>\
9021 |community-list <(1-500)|WORD> [exact-match]\
9022 |A.B.C.D/M longer-prefixes\
9023 |X:X::X:X/M longer-prefixes\
9028 BGP_INSTANCE_HELP_STR
9030 BGP_SAFI_WITH_LABEL_HELP_STR
9031 "Display detailed information about dampening\n"
9032 "Display detail of configured dampening parameters\n"
9033 "Display routes matching the route-map\n"
9034 "A route-map to match on\n"
9035 "Display routes conforming to the prefix-list\n"
9036 "Prefix-list name\n"
9037 "Display routes conforming to the filter-list\n"
9038 "Regular expression access list name\n"
9039 "BGP RIB advertisement statistics\n"
9040 "Display routes matching the community-list\n"
9041 "community-list number\n"
9042 "community-list name\n"
9043 "Exact match of the communities\n"
9045 "Display route and more specific routes\n"
9047 "Display route and more specific routes\n")
9049 afi_t afi
= AFI_IP6
;
9050 safi_t safi
= SAFI_UNICAST
;
9051 int exact_match
= 0;
9052 struct bgp
*bgp
= NULL
;
9055 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9060 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9061 if (argv_find(argv
, argc
, "parameters", &idx
))
9062 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9065 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9066 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9067 safi
, bgp_show_type_prefix_list
);
9069 if (argv_find(argv
, argc
, "filter-list", &idx
))
9070 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9071 safi
, bgp_show_type_filter_list
);
9073 if (argv_find(argv
, argc
, "statistics", &idx
))
9074 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9076 if (argv_find(argv
, argc
, "route-map", &idx
))
9077 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9078 safi
, bgp_show_type_route_map
);
9080 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9081 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9082 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9084 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9085 exact_match
, afi
, safi
);
9088 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9089 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9090 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9092 bgp_show_type_prefix_longer
);
9097 /* BGP route print out function with JSON */
9098 DEFUN (show_ip_bgp_json
,
9099 show_ip_bgp_json_cmd
,
9100 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9103 |dampening <flap-statistics|dampened-paths>\
9104 |community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown>] [exact-match]\
9109 BGP_INSTANCE_HELP_STR
9111 BGP_SAFI_WITH_LABEL_HELP_STR
9112 "Display only routes with non-natural netmasks\n"
9113 "Display detailed information about dampening\n"
9114 "Display flap statistics of routes\n"
9115 "Display paths suppressed due to dampening\n"
9116 "Display routes matching the communities\n"
9118 "Do not send outside local AS (well-known community)\n"
9119 "Do not advertise to any peer (well-known community)\n"
9120 "Do not export to next AS (well-known community)\n"
9121 "Graceful shutdown (well-known community)\n"
9122 "Exact match of the communities\n"
9125 afi_t afi
= AFI_IP6
;
9126 safi_t safi
= SAFI_UNICAST
;
9127 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9128 struct bgp
*bgp
= NULL
;
9130 int idx_community_type
= 0;
9131 int exact_match
= 0;
9133 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9138 int uj
= use_json(argc
, argv
);
9142 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9143 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9146 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9147 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9148 return bgp_show(vty
, bgp
, afi
, safi
,
9149 bgp_show_type_dampend_paths
, NULL
, uj
);
9150 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9151 return bgp_show(vty
, bgp
, afi
, safi
,
9152 bgp_show_type_flap_statistics
, NULL
,
9156 if (argv_find(argv
, argc
, "community", &idx
)) {
9158 /* show a specific community */
9159 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
) ||
9160 argv_find(argv
, argc
, "no-advertise",
9161 &idx_community_type
) ||
9162 argv_find(argv
, argc
, "no-export",
9163 &idx_community_type
) ||
9164 argv_find(argv
, argc
, "graceful-shutdown",
9165 &idx_community_type
) ||
9166 argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9167 if (argv_find(argv
, argc
, "exact-match", &idx
))
9170 return (bgp_show_community(vty
, bgp
,
9171 argv
[idx_community_type
]->arg
,
9172 exact_match
, afi
, safi
, uj
));
9175 /* show all communities */
9176 return (bgp_show(vty
, bgp
, afi
, safi
,
9177 bgp_show_type_community_all
, NULL
,
9182 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9185 DEFUN (show_ip_bgp_route
,
9186 show_ip_bgp_route_cmd
,
9187 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9188 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9192 BGP_INSTANCE_HELP_STR
9194 BGP_SAFI_WITH_LABEL_HELP_STR
9195 "Network in the BGP routing table to display\n"
9197 "Network in the BGP routing table to display\n"
9199 "Display only the bestpath\n"
9200 "Display only multipaths\n"
9203 int prefix_check
= 0;
9205 afi_t afi
= AFI_IP6
;
9206 safi_t safi
= SAFI_UNICAST
;
9207 char *prefix
= NULL
;
9208 struct bgp
*bgp
= NULL
;
9209 enum bgp_path_type path_type
;
9210 uint8_t uj
= use_json(argc
, argv
);
9214 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9221 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9225 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9226 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9227 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9229 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9230 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9233 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9234 && afi
!= AFI_IP6
) {
9236 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9239 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9242 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9246 prefix
= argv
[idx
]->arg
;
9248 /* [<bestpath|multipath>] */
9249 if (argv_find(argv
, argc
, "bestpath", &idx
))
9250 path_type
= BGP_PATH_BESTPATH
;
9251 else if (argv_find(argv
, argc
, "multipath", &idx
))
9252 path_type
= BGP_PATH_MULTIPATH
;
9254 path_type
= BGP_PATH_ALL
;
9256 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9260 DEFUN (show_ip_bgp_regexp
,
9261 show_ip_bgp_regexp_cmd
,
9262 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9266 BGP_INSTANCE_HELP_STR
9268 BGP_SAFI_WITH_LABEL_HELP_STR
9269 "Display routes matching the AS path regular expression\n"
9270 "A regular-expression to match the BGP AS paths\n")
9272 afi_t afi
= AFI_IP6
;
9273 safi_t safi
= SAFI_UNICAST
;
9274 struct bgp
*bgp
= NULL
;
9277 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9282 // get index of regex
9283 argv_find(argv
, argc
, "regexp", &idx
);
9286 char *regstr
= argv_concat(argv
, argc
, idx
);
9287 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9288 bgp_show_type_regexp
);
9289 XFREE(MTYPE_TMP
, regstr
);
9293 DEFUN (show_ip_bgp_instance_all
,
9294 show_ip_bgp_instance_all_cmd
,
9295 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9299 BGP_INSTANCE_ALL_HELP_STR
9301 BGP_SAFI_WITH_LABEL_HELP_STR
9305 safi_t safi
= SAFI_UNICAST
;
9306 struct bgp
*bgp
= NULL
;
9309 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9314 int uj
= use_json(argc
, argv
);
9318 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9322 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9323 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9328 regex
= bgp_regcomp(regstr
);
9330 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9334 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9335 bgp_regex_free(regex
);
9339 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9340 const char *prefix_list_str
, afi_t afi
,
9341 safi_t safi
, enum bgp_show_type type
)
9343 struct prefix_list
*plist
;
9345 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9346 if (plist
== NULL
) {
9347 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9352 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9355 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9356 const char *filter
, afi_t afi
, safi_t safi
,
9357 enum bgp_show_type type
)
9359 struct as_list
*as_list
;
9361 as_list
= as_list_lookup(filter
);
9362 if (as_list
== NULL
) {
9363 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9368 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9371 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9372 const char *rmap_str
, afi_t afi
, safi_t safi
,
9373 enum bgp_show_type type
)
9375 struct route_map
*rmap
;
9377 rmap
= route_map_lookup_by_name(rmap_str
);
9379 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9383 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9386 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9387 const char *comstr
, int exact
, afi_t afi
,
9388 safi_t safi
, uint8_t use_json
)
9390 struct community
*com
;
9393 com
= community_str2com(comstr
);
9395 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9399 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9400 (exact
? bgp_show_type_community_exact
9401 : bgp_show_type_community
),
9403 community_free(com
);
9408 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9409 const char *com
, int exact
, afi_t afi
,
9412 struct community_list
*list
;
9414 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9416 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9420 return bgp_show(vty
, bgp
, afi
, safi
,
9421 (exact
? bgp_show_type_community_list_exact
9422 : bgp_show_type_community_list
),
9426 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9427 const char *prefix
, afi_t afi
, safi_t safi
,
9428 enum bgp_show_type type
)
9435 ret
= str2prefix(prefix
, p
);
9437 vty_out(vty
, "%% Malformed Prefix\n");
9441 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9446 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9447 const char *ip_str
, uint8_t use_json
)
9453 /* Get peer sockunion. */
9454 ret
= str2sockunion(ip_str
, &su
);
9456 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9458 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9462 json_object
*json_no
= NULL
;
9463 json_no
= json_object_new_object();
9464 json_object_string_add(
9466 "malformedAddressOrName",
9468 vty_out(vty
, "%s\n",
9469 json_object_to_json_string_ext(
9471 JSON_C_TO_STRING_PRETTY
));
9472 json_object_free(json_no
);
9475 "%% Malformed address or name: %s\n",
9483 /* Peer structure lookup. */
9484 peer
= peer_lookup(bgp
, &su
);
9487 json_object
*json_no
= NULL
;
9488 json_no
= json_object_new_object();
9489 json_object_string_add(json_no
, "warning",
9490 "No such neighbor in this view/vrf");
9491 vty_out(vty
, "%s\n",
9492 json_object_to_json_string_ext(
9493 json_no
, JSON_C_TO_STRING_PRETTY
));
9494 json_object_free(json_no
);
9496 vty_out(vty
, "No such neighbor in this view/vrf\n");
9504 BGP_STATS_MAXBITLEN
= 0,
9508 BGP_STATS_UNAGGREGATEABLE
,
9509 BGP_STATS_MAX_AGGREGATEABLE
,
9510 BGP_STATS_AGGREGATES
,
9512 BGP_STATS_ASPATH_COUNT
,
9513 BGP_STATS_ASPATH_MAXHOPS
,
9514 BGP_STATS_ASPATH_TOTHOPS
,
9515 BGP_STATS_ASPATH_MAXSIZE
,
9516 BGP_STATS_ASPATH_TOTSIZE
,
9517 BGP_STATS_ASN_HIGHEST
,
9521 static const char *table_stats_strs
[] = {
9522 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9523 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9524 [BGP_STATS_RIB
] = "Total Advertisements",
9525 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9526 [BGP_STATS_MAX_AGGREGATEABLE
] =
9527 "Maximum aggregateable prefixes",
9528 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9529 [BGP_STATS_SPACE
] = "Address space advertised",
9530 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9531 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9532 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9533 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9534 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9535 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9536 [BGP_STATS_MAX
] = NULL
,
9539 struct bgp_table_stats
{
9540 struct bgp_table
*table
;
9541 unsigned long long counts
[BGP_STATS_MAX
];
9546 #define TALLY_SIGFIG 100000
9547 static unsigned long
9548 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9550 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9551 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9552 unsigned long ret
= newtot
/ count
;
9554 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9561 static int bgp_table_stats_walker(struct thread
*t
)
9563 struct bgp_node
*rn
;
9564 struct bgp_node
*top
;
9565 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9566 unsigned int space
= 0;
9568 if (!(top
= bgp_table_top(ts
->table
)))
9571 switch (top
->p
.family
) {
9573 space
= IPV4_MAX_BITLEN
;
9576 space
= IPV6_MAX_BITLEN
;
9580 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9582 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9583 struct bgp_info
*ri
;
9584 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9585 unsigned int rinum
= 0;
9593 ts
->counts
[BGP_STATS_PREFIXES
]++;
9594 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9597 ts
->counts
[BGP_STATS_AVGPLEN
]
9598 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9599 ts
->counts
[BGP_STATS_AVGPLEN
],
9603 /* check if the prefix is included by any other announcements */
9604 while (prn
&& !prn
->info
)
9605 prn
= bgp_node_parent_nolock(prn
);
9607 if (prn
== NULL
|| prn
== top
) {
9608 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9609 /* announced address space */
9612 pow(2.0, space
- rn
->p
.prefixlen
);
9613 } else if (prn
->info
)
9614 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9616 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9618 ts
->counts
[BGP_STATS_RIB
]++;
9621 && (CHECK_FLAG(ri
->attr
->flag
,
9623 BGP_ATTR_ATOMIC_AGGREGATE
))))
9624 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9627 if (ri
->attr
&& ri
->attr
->aspath
) {
9629 aspath_count_hops(ri
->attr
->aspath
);
9631 aspath_size(ri
->attr
->aspath
);
9632 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9634 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9636 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9637 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9640 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9641 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9644 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9645 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9647 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9648 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9649 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9651 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9652 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9653 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9656 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9657 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9665 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9668 struct bgp_table_stats ts
;
9671 if (!bgp
->rib
[afi
][safi
]) {
9672 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9677 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9679 /* labeled-unicast routes live in the unicast table */
9680 if (safi
== SAFI_LABELED_UNICAST
)
9681 safi
= SAFI_UNICAST
;
9683 memset(&ts
, 0, sizeof(ts
));
9684 ts
.table
= bgp
->rib
[afi
][safi
];
9685 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9687 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9688 if (!table_stats_strs
[i
])
9693 case BGP_STATS_ASPATH_AVGHOPS
:
9694 case BGP_STATS_ASPATH_AVGSIZE
:
9695 case BGP_STATS_AVGPLEN
:
9696 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9697 vty_out (vty
, "%12.2f",
9698 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9701 case BGP_STATS_ASPATH_TOTHOPS
:
9702 case BGP_STATS_ASPATH_TOTSIZE
:
9703 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9704 vty_out(vty
, "%12.2f",
9706 ? (float)ts
.counts
[i
]
9708 [BGP_STATS_ASPATH_COUNT
]
9711 case BGP_STATS_TOTPLEN
:
9712 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9713 vty_out(vty
, "%12.2f",
9715 ? (float)ts
.counts
[i
]
9717 [BGP_STATS_PREFIXES
]
9720 case BGP_STATS_SPACE
:
9721 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9722 vty_out(vty
, "%12g\n", ts
.total_space
);
9724 if (afi
== AFI_IP6
) {
9725 vty_out(vty
, "%30s: ", "/32 equivalent ");
9726 vty_out(vty
, "%12g\n",
9727 ts
.total_space
* pow(2.0, -128 + 32));
9728 vty_out(vty
, "%30s: ", "/48 equivalent ");
9729 vty_out(vty
, "%12g\n",
9730 ts
.total_space
* pow(2.0, -128 + 48));
9732 vty_out(vty
, "%30s: ", "% announced ");
9733 vty_out(vty
, "%12.2f\n",
9734 ts
.total_space
* 100. * pow(2.0, -32));
9735 vty_out(vty
, "%30s: ", "/8 equivalent ");
9736 vty_out(vty
, "%12.2f\n",
9737 ts
.total_space
* pow(2.0, -32 + 8));
9738 vty_out(vty
, "%30s: ", "/24 equivalent ");
9739 vty_out(vty
, "%12.2f\n",
9740 ts
.total_space
* pow(2.0, -32 + 24));
9744 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9745 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9762 PCOUNT_PFCNT
, /* the figure we display to users */
9766 static const char *pcount_strs
[] = {
9767 [PCOUNT_ADJ_IN
] = "Adj-in",
9768 [PCOUNT_DAMPED
] = "Damped",
9769 [PCOUNT_REMOVED
] = "Removed",
9770 [PCOUNT_HISTORY
] = "History",
9771 [PCOUNT_STALE
] = "Stale",
9772 [PCOUNT_VALID
] = "Valid",
9773 [PCOUNT_ALL
] = "All RIB",
9774 [PCOUNT_COUNTED
] = "PfxCt counted",
9775 [PCOUNT_PFCNT
] = "Useable",
9776 [PCOUNT_MAX
] = NULL
,
9779 struct peer_pcounts
{
9780 unsigned int count
[PCOUNT_MAX
];
9781 const struct peer
*peer
;
9782 const struct bgp_table
*table
;
9785 static int bgp_peer_count_walker(struct thread
*t
)
9787 struct bgp_node
*rn
;
9788 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9789 const struct peer
*peer
= pc
->peer
;
9791 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9792 struct bgp_adj_in
*ain
;
9793 struct bgp_info
*ri
;
9795 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9796 if (ain
->peer
== peer
)
9797 pc
->count
[PCOUNT_ADJ_IN
]++;
9799 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9800 char buf
[SU_ADDRSTRLEN
];
9802 if (ri
->peer
!= peer
)
9805 pc
->count
[PCOUNT_ALL
]++;
9807 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9808 pc
->count
[PCOUNT_DAMPED
]++;
9809 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9810 pc
->count
[PCOUNT_HISTORY
]++;
9811 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9812 pc
->count
[PCOUNT_REMOVED
]++;
9813 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9814 pc
->count
[PCOUNT_STALE
]++;
9815 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9816 pc
->count
[PCOUNT_VALID
]++;
9817 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9818 pc
->count
[PCOUNT_PFCNT
]++;
9820 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9821 pc
->count
[PCOUNT_COUNTED
]++;
9822 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9824 "%s [pcount] %s/%d is counted but flags 0x%x",
9826 inet_ntop(rn
->p
.family
,
9827 &rn
->p
.u
.prefix
, buf
,
9829 rn
->p
.prefixlen
, ri
->flags
);
9831 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9833 "%s [pcount] %s/%d not counted but flags 0x%x",
9835 inet_ntop(rn
->p
.family
,
9836 &rn
->p
.u
.prefix
, buf
,
9838 rn
->p
.prefixlen
, ri
->flags
);
9845 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9846 safi_t safi
, uint8_t use_json
)
9848 struct peer_pcounts pcounts
= {.peer
= peer
};
9850 json_object
*json
= NULL
;
9851 json_object
*json_loop
= NULL
;
9854 json
= json_object_new_object();
9855 json_loop
= json_object_new_object();
9858 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9859 || !peer
->bgp
->rib
[afi
][safi
]) {
9861 json_object_string_add(
9863 "No such neighbor or address family");
9864 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9865 json_object_free(json
);
9867 vty_out(vty
, "%% No such neighbor or address family\n");
9872 memset(&pcounts
, 0, sizeof(pcounts
));
9873 pcounts
.peer
= peer
;
9874 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9876 /* in-place call via thread subsystem so as to record execution time
9877 * stats for the thread-walk (i.e. ensure this can't be blamed on
9878 * on just vty_read()).
9880 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9883 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9884 json_object_string_add(json
, "multiProtocol",
9885 afi_safi_print(afi
, safi
));
9886 json_object_int_add(json
, "pfxCounter",
9887 peer
->pcount
[afi
][safi
]);
9889 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9890 json_object_int_add(json_loop
, pcount_strs
[i
],
9893 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9895 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9896 json_object_string_add(json
, "pfxctDriftFor",
9898 json_object_string_add(
9899 json
, "recommended",
9900 "Please report this bug, with the above command output");
9902 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9903 json
, JSON_C_TO_STRING_PRETTY
));
9904 json_object_free(json
);
9908 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9909 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9910 peer
->hostname
, peer
->host
,
9911 afi_safi_print(afi
, safi
));
9913 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9914 afi_safi_print(afi
, safi
));
9917 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9918 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9920 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9921 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9924 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9925 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9927 "Please report this bug, with the above command output\n");
9934 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9935 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9936 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9937 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9941 BGP_INSTANCE_HELP_STR
9944 "Detailed information on TCP and BGP neighbor connections\n"
9945 "Neighbor to display information about\n"
9946 "Neighbor to display information about\n"
9947 "Neighbor on BGP configured interface\n"
9948 "Display detailed prefix count information\n"
9951 afi_t afi
= AFI_IP6
;
9952 safi_t safi
= SAFI_UNICAST
;
9955 struct bgp
*bgp
= NULL
;
9957 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9962 int uj
= use_json(argc
, argv
);
9966 argv_find(argv
, argc
, "neighbors", &idx
);
9967 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9971 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9974 #ifdef KEEP_OLD_VPN_COMMANDS
9975 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9976 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9977 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9982 "Display information about all VPNv4 NLRIs\n"
9983 "Detailed information on TCP and BGP neighbor connections\n"
9984 "Neighbor to display information about\n"
9985 "Neighbor to display information about\n"
9986 "Neighbor on BGP configured interface\n"
9987 "Display detailed prefix count information\n"
9992 uint8_t uj
= use_json(argc
, argv
);
9994 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9998 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10001 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10002 show_ip_bgp_vpn_all_route_prefix_cmd
,
10003 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10008 "Display information about all VPNv4 NLRIs\n"
10009 "Network in the BGP routing table to display\n"
10010 "Network in the BGP routing table to display\n"
10014 char *network
= NULL
;
10015 struct bgp
*bgp
= bgp_get_default();
10017 vty_out(vty
, "Can't find default instance\n");
10018 return CMD_WARNING
;
10021 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10022 network
= argv
[idx
]->arg
;
10023 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10024 network
= argv
[idx
]->arg
;
10026 vty_out(vty
, "Unable to figure out Network\n");
10027 return CMD_WARNING
;
10030 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10031 BGP_PATH_ALL
, use_json(argc
, argv
));
10033 #endif /* KEEP_OLD_VPN_COMMANDS */
10035 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10036 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10037 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10043 "Display information about all EVPN NLRIs\n"
10044 "Network in the BGP routing table to display\n"
10045 "Network in the BGP routing table to display\n"
10049 char *network
= NULL
;
10051 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10052 network
= argv
[idx
]->arg
;
10053 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10054 network
= argv
[idx
]->arg
;
10056 vty_out(vty
, "Unable to figure out Network\n");
10057 return CMD_WARNING
;
10059 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10060 BGP_PATH_ALL
, use_json(argc
, argv
));
10063 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10064 safi_t safi
, enum bgp_show_adj_route_type type
,
10065 const char *rmap_name
, uint8_t use_json
,
10068 struct bgp_table
*table
;
10069 struct bgp_adj_in
*ain
;
10070 struct bgp_adj_out
*adj
;
10071 unsigned long output_count
;
10072 unsigned long filtered_count
;
10073 struct bgp_node
*rn
;
10079 struct update_subgroup
*subgrp
;
10080 json_object
*json_scode
= NULL
;
10081 json_object
*json_ocode
= NULL
;
10082 json_object
*json_ar
= NULL
;
10083 struct peer_af
*paf
;
10084 bool route_filtered
;
10087 json_scode
= json_object_new_object();
10088 json_ocode
= json_object_new_object();
10089 json_ar
= json_object_new_object();
10091 json_object_string_add(json_scode
, "suppressed", "s");
10092 json_object_string_add(json_scode
, "damped", "d");
10093 json_object_string_add(json_scode
, "history", "h");
10094 json_object_string_add(json_scode
, "valid", "*");
10095 json_object_string_add(json_scode
, "best", ">");
10096 json_object_string_add(json_scode
, "multipath", "=");
10097 json_object_string_add(json_scode
, "internal", "i");
10098 json_object_string_add(json_scode
, "ribFailure", "r");
10099 json_object_string_add(json_scode
, "stale", "S");
10100 json_object_string_add(json_scode
, "removed", "R");
10102 json_object_string_add(json_ocode
, "igp", "i");
10103 json_object_string_add(json_ocode
, "egp", "e");
10104 json_object_string_add(json_ocode
, "incomplete", "?");
10111 json_object_string_add(json
, "alert", "no BGP");
10112 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10113 json_object_free(json
);
10115 vty_out(vty
, "%% No bgp\n");
10119 table
= bgp
->rib
[afi
][safi
];
10121 output_count
= filtered_count
= 0;
10122 subgrp
= peer_subgroup(peer
, afi
, safi
);
10124 if (type
== bgp_show_adj_route_advertised
&& subgrp
10125 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10127 json_object_int_add(json
, "bgpTableVersion",
10129 json_object_string_add(json
, "bgpLocalRouterId",
10130 inet_ntoa(bgp
->router_id
));
10131 json_object_object_add(json
, "bgpStatusCodes",
10133 json_object_object_add(json
, "bgpOriginCodes",
10135 json_object_string_add(
10136 json
, "bgpOriginatingDefaultNetwork",
10137 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10139 vty_out(vty
, "BGP table version is %" PRIu64
10140 ", local router ID is %s, vrf id ",
10141 table
->version
, inet_ntoa(bgp
->router_id
));
10142 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10143 vty_out(vty
, "%s", VRFID_NONE_STR
);
10145 vty_out(vty
, "%u", bgp
->vrf_id
);
10146 vty_out(vty
, "\n");
10147 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10148 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10149 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10151 vty_out(vty
, "Originating default network %s\n\n",
10152 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10157 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10158 if (type
== bgp_show_adj_route_received
10159 || type
== bgp_show_adj_route_filtered
) {
10160 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10161 if (ain
->peer
!= peer
|| !ain
->attr
)
10166 json_object_int_add(
10167 json
, "bgpTableVersion",
10169 json_object_string_add(
10171 "bgpLocalRouterId",
10174 json_object_object_add(
10175 json
, "bgpStatusCodes",
10177 json_object_object_add(
10178 json
, "bgpOriginCodes",
10182 "BGP table version is 0, local router ID is %s, vrf id ",
10185 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10191 vty_out(vty
, "\n");
10193 BGP_SHOW_SCODE_HEADER
);
10195 BGP_SHOW_NCODE_HEADER
);
10197 BGP_SHOW_OCODE_HEADER
);
10203 vty_out(vty
, BGP_SHOW_HEADER
);
10207 bgp_attr_dup(&attr
, ain
->attr
);
10208 route_filtered
= false;
10210 /* Filter prefix using distribute list,
10211 * filter list or prefix list
10213 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10214 safi
)) == FILTER_DENY
)
10215 route_filtered
= true;
10217 /* Filter prefix using route-map */
10218 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10219 afi
, safi
, rmap_name
);
10221 if (type
== bgp_show_adj_route_filtered
&&
10222 !route_filtered
&& ret
!= RMAP_DENY
) {
10223 bgp_attr_undup(&attr
, ain
->attr
);
10227 if (type
== bgp_show_adj_route_received
&&
10228 (route_filtered
|| ret
== RMAP_DENY
))
10231 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10232 use_json
, json_ar
);
10233 bgp_attr_undup(&attr
, ain
->attr
);
10236 } else if (type
== bgp_show_adj_route_advertised
) {
10237 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10238 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10239 if (paf
->peer
!= peer
|| !adj
->attr
)
10244 json_object_int_add(
10248 json_object_string_add(
10250 "bgpLocalRouterId",
10253 json_object_object_add(
10257 json_object_object_add(
10263 "BGP table version is %" PRIu64
10264 ", local router ID is %s, vrf id ",
10277 vty_out(vty
, "\n");
10279 BGP_SHOW_SCODE_HEADER
);
10281 BGP_SHOW_NCODE_HEADER
);
10283 BGP_SHOW_OCODE_HEADER
);
10294 bgp_attr_dup(&attr
, adj
->attr
);
10295 ret
= bgp_output_modifier(
10296 peer
, &rn
->p
, &attr
, afi
, safi
,
10299 if (ret
!= RMAP_DENY
) {
10300 route_vty_out_tmp(vty
, &rn
->p
,
10309 bgp_attr_undup(&attr
, adj
->attr
);
10315 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10316 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10317 json_object_int_add(json
, "filteredPrefixCounter",
10320 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10321 json
, JSON_C_TO_STRING_PRETTY
));
10322 json_object_free(json
);
10323 } else if (output_count
> 0) {
10324 if (filtered_count
> 0)
10326 "\nTotal number of prefixes %ld (%ld filtered)\n",
10327 output_count
, filtered_count
);
10329 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10334 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10335 safi_t safi
, enum bgp_show_adj_route_type type
,
10336 const char *rmap_name
, uint8_t use_json
)
10338 json_object
*json
= NULL
;
10341 json
= json_object_new_object();
10343 /* labeled-unicast routes live in the unicast table */
10344 if (safi
== SAFI_LABELED_UNICAST
)
10345 safi
= SAFI_UNICAST
;
10347 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10349 json_object_string_add(
10351 "No such neighbor or address family");
10352 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10353 json_object_free(json
);
10355 vty_out(vty
, "%% No such neighbor or address family\n");
10357 return CMD_WARNING
;
10360 if ((type
== bgp_show_adj_route_received
10361 || type
== bgp_show_adj_route_filtered
)
10362 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10363 PEER_FLAG_SOFT_RECONFIG
)) {
10365 json_object_string_add(
10367 "Inbound soft reconfiguration not enabled");
10368 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10369 json_object_free(json
);
10372 "%% Inbound soft reconfiguration not enabled\n");
10374 return CMD_WARNING
;
10377 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10379 return CMD_SUCCESS
;
10382 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10383 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10384 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10385 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10389 BGP_INSTANCE_HELP_STR
10391 BGP_SAFI_WITH_LABEL_HELP_STR
10392 "Detailed information on TCP and BGP neighbor connections\n"
10393 "Neighbor to display information about\n"
10394 "Neighbor to display information about\n"
10395 "Neighbor on BGP configured interface\n"
10396 "Display the routes advertised to a BGP neighbor\n"
10397 "Display the received routes from neighbor\n"
10398 "Display the filtered routes received from neighbor\n"
10399 "Route-map to modify the attributes\n"
10400 "Name of the route map\n"
10403 afi_t afi
= AFI_IP6
;
10404 safi_t safi
= SAFI_UNICAST
;
10405 char *rmap_name
= NULL
;
10406 char *peerstr
= NULL
;
10407 struct bgp
*bgp
= NULL
;
10409 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10412 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10415 return CMD_WARNING
;
10417 int uj
= use_json(argc
, argv
);
10422 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10423 argv_find(argv
, argc
, "neighbors", &idx
);
10424 peerstr
= argv
[++idx
]->arg
;
10426 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10428 return CMD_WARNING
;
10430 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10431 type
= bgp_show_adj_route_advertised
;
10432 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10433 type
= bgp_show_adj_route_received
;
10434 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10435 type
= bgp_show_adj_route_filtered
;
10437 if (argv_find(argv
, argc
, "route-map", &idx
))
10438 rmap_name
= argv
[++idx
]->arg
;
10440 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10443 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10444 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10445 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10451 "Address Family modifier\n"
10452 "Detailed information on TCP and BGP neighbor connections\n"
10453 "Neighbor to display information about\n"
10454 "Neighbor to display information about\n"
10455 "Neighbor on BGP configured interface\n"
10456 "Display information received from a BGP neighbor\n"
10457 "Display the prefixlist filter\n"
10460 afi_t afi
= AFI_IP6
;
10461 safi_t safi
= SAFI_UNICAST
;
10462 char *peerstr
= NULL
;
10465 union sockunion su
;
10471 /* show [ip] bgp */
10472 if (argv_find(argv
, argc
, "ip", &idx
))
10474 /* [<ipv4|ipv6> [unicast]] */
10475 if (argv_find(argv
, argc
, "ipv4", &idx
))
10477 if (argv_find(argv
, argc
, "ipv6", &idx
))
10479 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10480 argv_find(argv
, argc
, "neighbors", &idx
);
10481 peerstr
= argv
[++idx
]->arg
;
10483 uint8_t uj
= use_json(argc
, argv
);
10485 ret
= str2sockunion(peerstr
, &su
);
10487 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10490 vty_out(vty
, "{}\n");
10493 "%% Malformed address or name: %s\n",
10495 return CMD_WARNING
;
10498 peer
= peer_lookup(NULL
, &su
);
10501 vty_out(vty
, "{}\n");
10503 vty_out(vty
, "No peer\n");
10504 return CMD_WARNING
;
10508 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10509 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10512 vty_out(vty
, "Address Family: %s\n",
10513 afi_safi_print(afi
, safi
));
10514 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10517 vty_out(vty
, "{}\n");
10519 vty_out(vty
, "No functional output\n");
10522 return CMD_SUCCESS
;
10525 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10526 afi_t afi
, safi_t safi
,
10527 enum bgp_show_type type
, uint8_t use_json
)
10529 /* labeled-unicast routes live in the unicast table */
10530 if (safi
== SAFI_LABELED_UNICAST
)
10531 safi
= SAFI_UNICAST
;
10533 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10535 json_object
*json_no
= NULL
;
10536 json_no
= json_object_new_object();
10537 json_object_string_add(
10538 json_no
, "warning",
10539 "No such neighbor or address family");
10540 vty_out(vty
, "%s\n",
10541 json_object_to_json_string(json_no
));
10542 json_object_free(json_no
);
10544 vty_out(vty
, "%% No such neighbor or address family\n");
10545 return CMD_WARNING
;
10548 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10551 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10552 show_ip_bgp_flowspec_routes_detailed_cmd
,
10553 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10557 BGP_INSTANCE_HELP_STR
10560 "Detailed information on flowspec entries\n"
10563 afi_t afi
= AFI_IP
;
10564 safi_t safi
= SAFI_UNICAST
;
10565 struct bgp
*bgp
= NULL
;
10568 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10571 return CMD_WARNING
;
10573 return bgp_show(vty
, bgp
, afi
, safi
,
10574 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10577 DEFUN (show_ip_bgp_neighbor_routes
,
10578 show_ip_bgp_neighbor_routes_cmd
,
10579 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10580 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10584 BGP_INSTANCE_HELP_STR
10586 BGP_SAFI_WITH_LABEL_HELP_STR
10587 "Detailed information on TCP and BGP neighbor connections\n"
10588 "Neighbor to display information about\n"
10589 "Neighbor to display information about\n"
10590 "Neighbor on BGP configured interface\n"
10591 "Display flap statistics of the routes learned from neighbor\n"
10592 "Display the dampened routes received from neighbor\n"
10593 "Display routes learned from neighbor\n"
10596 char *peerstr
= NULL
;
10597 struct bgp
*bgp
= NULL
;
10598 afi_t afi
= AFI_IP6
;
10599 safi_t safi
= SAFI_UNICAST
;
10601 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10605 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10608 return CMD_WARNING
;
10610 int uj
= use_json(argc
, argv
);
10614 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10615 argv_find(argv
, argc
, "neighbors", &idx
);
10616 peerstr
= argv
[++idx
]->arg
;
10618 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10620 return CMD_WARNING
;
10622 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10623 sh_type
= bgp_show_type_flap_neighbor
;
10624 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10625 sh_type
= bgp_show_type_damp_neighbor
;
10626 else if (argv_find(argv
, argc
, "routes", &idx
))
10627 sh_type
= bgp_show_type_neighbor
;
10629 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10632 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10634 struct bgp_distance
{
10635 /* Distance value for the IP source prefix. */
10638 /* Name of the access-list to be matched. */
10642 DEFUN (show_bgp_afi_vpn_rd_route
,
10643 show_bgp_afi_vpn_rd_route_cmd
,
10644 "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]",
10648 "Address Family modifier\n"
10649 "Display information for a route distinguisher\n"
10650 "Route Distinguisher\n"
10651 "Network in the BGP routing table to display\n"
10652 "Network in the BGP routing table to display\n"
10656 struct prefix_rd prd
;
10657 afi_t afi
= AFI_MAX
;
10660 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10661 vty_out(vty
, "%% Malformed Address Family\n");
10662 return CMD_WARNING
;
10665 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10667 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10668 return CMD_WARNING
;
10671 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10672 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10675 static struct bgp_distance
*bgp_distance_new(void)
10677 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10680 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10682 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10685 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10686 const char *ip_str
, const char *access_list_str
)
10693 struct bgp_node
*rn
;
10694 struct bgp_distance
*bdistance
;
10696 afi
= bgp_node_afi(vty
);
10697 safi
= bgp_node_safi(vty
);
10699 ret
= str2prefix(ip_str
, &p
);
10701 vty_out(vty
, "Malformed prefix\n");
10702 return CMD_WARNING_CONFIG_FAILED
;
10705 distance
= atoi(distance_str
);
10707 /* Get BGP distance node. */
10708 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10710 bdistance
= rn
->info
;
10711 bgp_unlock_node(rn
);
10713 bdistance
= bgp_distance_new();
10714 rn
->info
= bdistance
;
10717 /* Set distance value. */
10718 bdistance
->distance
= distance
;
10720 /* Reset access-list configuration. */
10721 if (bdistance
->access_list
) {
10722 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10723 bdistance
->access_list
= NULL
;
10725 if (access_list_str
)
10726 bdistance
->access_list
=
10727 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10729 return CMD_SUCCESS
;
10732 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10733 const char *ip_str
, const char *access_list_str
)
10740 struct bgp_node
*rn
;
10741 struct bgp_distance
*bdistance
;
10743 afi
= bgp_node_afi(vty
);
10744 safi
= bgp_node_safi(vty
);
10746 ret
= str2prefix(ip_str
, &p
);
10748 vty_out(vty
, "Malformed prefix\n");
10749 return CMD_WARNING_CONFIG_FAILED
;
10752 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10753 (struct prefix
*)&p
);
10755 vty_out(vty
, "Can't find specified prefix\n");
10756 return CMD_WARNING_CONFIG_FAILED
;
10759 bdistance
= rn
->info
;
10760 distance
= atoi(distance_str
);
10762 if (bdistance
->distance
!= distance
) {
10763 vty_out(vty
, "Distance does not match configured\n");
10764 return CMD_WARNING_CONFIG_FAILED
;
10767 if (bdistance
->access_list
)
10768 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10769 bgp_distance_free(bdistance
);
10772 bgp_unlock_node(rn
);
10773 bgp_unlock_node(rn
);
10775 return CMD_SUCCESS
;
10778 /* Apply BGP information to distance method. */
10779 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10780 safi_t safi
, struct bgp
*bgp
)
10782 struct bgp_node
*rn
;
10785 struct bgp_distance
*bdistance
;
10786 struct access_list
*alist
;
10787 struct bgp_static
*bgp_static
;
10792 peer
= rinfo
->peer
;
10794 /* Check source address. */
10795 sockunion2hostprefix(&peer
->su
, &q
);
10796 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10798 bdistance
= rn
->info
;
10799 bgp_unlock_node(rn
);
10801 if (bdistance
->access_list
) {
10802 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10804 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10805 return bdistance
->distance
;
10807 return bdistance
->distance
;
10810 /* Backdoor check. */
10811 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10813 bgp_static
= rn
->info
;
10814 bgp_unlock_node(rn
);
10816 if (bgp_static
->backdoor
) {
10817 if (bgp
->distance_local
[afi
][safi
])
10818 return bgp
->distance_local
[afi
][safi
];
10820 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10824 if (peer
->sort
== BGP_PEER_EBGP
) {
10825 if (bgp
->distance_ebgp
[afi
][safi
])
10826 return bgp
->distance_ebgp
[afi
][safi
];
10827 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10829 if (bgp
->distance_ibgp
[afi
][safi
])
10830 return bgp
->distance_ibgp
[afi
][safi
];
10831 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10835 DEFUN (bgp_distance
,
10837 "distance bgp (1-255) (1-255) (1-255)",
10838 "Define an administrative distance\n"
10840 "Distance for routes external to the AS\n"
10841 "Distance for routes internal to the AS\n"
10842 "Distance for local routes\n")
10844 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10845 int idx_number
= 2;
10846 int idx_number_2
= 3;
10847 int idx_number_3
= 4;
10851 afi
= bgp_node_afi(vty
);
10852 safi
= bgp_node_safi(vty
);
10854 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10855 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10856 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10857 return CMD_SUCCESS
;
10860 DEFUN (no_bgp_distance
,
10861 no_bgp_distance_cmd
,
10862 "no distance bgp [(1-255) (1-255) (1-255)]",
10864 "Define an administrative distance\n"
10866 "Distance for routes external to the AS\n"
10867 "Distance for routes internal to the AS\n"
10868 "Distance for local routes\n")
10870 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10874 afi
= bgp_node_afi(vty
);
10875 safi
= bgp_node_safi(vty
);
10877 bgp
->distance_ebgp
[afi
][safi
] = 0;
10878 bgp
->distance_ibgp
[afi
][safi
] = 0;
10879 bgp
->distance_local
[afi
][safi
] = 0;
10880 return CMD_SUCCESS
;
10884 DEFUN (bgp_distance_source
,
10885 bgp_distance_source_cmd
,
10886 "distance (1-255) A.B.C.D/M",
10887 "Define an administrative distance\n"
10888 "Administrative distance\n"
10889 "IP source prefix\n")
10891 int idx_number
= 1;
10892 int idx_ipv4_prefixlen
= 2;
10893 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10894 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10895 return CMD_SUCCESS
;
10898 DEFUN (no_bgp_distance_source
,
10899 no_bgp_distance_source_cmd
,
10900 "no distance (1-255) A.B.C.D/M",
10902 "Define an administrative distance\n"
10903 "Administrative distance\n"
10904 "IP source prefix\n")
10906 int idx_number
= 2;
10907 int idx_ipv4_prefixlen
= 3;
10908 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10909 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10910 return CMD_SUCCESS
;
10913 DEFUN (bgp_distance_source_access_list
,
10914 bgp_distance_source_access_list_cmd
,
10915 "distance (1-255) A.B.C.D/M WORD",
10916 "Define an administrative distance\n"
10917 "Administrative distance\n"
10918 "IP source prefix\n"
10919 "Access list name\n")
10921 int idx_number
= 1;
10922 int idx_ipv4_prefixlen
= 2;
10924 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10925 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10926 return CMD_SUCCESS
;
10929 DEFUN (no_bgp_distance_source_access_list
,
10930 no_bgp_distance_source_access_list_cmd
,
10931 "no distance (1-255) A.B.C.D/M WORD",
10933 "Define an administrative distance\n"
10934 "Administrative distance\n"
10935 "IP source prefix\n"
10936 "Access list name\n")
10938 int idx_number
= 2;
10939 int idx_ipv4_prefixlen
= 3;
10941 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10942 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10943 return CMD_SUCCESS
;
10946 DEFUN (ipv6_bgp_distance_source
,
10947 ipv6_bgp_distance_source_cmd
,
10948 "distance (1-255) X:X::X:X/M",
10949 "Define an administrative distance\n"
10950 "Administrative distance\n"
10951 "IP source prefix\n")
10953 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10954 return CMD_SUCCESS
;
10957 DEFUN (no_ipv6_bgp_distance_source
,
10958 no_ipv6_bgp_distance_source_cmd
,
10959 "no distance (1-255) X:X::X:X/M",
10961 "Define an administrative distance\n"
10962 "Administrative distance\n"
10963 "IP source prefix\n")
10965 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10966 return CMD_SUCCESS
;
10969 DEFUN (ipv6_bgp_distance_source_access_list
,
10970 ipv6_bgp_distance_source_access_list_cmd
,
10971 "distance (1-255) X:X::X:X/M WORD",
10972 "Define an administrative distance\n"
10973 "Administrative distance\n"
10974 "IP source prefix\n"
10975 "Access list name\n")
10977 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10978 return CMD_SUCCESS
;
10981 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10982 no_ipv6_bgp_distance_source_access_list_cmd
,
10983 "no distance (1-255) X:X::X:X/M WORD",
10985 "Define an administrative distance\n"
10986 "Administrative distance\n"
10987 "IP source prefix\n"
10988 "Access list name\n")
10990 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10991 return CMD_SUCCESS
;
10994 DEFUN (bgp_damp_set
,
10996 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10997 "BGP Specific commands\n"
10998 "Enable route-flap dampening\n"
10999 "Half-life time for the penalty\n"
11000 "Value to start reusing a route\n"
11001 "Value to start suppressing a route\n"
11002 "Maximum duration to suppress a stable route\n")
11004 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11005 int idx_half_life
= 2;
11007 int idx_suppress
= 4;
11008 int idx_max_suppress
= 5;
11009 int half
= DEFAULT_HALF_LIFE
* 60;
11010 int reuse
= DEFAULT_REUSE
;
11011 int suppress
= DEFAULT_SUPPRESS
;
11012 int max
= 4 * half
;
11015 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11016 reuse
= atoi(argv
[idx_reuse
]->arg
);
11017 suppress
= atoi(argv
[idx_suppress
]->arg
);
11018 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11019 } else if (argc
== 3) {
11020 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11024 if (suppress
< reuse
) {
11026 "Suppress value cannot be less than reuse value \n");
11030 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11031 reuse
, suppress
, max
);
11034 DEFUN (bgp_damp_unset
,
11035 bgp_damp_unset_cmd
,
11036 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11038 "BGP Specific commands\n"
11039 "Enable route-flap dampening\n"
11040 "Half-life time for the penalty\n"
11041 "Value to start reusing a route\n"
11042 "Value to start suppressing a route\n"
11043 "Maximum duration to suppress a stable route\n")
11045 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11046 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11049 /* Display specified route of BGP table. */
11050 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11051 const char *ip_str
, afi_t afi
, safi_t safi
,
11052 struct prefix_rd
*prd
, int prefix_check
)
11055 struct prefix match
;
11056 struct bgp_node
*rn
;
11057 struct bgp_node
*rm
;
11058 struct bgp_info
*ri
;
11059 struct bgp_info
*ri_temp
;
11061 struct bgp_table
*table
;
11063 /* BGP structure lookup. */
11065 bgp
= bgp_lookup_by_name(view_name
);
11067 vty_out(vty
, "%% Can't find BGP instance %s\n",
11069 return CMD_WARNING
;
11072 bgp
= bgp_get_default();
11074 vty_out(vty
, "%% No BGP process is configured\n");
11075 return CMD_WARNING
;
11079 /* Check IP address argument. */
11080 ret
= str2prefix(ip_str
, &match
);
11082 vty_out(vty
, "%% address is malformed\n");
11083 return CMD_WARNING
;
11086 match
.family
= afi2family(afi
);
11088 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11089 || (safi
== SAFI_EVPN
)) {
11090 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11091 rn
= bgp_route_next(rn
)) {
11092 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11094 if ((table
= rn
->info
) == NULL
)
11096 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11100 || rm
->p
.prefixlen
== match
.prefixlen
) {
11103 if (ri
->extra
&& ri
->extra
->damp_info
) {
11104 ri_temp
= ri
->next
;
11105 bgp_damp_info_free(
11106 ri
->extra
->damp_info
,
11114 bgp_unlock_node(rm
);
11117 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11120 || rn
->p
.prefixlen
== match
.prefixlen
) {
11123 if (ri
->extra
&& ri
->extra
->damp_info
) {
11124 ri_temp
= ri
->next
;
11125 bgp_damp_info_free(
11126 ri
->extra
->damp_info
,
11134 bgp_unlock_node(rn
);
11138 return CMD_SUCCESS
;
11141 DEFUN (clear_ip_bgp_dampening
,
11142 clear_ip_bgp_dampening_cmd
,
11143 "clear ip bgp dampening",
11147 "Clear route flap dampening information\n")
11149 bgp_damp_info_clean();
11150 return CMD_SUCCESS
;
11153 DEFUN (clear_ip_bgp_dampening_prefix
,
11154 clear_ip_bgp_dampening_prefix_cmd
,
11155 "clear ip bgp dampening A.B.C.D/M",
11159 "Clear route flap dampening information\n"
11162 int idx_ipv4_prefixlen
= 4;
11163 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11164 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11167 DEFUN (clear_ip_bgp_dampening_address
,
11168 clear_ip_bgp_dampening_address_cmd
,
11169 "clear ip bgp dampening A.B.C.D",
11173 "Clear route flap dampening information\n"
11174 "Network to clear damping information\n")
11177 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11178 SAFI_UNICAST
, NULL
, 0);
11181 DEFUN (clear_ip_bgp_dampening_address_mask
,
11182 clear_ip_bgp_dampening_address_mask_cmd
,
11183 "clear ip bgp dampening A.B.C.D A.B.C.D",
11187 "Clear route flap dampening information\n"
11188 "Network to clear damping information\n"
11192 int idx_ipv4_2
= 5;
11194 char prefix_str
[BUFSIZ
];
11196 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11199 vty_out(vty
, "%% Inconsistent address and mask\n");
11200 return CMD_WARNING
;
11203 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11207 /* also used for encap safi */
11208 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11209 afi_t afi
, safi_t safi
)
11211 struct bgp_node
*prn
;
11212 struct bgp_node
*rn
;
11213 struct bgp_table
*table
;
11215 struct prefix_rd
*prd
;
11216 struct bgp_static
*bgp_static
;
11217 mpls_label_t label
;
11218 char buf
[SU_ADDRSTRLEN
];
11219 char rdbuf
[RD_ADDRSTRLEN
];
11221 /* Network configuration. */
11222 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11223 prn
= bgp_route_next(prn
)) {
11224 if ((table
= prn
->info
) == NULL
)
11227 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11228 if ((bgp_static
= rn
->info
) == NULL
)
11232 prd
= (struct prefix_rd
*)&prn
->p
;
11234 /* "network" configuration display. */
11235 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11236 label
= decode_label(&bgp_static
->label
);
11238 vty_out(vty
, " network %s/%d rd %s",
11239 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11241 p
->prefixlen
, rdbuf
);
11242 if (safi
== SAFI_MPLS_VPN
)
11243 vty_out(vty
, " label %u", label
);
11245 if (bgp_static
->rmap
.name
)
11246 vty_out(vty
, " route-map %s",
11247 bgp_static
->rmap
.name
);
11249 if (bgp_static
->backdoor
)
11250 vty_out(vty
, " backdoor");
11252 vty_out(vty
, "\n");
11257 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11258 afi_t afi
, safi_t safi
)
11260 struct bgp_node
*prn
;
11261 struct bgp_node
*rn
;
11262 struct bgp_table
*table
;
11264 struct prefix_rd
*prd
;
11265 struct bgp_static
*bgp_static
;
11266 char buf
[PREFIX_STRLEN
* 2];
11267 char buf2
[SU_ADDRSTRLEN
];
11268 char rdbuf
[RD_ADDRSTRLEN
];
11270 /* Network configuration. */
11271 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11272 prn
= bgp_route_next(prn
)) {
11273 if ((table
= prn
->info
) == NULL
)
11276 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11277 if ((bgp_static
= rn
->info
) == NULL
)
11280 char *macrouter
= NULL
;
11283 if (bgp_static
->router_mac
)
11284 macrouter
= prefix_mac2str(
11285 bgp_static
->router_mac
, NULL
, 0);
11286 if (bgp_static
->eth_s_id
)
11287 esi
= esi2str(bgp_static
->eth_s_id
);
11289 prd
= (struct prefix_rd
*)&prn
->p
;
11291 /* "network" configuration display. */
11292 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11293 if (p
->u
.prefix_evpn
.route_type
== 5) {
11294 char local_buf
[PREFIX_STRLEN
];
11295 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11296 struct prefix_evpn
*)p
)
11300 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11301 local_buf
, PREFIX_STRLEN
);
11302 sprintf(buf
, "%s/%u", local_buf
,
11303 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11305 prefix2str(p
, buf
, sizeof(buf
));
11308 if (bgp_static
->gatewayIp
.family
== AF_INET
11309 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11310 inet_ntop(bgp_static
->gatewayIp
.family
,
11311 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11314 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11316 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11317 decode_label(&bgp_static
->label
), esi
, buf2
,
11321 XFREE(MTYPE_TMP
, macrouter
);
11323 XFREE(MTYPE_TMP
, esi
);
11328 /* Configuration of static route announcement and aggregate
11330 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11333 struct bgp_node
*rn
;
11335 struct bgp_static
*bgp_static
;
11336 struct bgp_aggregate
*bgp_aggregate
;
11337 char buf
[SU_ADDRSTRLEN
];
11339 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11340 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11344 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11345 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11349 /* Network configuration. */
11350 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11351 rn
= bgp_route_next(rn
)) {
11352 if ((bgp_static
= rn
->info
) == NULL
)
11357 /* "network" configuration display. */
11358 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11359 uint32_t destination
;
11360 struct in_addr netmask
;
11362 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11363 masklen2ip(p
->prefixlen
, &netmask
);
11364 vty_out(vty
, " network %s",
11365 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11368 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11369 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11370 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11371 || p
->u
.prefix4
.s_addr
== 0) {
11372 /* Natural mask is not display. */
11374 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11376 vty_out(vty
, " network %s/%d",
11377 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11382 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11383 vty_out(vty
, " label-index %u",
11384 bgp_static
->label_index
);
11386 if (bgp_static
->rmap
.name
)
11387 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11389 if (bgp_static
->backdoor
)
11390 vty_out(vty
, " backdoor");
11392 vty_out(vty
, "\n");
11395 /* Aggregate-address configuration. */
11396 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11397 rn
= bgp_route_next(rn
)) {
11398 if ((bgp_aggregate
= rn
->info
) == NULL
)
11403 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11404 struct in_addr netmask
;
11406 masklen2ip(p
->prefixlen
, &netmask
);
11407 vty_out(vty
, " aggregate-address %s %s",
11408 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11410 inet_ntoa(netmask
));
11412 vty_out(vty
, " aggregate-address %s/%d",
11413 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11418 if (bgp_aggregate
->as_set
)
11419 vty_out(vty
, " as-set");
11421 if (bgp_aggregate
->summary_only
)
11422 vty_out(vty
, " summary-only");
11424 vty_out(vty
, "\n");
11428 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11431 struct bgp_node
*rn
;
11432 struct bgp_distance
*bdistance
;
11434 /* Distance configuration. */
11435 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11436 && bgp
->distance_local
[afi
][safi
]
11437 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11438 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11439 || bgp
->distance_local
[afi
][safi
]
11440 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11441 vty_out(vty
, " distance bgp %d %d %d\n",
11442 bgp
->distance_ebgp
[afi
][safi
],
11443 bgp
->distance_ibgp
[afi
][safi
],
11444 bgp
->distance_local
[afi
][safi
]);
11447 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11448 rn
= bgp_route_next(rn
))
11449 if ((bdistance
= rn
->info
) != NULL
) {
11450 char buf
[PREFIX_STRLEN
];
11452 vty_out(vty
, " distance %d %s %s\n",
11453 bdistance
->distance
,
11454 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11455 bdistance
->access_list
? bdistance
->access_list
11460 /* Allocate routing table structure and install commands. */
11461 void bgp_route_init(void)
11466 /* Init BGP distance table. */
11467 FOREACH_AFI_SAFI (afi
, safi
)
11468 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11470 /* IPv4 BGP commands. */
11471 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11472 install_element(BGP_NODE
, &bgp_network_cmd
);
11473 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11475 install_element(BGP_NODE
, &aggregate_address_cmd
);
11476 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11477 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11478 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11480 /* IPv4 unicast configuration. */
11481 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11482 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11483 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11485 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11486 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11487 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11488 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11490 /* IPv4 multicast configuration. */
11491 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11492 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11493 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11494 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11495 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11496 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11497 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11499 /* IPv4 labeled-unicast configuration. */
11500 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11501 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11502 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11503 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11504 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11506 install_element(VIEW_NODE
,
11507 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11508 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11509 install_element(VIEW_NODE
,
11510 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11511 #ifdef KEEP_OLD_VPN_COMMANDS
11512 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11513 #endif /* KEEP_OLD_VPN_COMMANDS */
11514 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11515 install_element(VIEW_NODE
,
11516 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11518 /* BGP dampening clear commands */
11519 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11520 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11522 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11523 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11526 install_element(ENABLE_NODE
,
11527 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11528 #ifdef KEEP_OLD_VPN_COMMANDS
11529 install_element(ENABLE_NODE
,
11530 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11531 #endif /* KEEP_OLD_VPN_COMMANDS */
11533 /* New config IPv6 BGP commands. */
11534 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11535 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11536 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11538 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11539 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11541 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11543 install_element(BGP_NODE
, &bgp_distance_cmd
);
11544 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11545 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11546 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11547 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11548 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11549 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11550 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11551 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11552 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11553 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11554 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11555 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11556 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11557 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11558 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11559 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11560 install_element(BGP_IPV4M_NODE
,
11561 &no_bgp_distance_source_access_list_cmd
);
11562 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11563 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11564 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11565 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11566 install_element(BGP_IPV6_NODE
,
11567 &ipv6_bgp_distance_source_access_list_cmd
);
11568 install_element(BGP_IPV6_NODE
,
11569 &no_ipv6_bgp_distance_source_access_list_cmd
);
11570 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11571 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11572 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11573 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11574 install_element(BGP_IPV6M_NODE
,
11575 &ipv6_bgp_distance_source_access_list_cmd
);
11576 install_element(BGP_IPV6M_NODE
,
11577 &no_ipv6_bgp_distance_source_access_list_cmd
);
11579 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11580 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11581 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11582 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11584 /* IPv4 Multicast Mode */
11585 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11586 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11588 /* Large Communities */
11589 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11590 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11592 /* show bgp ipv4 flowspec detailed */
11593 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11597 void bgp_route_finish(void)
11602 FOREACH_AFI_SAFI (afi
, safi
) {
11603 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11604 bgp_distance_table
[afi
][safi
] = NULL
;